注意:说明:
一、前提条件
此方案支持 Python 3.6及以上版本。
二、Django 应用注意事项
如果你的应用使用 Django 框架,通过 OpenTelemetry-Python 方案接入前需要注意如下事项:
·推荐使用 uWSGI 方式部署服务,部署方式请参考 通过 uWSGI 托管 Django 应用,直接通过 Python 命令启动可能会造成上报失败。
·OpenTelemetry-Python 的引入,可能会导致 Django 应用不再使用默认的配置文件,需要通过环境变量重新指定配置文件。
export DJANGO_SETTINGS_MODULE=mysite.settings
·如果你使用 runserver 命令启动 Django 服务,尝试禁用 autoreload,防止 fork 子进程操作影响到埋点。
opentelemetry-instrument python manage.py runserver –noreload
三、gevent 应用注意事项
如果项目中将 gevent 作为协程库与 Python 自动埋点探针结合使用,可能会出现一系列问题,包括启动报错、Span 异常断链等问题。以下是几种可能的解决方案:
·gevent.monkey.patch_all() 需要尽早执行:gevent 通过 monkey patching 修改 Python 标准库中的阻塞式 I/O 操作,使其变为非阻塞式,以适应协程的并发模型。OpenTelemetry 的自动埋点探针也可能依赖或修改标准库的行为。如果 monkey patching 的顺序不当,或者 OpenTelemetry 探针在 gevent 完成 patching 之前加载了某些模块,就可能造成启动报错 RecursionError。
from gevent import monkeymonkey.patch_all() # 尽可能早地执行# 之后再导入其他模块和 OpenTelemetry 相关库from flask import Flaskfrom opentelemetry import tracefrom opentelemetry.sdk.trace import TracerProvider# … 其他 OpenTelemetry 配置和应用代码
·如果你在使用 Gunicorn 作为 Python 程序的 HTTP 服务器,我们更推荐用 uvicorn 或 gthread 替换 gevent 作为 worker class,以避免潜在的问题。
四、uWSGI 应用注意事项
uWSGI 使用 master-worker 多进程模型,以下情况可能导致 OpenTelemetry 埋点失败:
·插桩代码在 master 进程中初始化,但实际请求在 worker 进程中处理。
·worker 进程 fork 后,某些插桩组件可能没有正确继承。
为了保证埋点的成功,可以启用 –lazy-apps 参数,其作用是让每个 worker 独立加载应用,示例如下:
[uwsgi]module = your_app:applicationmaster = trueprocesses = 4lazy-apps = true # 重要:延迟应用加载enable-threads = true
五、示例 Demo
所需依赖如下。
pip install flaskpip install mysql-connector-pythonpip install redispip install requests
示例代码 app.py 通过 Flask 框架提供3个 HTTP 接口,对应的 MySQL 和 Redis 服务请自行搭建,或直接购买云产品。
from flask import Flaskimport requestsimport timeimport mysql.connectorimport redisbackend_addr = 'https://example.com/' app = Flask(__name__)# 访问外部站点@app.route('/')def index(): start = time.time() r = requests.get(backend_addr) return r.text# 访问数据库@app.route('/mysql')def func_rdb(): cnx = mysql.connector.connect(host='127.0.0.1', database="<DB-NAME>", user='<DB-USER>', password='<DB-PASSWORD>', auth_plugin='mysql_native_password') cursor = cnx.cursor() val = "null" cursor.execute("select value from table_demo where id=1;") val = cursor.fetchone()[0] cursor.close() cnx.close() return "rdb res:" + val# 访问Redis@app.route("/redis")def func_kvop(): client = redis.StrictRedis(host="localhost", port=6379) val = "null" val = client.get('foo').decode("utf8") return "kv res:" + valapp.run(host='0.0.0.0', port=8080)
六、获取接入点和 Token
1. 登录 腾讯云可观测平台 控制台。
2. 在左侧菜单栏中选择应用性能监控 > 应用列表,单击接入应用。
3. 在右侧弹出的接入应用抽屉框中,单击 Python 语言。
4. 在接入 Python 应用页面,选择你所要接入的地域以及业务系统。
5. 选择接入协议类型为 OpenTelemetry。
6. 选择你所想要的上报方式,获取你的接入点和 Token。
注意:说明:
七、步骤1:安装所需的依赖包
pip install opentelemetry-distro opentelemetry-exporter-otlpopentelemetry-bootstrap -a install
八、步骤2:添加运行参数
通过如下命令启动 Python 应用。
opentelemetry-instrument \\–traces_exporter otlp_proto_grpc \\–metrics_exporter none \\–logs_exporter none \\–service_name <serviceName> \\–resource_attributes token=<token>,host.name=<hostName> \\–exporter_otlp_endpoint <endpoint> \\python3 app.py
对应的字段说明如下:
·<serviceName> :应用名,多个使用相同 serviceName 接入的应用进程,在 APM 中会表现为相同应用下的多个实例。应用名最长63个字符,只能包含小写字母、数字及分隔符“ – ”,且必须以小写字母开头,数字或小写字母结尾。
·<token> :前置步骤中拿到业务系统 Token。
·<hostName>:该实例的主机名,是应用实例的唯一标识,通常情况下可以设置为应用实例的 IP 地址。对于 K8s 环境,可以通过 Downward API 动态获取 Pod IP,具体配置方式请参见 动态获取 Pod 名称和 Pod IP。
·<endpoint> :前置步骤中拿到的接入点。
注意:说明:
注意:上述列出的字段均为必填(Required)。
下述内容以应用名为 myService,业务系统 Token 为 myToken,主机名为 192.168.0.10,接入点 https://pl-demo.ap-guangzhou.apm.tencentcs.com:4319 为例,完整的启动命令为如下。
opentelemetry-instrument \\–traces_exporter otlp_proto_grpc \\–metrics_exporter none \\–logs_exporter none \\–service_name myService \\–resource_attributes token=myToken,host.name=192.168.0.10 \\–exporter_otlp_endpoint https://pl-demo.ap-guangzhou.apm.tencentcs.com:4319/ \\python3 app.py
九、接入验证
启动 Python 应用后,通过8080端口访问对应的接口,例如 https://localhost:8080/。在有正常流量的情况下,应用性能监控 > 应用列表 中将展示接入的应用,单击应用名称/ID 进入应用详情页。
再选择实例分析,即可看到接入的应用实例。由于可观测数据的处理存在一定延时,如果接入后在控制台没有查询到应用或实例,请等待30秒左右。
十、自定义埋点(可选)
当自动埋点不满足你的场景或者需要增加业务层埋点时,你可参照下述内容,使用 OpenTelemetry API 添加自定义埋点。这篇仅展示最基本的自定义埋点方式,OpenTelemetry 社区提供了更多灵活的自定义埋点方式,具体使用方法可参考 OpenTelemetry 社区提供的 Python 自定义埋点文档。
from opentelemetry import traceimport requestsfrom flask import Flaskimport time
backend_addr = 'https://example.com/' app = Flask(__name__)
@app.route('/')
def index():
r = requests.get(backend_addr) # 对于requests.get()发起的外部请求,OpenTelemetry-Python会自动埋点
slow() # 调用一个自定义函数
return r.text
def slow():
tracer = trace.get_tracer(__name__) # 自定义函数不在OpenTelemetry-Python自动埋点范围内,因此增加一个自定义埋点 with tracer.start_as_current_span("child_span"): time.sleep(5) return
十一、问题排查
如果发现自动埋点无法上报数据到 APM,可以通过设置 –traces_exporter=console,otlp_proto_grpc 将链路数据打印到控制台,如果发现控制台中有 span 和 trace 等输出,但是 APM 中没有数据,则排查是否是 endpoint 和 token 有误;如果发现控制台中没有相关的输出,可以检查应用程序所使用的框架或组件是否在 OpenTelemetry 支持的 完整列表 中。如果无法确认具体问题,可以向我们 提交工单。