通过OpenTelemetry为应用埋点并上报链路数据至可观测链路 OpenTelemetry 版后,可观测链路 OpenTelemetry 版即可开始监控应用,您可以查看应用拓扑、调用链路、异常事务、慢事务和SQL分析等一系列监控数据。本文介绍如何使用OpenTelemetry Python Agent/SDK进行自动或手动埋点并上报数据。
推荐您优先接入阿里云自研Python Agent。
相比开源实现,阿里云 Python 探针提供对常见大模型框架(llama-index、dify、langchain、openai、通义千问等)的可观测性,提供更丰富的指标、链路及持续剖析数据。详细信息,请参见开始监控Python应用。
前提条件
背景信息
OpenTelemetry提供了若干自动埋点插件,支持为常见框架自动创建Span,支持的框架列表如下,完整信息请参见OpenTelemetry官方文档。
版本~= V.N
表示≥ V.N
且== V.*
,例如,aiohttp ~= 3.0
表示aiohttp版本要求aiohttp ≥ 3.0
且aiohttp == 3.*
。
示例Demo
示例代码仓库地址:python-opentelemetry-demo
方法一:通过Agent自动埋点并上报
下载所需包。
pip install django pip install requests pip install opentelemetry-distro \ opentelemetry-exporter-otlp opentelemetry-bootstrap -a install
创建AutoAndManualDemo项目并创建HelloWorld应用。
创建AutoAndManualDemo项目。
django-admin startproject AutoAndManualDemo
在项目中创建HelloWorld应用。
cd AutoAndManualDemo # 在项目中创建helloworld app python manage.py startapp helloworld
修改HelloWorld应用代码。
在AutoAndManualDemo/helloworld/views.py文件中添加以下代码。
from django.http import HttpResponse from datetime import datetime # Create your views here. def hello_world_view(request): result = "Hello World! Current Time =" + str(get_time()) return HttpResponse(result) def get_time(): now = datetime.now() return now.strftime("%H:%M:%S")
创建AutoAndManualDemo/helloworld/urls.py文件,并在urls.py文件中添加以下代码。
from django.urls import path from . import views urlpatterns = [ path('', views.hello_world_view, name='helloworld') ]
修改AutoAndManualDemo/AutoAndManualDemo/urls.py文件,添加helloworld的URL。
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('helloworld/', include('helloworld.urls')), ]
运行项目。
通过HTTP上报,请将
<your-service-name>
替换为您的应用名,将<http-endpoint>
替换为HTTP接入点。opentelemetry-instrument \ --traces_exporter console,otlp_proto_http \ --metrics_exporter none \ --service_name <your-service-name> \ --exporter_otlp_traces_endpoint <http-endpoint> \ python manage.py runserver --noreload
说明--noreload
:避免manage.main方法执行两次。如果运行报错
CommandError: You must set settings.ALLOWED_HOSTS if DEBUG is False.
,但AutoAndManualDemo/AutoAndManualDemo/settings.py中的DEBUG和ALLOWED_HOSTS均已配置正确,这是因为使用opentelemetry-instrument启动时使用了Django框架的默认配置文件(django/conf/global_settings.py), 因此需要添加export DJANGO_SETTINGS_MODULE=AutoAndManualDemo.settings
环境变量。
在浏览器中访问
http://127.0.0.1:8000/helloworld/
,控制台会打印Trace,同时也会将Trace上报至阿里云可观测链路 OpenTelemetry 版。如需关闭控制台打印Trace,只需将
--traces_exporter
参数配置为--traces_exporter otlp_proto_http
。
方法二:手动埋点并上报
下载所需包。
pip install opentelemetry-api pip install opentelemetry-sdk pip install opentelemetry-exporter-otlp
在manual.py文件中设置OpenTelemetry初始化代码。
请将代码中的
<token>
的<endpoint>
替换成前提条件中获取的接入点信息。请根据实际情况替换代码中的
<service-name>
(服务名)和<host-name>
(主机名)。
from opentelemetry import trace, baggage from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter as OTLPSpanGrpcExporter from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter as OTLPSpanHttpExporter from opentelemetry.sdk.resources import SERVICE_NAME, Resource, HOST_NAME from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor def init_opentelemetry(): # 设置服务名、主机名 resource = Resource(attributes={ SERVICE_NAME: "<service-name>", HOST_NAME: "<host-name>" }) # 使用GRPC协议上报 span_processor = BatchSpanProcessor(OTLPSpanGrpcExporter( endpoint="<endpoint>", headers=("Authentication=<token>") )) # 使用HTTP协议上报 # span_processor = BatchSpanProcessor(OTLPSpanHttpExporter( # endpoint="<endpoint>", # )) trace_provider = TracerProvider(resource=resource, active_span_processor=span_processor) trace.set_tracer_provider(trace_provider)
创建Span。
tracer = trace.get_tracer(__name__) # 获取tracer with tracer.start_as_current_span("child_span") as child_span: # 创建名为child_span的span print("hello world")
获取TraceID和SpanID。
ctx = trace.get_current_span().get_span_context() trace_id = '{trace:032x}'.format(trace=ctx.trace_id) span_id = '{span:016x}'.format(span=ctx.span_id) print(trace_id) print(span_id)
使用OpenTelemetry Baggage API透传业务自定义标签。
创建baggage_parent_span时通过指定attributes参数来设置属性。
def baggage_and_attribute_usage(): tracer = trace.get_tracer(__name__) global_ctx = baggage.set_baggage("key", "value_from_global_ctx") # 使用baggage api,在不同span之间传递数据 with tracer.start_as_current_span(name='baggage_parent_span', attributes={'attribute_key': 'value'}) as baggage_parent_span: parent_ctx = baggage.set_baggage("key", "value_from_parent_ctx") with tracer.start_as_current_span(name='baggage_child_span', context=parent_ctx) as baggage_child_span: child_ctx = baggage.set_baggage("key", "value_from_child_ctx") # 获取不同contex下key对应的值 print(baggage.get_baggage("key", global_ctx)) print(baggage.get_baggage("key", parent_ctx)) print(baggage.get_baggage("key", child_ctx))
运行程序。
python manual.py
方法三:在自动埋点基础上手动埋点
如果您需要在使用OpenTelemetry获得自动埋点能力的同时,添加自定义业务埋点,请在方法一的基础上完成以下操作。
下载包。
pip install django pip install requests pip install opentelemetry-sdk pip install opentelemetry-instrumentation-django pip install opentelemetry-exporter-otlp
创建AutoAndManualDemo项目并创建HelloWorld应用。
创建AutoAndManualDemo项目。
django-admin startproject AutoAndManualDemo
在项目中创建HelloWorld应用。
cd AutoAndManualDemo # 在项目中创建helloworld app python manage.py startapp helloworld
修改helloworld/views.py文件代码。
获取tracer并手动创建span,同时设置span名称。
from django.http import HttpResponse from opentelemetry import trace from datetime import datetime # Create your views here. def hello_world_view(request): tracer = trace.get_tracer(__name__) with tracer.start_as_current_span("hello_world_span") as hello_world_span: result = "Hello World! Current Time =" + str(get_time()) return HttpResponse(result) def get_time(): now = datetime.now() tracer = trace.get_tracer(__name__) # 创建新的span with tracer.start_as_current_span("time_span") as time_span: return now.strftime("%H:%M:%S")
修改urls.py文件。
创建helloworld/urls.py文件,在urls.py中添加以下代码。
from django.urls import path from . import views urlpatterns = [ path('', views.hello_world_view, name='helloworld') ]
修改AutoAndManualDemo/AutoAndManualDemo/urls.py文件,添加helloworld的URL。
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('helloworld/', include('helloworld.urls')), ]
修改manage.py文件代码,在应用初始化的代码中添加以下内容。
from opentelemetry import trace from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter # 通过gRPC接入 # from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter # 通过HTTP接入 from opentelemetry.sdk.resources import SERVICE_NAME, Resource, HOST_NAME from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter resource = Resource(attributes={ SERVICE_NAME: "<service-name>", HOST_NAME: "<host-name>" }) trace.set_tracer_provider(TracerProvider(resource=resource)) trace.get_tracer_provider().add_span_processor( BatchSpanProcessor(OTLPSpanExporter( endpoint="<endpoint>", headers="Authentication=<token>" # 通过gRPC接入时需要headers参数,通过HTTP接入时不需要此参数 ))) # 通过 OTLPSpanExporter 上报Trace trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(ConsoleSpanExporter())) # 在控制台输出Trace
请替换以下内容,并根据接入方式(gRPC或者HTTP)修改代码:
<service-name>
: 需要上报的服务名<host-name>
:主机名<endpoint>
:通过HTTP/gRPC上报数据的接入点<token>
:通过gRPC上报数据的鉴权Token
运行项目。
python manage.py runserver --noreload
--noreload
防止manage.main方法执行两次。如果运行时出现
ImportError(symbol not found in flat namespace '_CFRelease')
,请下载并安装grpcio包。pip install grpcio
在浏览器中访问
127.0.0.1:8000/helloworld
,链路数据便会上报至可观测链路 OpenTelemetry 版控制台。
查看监控数据
在可观测链路 OpenTelemetry 版控制台的应用列表页面选择目标应用,查看链路数据。