Python - APM 链路跟踪探针之DDtrace

柯唯
2023-12-01

Python - APM 链路跟踪探针之DDtrace

Max.Bai
2021-03

APM (Application Performance Management),也叫链路跟踪系统,比较熟悉的有Pinpoint, SkyWalking,Zipkin等,系统简单来说由负责收集数据的探针和数据展示分析两部分组成,这个DDtrace就是python的探针。
DDtrace 是DataDog开源的python探针,官网地址 https://docs.datadoghq.com/tracing/setup_overview/compatibility_requirements/python/, 兼容大部分WEB框架,Flask,Django等等。

这里就测试一个Flask的Demo,看看收集到什么数据。

 

测试的方法是写一个flask demo 引入ddtrace,看如何工作,改动是不是很大,同时开另外一个flask数据收集器,让ddtrace把数据发到数据收集器,打印出来看看。


0. 安装

pip install ddtrace


1. 被监控Flask代码

内容简单,根路由,调用另外方法,并返回字符串

# ddtrace test    flaskserver.py
# 设置ddtrace
from ddtrace import patch_all, tracer

patch_all()
 # 数据收集服务器地址配置
tracer.configure(
    hostname="localhost",
    port="5001",
)


# flask 服务代码
import time
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    a = call_other_function_test()   # 调用非路由方法
    return a

@tracer.wrap()       # 非路由方法需要添加这个才可以收集数据
def call_other_function_test():
    print('call test')
    time.sleep(0.5)
    ab=5/0
    return "hello world, from other func!"



if __name__ == '__main__':
    app.run()


2. 数据收集服务器代码

很简单,就是要实现指定的路由地址就可以,我测试的版本是下面2个路由,内容一样的,就是打印收的数据。

/v0.4/traces
/v0.3/traces

# dataserver.py

from flask import Flask, request
import json
import msgpack

app = Flask(__name__)


@app.route("/v0.4/traces", methods=["GET", "POST", "PUT", "DELETE"])
def hello_world():
    print("0.4 data")
    print(request.headers)
    # print(request.get_data(as_text=True))
    # data = json.loads(request.get_data())
    data = msgpack.loads(request.get_data())
    # print(data)
    for item in data:
        print(item)

    return "Hello, World!"


@app.route("/v0.3/traces", methods=["GET", "POST", "PUT", "DELETE"])
def hello_world2():
    print("0.3 data")
    print(request.args)
    print(request.form.to_dict())
    for k in request.form:
        print(k, request.form.get(k))

    return "Hello, World!"


if __name__ == "__main__":
    app.run(port=5001, debug=True)

3. 开启被监控服务和数据收集服务

# 开启业务服务

python  flaskserver.py



# 开启数据收集服务

python dataserver.py

4. 访问被监控系统

访问后被监控系统,也就是我们的业务系统可正常工作,被访问的同时,访问数据就会发送到数据收集系统。
下面是我收到的数据。数据是个列表,列表包含每个节点的tarceid,父节点id,spanid,开始时间,duration等,这些数据足以用来绘制每个请求的链路和没个链路节点的性能信息了。

