提交 f857126c 编写于 作者: S stdrickforce 提交者: yapu.wang

[Python][3.1.0] Support fork

上级 dea7993c
FROM alpine:latest
MAINTAINER Terence Fan <stdrickforce@gmail.com>
RUN mkdir -p /tmp/ccat
COPY . /tmp/ccat
WORKDIR /tmp
RUN apk add cmake make g++ linux-headers
WORKDIR /tmp/ccat
RUN mkdir -p cmake && cd cmake && make -j && make install
src/cat/lib/
\ No newline at end of file
......@@ -32,7 +32,7 @@ classifiers = [
setup(
name='cat-sdk',
version='3.0.1',
version='3.1.0',
author='Cat Team and Contributors',
author_email='cat@dianping.com',
url="https://github.com/dianping/cat/",
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: stdrickforce (Tengyuan Fan)
# Email: <stdrickforce@gmail.com>
# Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved.
#
# Licensed to the Apache Software Foundation (ASF) under one or more
......@@ -15,9 +21,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# !/usr/bin/env python
# -*- coding: utf-8 -*-
__all__ = ['init', 'CAT_SUCCESS', 'CAT_ERROR']
import logging
......@@ -32,7 +35,6 @@ from .container import container
from .sdk import (
catSdk as catSdkDefault,
catSdkCoroutine,
)
log = logging.getLogger()
......@@ -42,9 +44,5 @@ log = logging.getLogger()
def init(appkey, **kwargs):
if container.contains("catsdk"):
log.warning("cat sdk has already been initialized!")
if kwargs.get("logview", True) is False:
sdk = catSdkCoroutine(appkey, **kwargs)
else:
sdk = catSdkDefault(appkey, **kwargs)
sdk = catSdkDefault(appkey, **kwargs)
container.put("catsdk", sdk)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: stdrickforce (Tengyuan Fan)
# Email: <stdrickforce@gmail.com>
# Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved.
#
# Licensed to the Apache Software Foundation (ASF) under one or more
......@@ -65,6 +71,7 @@ typedef struct _CatClientConfig {
int enableSampling;
int enableMultiprocessing;
int enableDebugLog;
int enableAutoInitialize;
} CatClientConfig;
"""
......@@ -85,7 +92,6 @@ ffi.cdef("void logError(const char *msg, const char *errStr);")
# heartbeat apis.
ffi.cdef("CatHeartBeat *newHeartBeat(const char *type, const char *name);")
# metric apis.
ffi.cdef("void logMetricForCount(const char *name, int quantity);")
ffi.cdef("void logMetricForDuration(const char *name, unsigned long long durationMs);")
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: stdrickforce (Tengyuan Fan)
# Email: <stdrickforce@gmail.com>
# Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved.
#
# Licensed to the Apache Software Foundation (ASF) under one or more
......@@ -15,9 +21,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from .container import sdk
......
......@@ -28,8 +28,8 @@ import time
from .catffi import ffi
from .const import (
CAT_SUCCESS,
ENCODER_BINARY,
CAT_SUCCESS
)
from .version import _
......@@ -38,154 +38,113 @@ log = logging.getLogger()
__all__ = ['catSdk']
class catSdk(object):
def load_ccat():
path = os.path.dirname(os.path.abspath(__file__))
if 'Linux' in platform.system():
if platform.libc_ver()[0] == 'glibc':
return ffi.dlopen(os.path.join(path, "lib/linux-glibc/libcatclient.so"))
else:
return ffi.dlopen(os.path.join(path, "lib/linux-musl-libc/libcatclient.so"))
elif 'Darwin' in platform.system():
return ffi.dlopen(os.path.join(path, "lib/darwin/libcatclient.dylib"))
else:
log.error("pycat can only run on the Linux/Darwin platform.")
return
def __init__(self, appkey, **kwargs):
path = os.path.dirname(os.path.abspath(__file__))
if 'Linux' in platform.system():
if platform.libc_ver()[0] == 'glibc':
self.cat = ffi.dlopen(
os.path.join(path, "lib/linux-glibc/libcatclient.so")
)
else:
self.cat = ffi.dlopen(
os.path.join(path, "lib/linux-musl-libc/libcatclient.so")
)
elif 'Darwin' in platform.system():
self.cat = ffi.dlopen(
os.path.join(path, "lib/darwin/libcatclient.dylib")
)
ccat = load_ccat()
class PyTransaction(object):
def __init__(self, mtype, mname):
self._mtype = mtype
self._mname = mname
self._status = CAT_SUCCESS
self._data = ""
self._duration = None
self._time = int(time.time() * 1000)
self._start = self._time
def setStatus(self, t, status):
self._status = status
def setTimestamp(self, t, timestamp):
self._time = timestamp
def setDurationInMillis(self, t, duration):
self._duration = duration
def setDurationStart(self, t, durationStart):
self._start = durationStart
def addData(self, t, data):
if self._data == "":
self._data = data
else:
log.error("pycat can only run on the Linux/Darwin platform.")
return
self._data += "&" + data
def addKV(self, t, key, val):
if self._data == "":
self._data = "{}={}".format(key, val)
else:
self._data += "&{}={}".format(key, val)
def complete(self, t):
t = ccat.newTransaction(_(self._mtype), _(self._mname))
try:
t.setStatus(t, _(self._status))
t.setTimestamp(t, self._time)
t.setDurationInMillis(t, self._duration_ms)
t.addData(t, _(self._data))
finally:
t.complete(t)
@property
def _duration_ms(self):
if self._duration is None:
return int(time.time() * 1000 - self._start)
return self._duration
class catSdk(object):
def __init__(self, appkey, **kwargs):
self.appkey = appkey
self.__init_ccat(**kwargs)
def __init_ccat(self, encoder=ENCODER_BINARY, sampling=True, debug=False, logview=True):
def __init_ccat(self, encoder=ENCODER_BINARY, sampling=True, debug=False, logview=True, auto_init=False):
self._logview = logview
config = ffi.new("CatClientConfig*", [
encoder, # encoder
0, # heartbeat
int(sampling), # sampling
1, # multiprocessing
1 if debug else 0, # debug log
encoder, # encoder
0, # heartbeat
int(sampling), # sampling
1, # multiprocessing
1 if debug else 0, # debug log
1 if auto_init else 0, # auto initialize
])
self.cat.catClientInitWithConfig(_(self.appkey), config)
ccat.catClientInitWithConfig(_(self.appkey), config)
def new_transaction(self, type, name):
return self.cat.newTransaction(_(type), _(name))
if not self._logview:
return PyTransaction(type, name)
return ccat.newTransaction(_(type), _(name))
def new_heartbeat(self, type, name):
return self.cat.newHeartBeat(_(type), _(name))
return ccat.newHeartBeat(_(type), _(name))
def log_event(self, mtype, mname, status, nameValuePairs):
self.cat.logEvent(_(mtype), _(mname), _(status), _(nameValuePairs))
ccat.logEvent(_(mtype), _(mname), _(status), _(nameValuePairs))
def log_error(self, msg, err_stack):
self.cat.logError(_(msg), _(err_stack))
ccat.logError(_(msg), _(err_stack))
def log_metric_for_count(self, name, count=1):
self.cat.logMetricForCount(_(name), count)
ccat.logMetricForCount(_(name), count)
def log_metric_for_duration(self, name, duration_ms):
self.cat.logMetricForDuration(_(name), duration_ms)
def _add_transaction_data(self, t, data):
'''
It's a temporary api, don't use it in your code!
'''
t.addData(t, _(data))
def _add_transaction_kv(self, t, key, val):
'''
It's a temporary api, don't use it in your code!
'''
t.addKV(t, _(key), _(val))
ccat.logMetricForDuration(_(name), duration_ms)
class catSdkCoroutine(catSdk):
'''
This is a wrapper of catSdk.
We don't create a ccat Transaction struct but a pycat Transaction instead.
All the properties are cached in the pycat object.
'''
class Transaction:
def __init__(self, sdk, mtype, mname):
self._sdk = sdk
self._type = _(mtype)
self._name = _(mname)
self._status = _(CAT_SUCCESS)
self._data = ""
self._timestamp = time.time() * 1000
self._duration = None
self._duration_start = self._timestamp
@property
def type(self):
return self._type
@property
def name(self):
return self._name
@property
def status(self):
return self._status
@property
def data(self):
return self._data
def setStatus(self, t, status):
self._status = status
def addData(self, t, data):
if self._data == "":
self._data = data
else:
self._data += "&" + data
def addKV(self, t, key, val):
if self._data == "":
self._data = "{}={}".format(key, val)
else:
self._data += "&{}={}".format(key, val)
def setDurationInMillis(self, t, duration):
self._duration = duration
def setDurationStart(self, t, timestamp):
self._duration_start = timestamp
def setTimestamp(self, t, timestamp):
self._timestamp = timestamp
def complete(self, trans):
if self._duration is None:
duration = time.time() * 1000 - self._duration_start
else:
duration = self._duration
t = self._sdk.cat.newTransaction(self.type, self.name)
t.setStatus(t, self.status)
t.setTimestamp(t, int(self._timestamp))
t.setDurationInMillis(t, int(duration))
t.addData(t, _(self.data))
t.complete(t)
def new_transaction(self, type, name):
return self.Transaction(self, type, name)
def _add_transaction_data(self, t, data):
'''
It's a temporary api, don't use it in your code!
'''
t.addData(t, data)
def _add_transaction_kv(self, t, key, val):
'''
It's a temporary api, don't use it in your code!
'''
t.addKV(t, key, val)
pass
......@@ -28,6 +28,7 @@ from .const import CAT_ERROR
from .container import sdk
from .event import log_exception
from .message import NullMessage
from .sdk import PyTransaction
from .version import _
__all__ = ['Transaction', 'transaction']
......@@ -37,6 +38,7 @@ class Transaction(NullMessage):
def __init__(self, mtype, mname):
self._trans = sdk().new_transaction(mtype, mname)
self._py = isinstance(self._trans, PyTransaction)
self._completed = False
def complete(self):
......@@ -46,14 +48,29 @@ class Transaction(NullMessage):
return self
def set_status(self, status):
self._trans.setStatus(self._trans, _(status))
if self._py:
self._trans.setStatus(self._trans, status)
else:
self._trans.setStatus(self._trans, _(status))
return self
def __add_data(self, data):
if self._py:
self._trans.addData(self._trans, data)
else:
self._trans.addData(self._trans, _(data))
def __add_kv(self, key, val):
if self._py:
self._trans.addKV(self._trans, key, val)
else:
self._trans.addKV(self._trans, _(key), _(val))
def add_data(self, data, val=None):
if val is None:
sdk()._add_transaction_data(self._trans, data)
self.__add_data(data)
else:
sdk()._add_transaction_kv(self._trans, data, val)
self.__add_kv(data, val)
return self
def set_duration(self, duration):
......
......@@ -21,6 +21,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import cffi
import sys
PY2 = False
......@@ -32,10 +33,10 @@ else:
PY2 = True
if PY3:
from .catffi import ffi
ffi = cffi.FFI()
def _(x):
return ffi.new("char[]", x.encode("utf-8"))
else:
def _(x):
return x.encode('utf-8') if isinstance(x, unicode) else x # noqa
return x.encode('utf-8') if isinstance(x, unicode) else x
......@@ -25,6 +25,7 @@ def serve(method, args):
with cat.Transaction("serve", method) as t:
try:
t.add_data(json.dumps(args))
t.add_data("foo", "bar")
cat.log_event("hook", "before1")
cat.log_event("hook", "before2")
cat.log_event("hook", "before3")
......@@ -37,7 +38,7 @@ def serve(method, args):
if __name__ == '__main__':
cat.init("pycat", logview=False)
cat.init("pycat", logview=True)
while True:
try:
serve('ping', ["a", {"b": 1}])
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: stdrickforce (Tengyuan Fan)
# Email: <stdrickforce@gmail.com> <fantengyuan@baixing.com>
import cat
import time
def test2():
'''
Use with context manager
'''
with cat.Transaction("Transaction", "test2") as trans:
trans.set_status(cat.CAT_ERROR)
cat.log_event("h", "v")
trans.add_data("a=1")
trans.add_data("b=2")
if __name__ == '__main__':
cat.switch(cat.MODE_COROUTINE)
cat.init("pycat")
for i in range(1000):
print(i)
test2()
time.sleep(1)
......@@ -19,27 +19,12 @@ def test3():
cat.metric("metric2").duration(152)
def test4():
cat.metric("metric3").add_tag("color", "red").count()
cat.metric("metric3").add_tag("color", "yellow").count()
cat.metric("metric3").add_tag("color", "blue").count()
def test5():
cat.metric("metric4").add_tag(
"color", "red").add_tag("category", "hat").count()
cat.metric("metric4").add_tag("color", "red").add_tag(
"category", "glass").count()
if __name__ == "__main__":
cat.init("pycat")
for i in range(1000):
test1()
test2()
test3()
test4()
test5()
import time
time.sleep(1)
......@@ -4,6 +4,7 @@
# Author: stdrickforce (Tengyuan Fan)
# Email: <stdrickforce@gmail.com> <fantengyuan@baixing.com>
import argparse
import cat
import time
......@@ -61,7 +62,12 @@ def test3():
if __name__ == '__main__':
cat.init("pycat", debug=True, logview=False)
parser = argparse.ArgumentParser()
parser.add_argument('--logview', action='store_true', default=False)
args = parser.parse_args()
cat.init("pycat", debug=True, logview=args.logview)
for i in range(100):
test1()
test2()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册