[
    {
        "trace_id": 6313747751933285704,
        "parent_id": None,
        "span_id": 14675715570392257531,
        "service": "flask",
        "resource": "GET /",
        "name": "flask.request",
        "error": 1,
        "start": 1615196507001553400,
        "duration": 518051800,
        "type": "web",
        "meta": {
            "runtime-id": "9d625dad17ab4244b4fdcd7c68069836",
            "flask.version": "1.1.2",
            "http.method": "GET",
            "http.url": "http://localhost:5000/",
            "flask.endpoint": "hello_world",
            "flask.url_rule": "/",
            "http.status_code": "500",
        },
        "metrics": {
            "system.pid": 278664,
            "_dd.agent_psr": 1.0,
            "_dd.measured": 1,
            "_sampling_priority_v1": 1,
            "_dd.tracer_kr": 1.0,
        },
    },
    {
        "trace_id": 6313747751933285704,
        "parent_id": 14675715570392257531,
        "span_id": 4248290624676178390,
        "service": "flask",
        "resource": "flask.try_trigger_before_first_request_functions",
        "name": "flask.try_trigger_before_first_request_functions",
        "error": 0,
        "start": 1615196507002553500,
        "duration": 0,
    },
    {
        "trace_id": 6313747751933285704,
        "parent_id": 14675715570392257531,
        "span_id": 12169504212513294621,
        "service": "flask",
        "resource": "flask.preprocess_request",
        "name": "flask.preprocess_request",
        "error": 0,
        "start": 1615196507003553600,
        "duration": 0,
    },
    {
        "trace_id": 6313747751933285704,
        "parent_id": 14675715570392257531,
        "span_id": 6167223375125391831,
        "service": "flask",
        "resource": "flask.dispatch_request",
        "name": "flask.dispatch_request",
        "error": 1,
        "start": 1615196507003553600,
        "duration": 504050400,
        "meta": {
            "error.msg": "division by zero",
            "error.type": "builtins.ZeroDivisionError",
            "error.stack": 'Traceback (most recent call last):\n  File "C:\\python3.7\\lib\\site-packages\\ddtrace\\contrib\\flask\\patch.py", line 496, in _traced_request\n    return wrapped(*args, **kwargs)\n  File "C:\\python3.7\\lib\\site-packages\\flask\\app.py", line 1936, in dispatch_request\n    return self.view_functions[rule.endpoint](**req.view_args)\n  File "C:\\python3.7\\lib\\site-packages\\ddtrace\\contrib\\flask\\wrappers.py", line 25, in trace_func\n    return wrapped(*args, **kwargs)\n  File "testddtrace.py", line 14, in hello_world\n    a = call_other_function_test()\n  File "testddtrace.py", line 21, in call_other_function_test\n    ab=5/0\nZeroDivisionError: division by zero\n',
        },
    },
    {
        "trace_id": 6313747751933285704,
        "parent_id": 6167223375125391831,
        "span_id": 6321986525867571848,
        "service": "flask",
        "resource": "/",
        "name": "__main__.hello_world",
        "error": 1,
        "start": 1615196507003553600,
        "duration": 502050200,
        "meta": {
            "error.msg": "division by zero",
            "error.type": "builtins.ZeroDivisionError",
            "error.stack": 'Traceback (most recent call last):\n  File "C:\\python3.7\\lib\\site-packages\\ddtrace\\contrib\\flask\\wrappers.py", line 25, in trace_func\n    return wrapped(*args, **kwargs)\n  File "testddtrace.py", line 14, in hello_world\n    a = call_other_function_test()\n  File "testddtrace.py", line 21, in call_other_function_test\n    ab=5/0\nZeroDivisionError: division by zero\n',
        },
    },
    {
        "trace_id": 6313747751933285704,
        "parent_id": 14675715570392257531,
        "span_id": 4313138956553452823,
        "service": "flask",
        "resource": "flask.handle_user_exception",
        "name": "flask.handle_user_exception",
        "error": 1,
        "start": 1615196507507604000,
        "duration": 3000300,
        "meta": {
            "error.msg": "division by zero",
            "error.type": "builtins.ZeroDivisionError",
            "error.stack": 'Traceback (most recent call last):\n  File "C:\\python3.7\\lib\\site-packages\\ddtrace\\contrib\\flask\\helpers.py", line 36, in wrapper\n    return wrapped(*args, **kwargs)\n  File "C:\\python3.7\\lib\\site-packages\\flask\\app.py", line 1821, in handle_user_exception\n    reraise(exc_type, exc_value, tb)\n  File "C:\\python3.7\\lib\\site-packages\\flask\\_compat.py", line 39, in reraise\n    raise value\n  File "C:\\python3.7\\lib\\site-packages\\flask\\app.py", line 1950, in full_dispatch_request\n    rv = self.dispatch_request()\n  File "C:\\python3.7\\lib\\site-packages\\ddtrace\\contrib\\flask\\helpers.py", line 25, in wrapper\n return func(pin, wrapped, instance, args, kwargs)\n  File "C:\\python3.7\\lib\\site-packages\\ddtrace\\contrib\\flask\\patch.py", line 496, in _traced_request\n    return wrapped(*args, **kwargs)\n  File "C:\\python3.7\\lib\\site-packages\\flask\\app.py", line 1936, in dispatch_request\n    return self.view_functions[rule.endpoint](**req.view_args)\n  File "C:\\python3.7\\lib\\site-packages\\ddtrace\\contrib\\flask\\wrappers.py", line 25, in trace_func\n    return wrapped(*args, **kwargs)\n  File "testddtrace.py", line 14,in hello_world\n    a = call_other_function_test()\n  File "testddtrace.py", line 21, in call_other_function_test\n    ab=5/0\nZeroDivisionError: division by zero\n',
        },
    },
    {
        "trace_id": 6313747751933285704,
        "parent_id": 14675715570392257531,
        "span_id": 8316614104702757702,
        "service": "flask",
        "resource": "flask.handle_exception",
        "name": "flask.handle_exception",
        "error": 0,
        "start": 1615196507510604300,
        "duration": 9000900,
    },
    {
        "trace_id": 6313747751933285704,
        "parent_id": 8316614104702757702,
        "span_id": 8591215255201123041,
        "service": "flask",
        "resource": "flask.process_response",
        "name": "flask.process_response",
        "error": 0,
        "start": 1615196507519605200,
        "duration": 0,
    },
    {
        "trace_id": 6313747751933285704,
        "parent_id": 14675715570392257531,
        "span_id": 18374612486554200250,
        "service": "flask",
        "resource": "flask.do_teardown_request",
        "name": "flask.do_teardown_request",
        "error": 0,
        "start": 1615196507519605200,
        "duration": 0,
    },
    {
        "trace_id": 6313747751933285704,
        "parent_id": 14675715570392257531,
        "span_id": 15661861780943223527,
        "service": "flask",
        "resource": "flask.do_teardown_appcontext",
        "name": "flask.do_teardown_appcontext",
        "error": 0,
        "start": 1615196507519605200,
        "duration": 0,
    },
]

 

 

 

 

 类似资料: