在追踪应用的链路数据之前,您需要通过客户端将应用数据上报至可观测链路 OpenTelemetry 版服务端。本文介绍如何通过OpenTelemetry Python SDK上报Python应用数据。
前提条件
获取接入点信息
- 登录可观测链路 OpenTelemetry 版控制台。
- 在左侧导航栏单击集群配置,然后在右侧页面单击接入点信息页签。
- 在页面顶部选择需要接入的地域,然后在集群信息区域打开显示Token开关。
- 在客户端采集工具区域单击OpenTelemetry。
在下方表格的相关信息列中,获取接入点信息。说明 如果应用部署于阿里云生产环境,则选择阿里云VPC网络接入点,否则选择公网接入点。
示例Demo
示例代码仓库地址:python-opentelemetry-demo
方法一:手动埋点上报Python应用数据
- 下载所需包。
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")
- 使用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))
展开查看完整示例代码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 inner_method(): tracer = trace.get_tracer(__name__) with tracer.start_as_current_span("child_span") as child_span: print("hello world") def outer_method(): tracer = trace.get_tracer(__name__) with tracer.start_as_current_span("parent_span") as parent_span: inner_method() 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") print(baggage.get_baggage("key", global_ctx)) print(baggage.get_baggage("key", parent_ctx)) print(baggage.get_baggage("key", child_ctx)) 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) if __name__ == '__main__': init_opentelemetry() outer_method() baggage_and_attribute_usage()
- 运行程序。
python manual.py
方法二:在Django应用中自动埋点并上报数据
- 下载所需包。
pip install django pip install opentelemetry-sdk pip install opentelemetry-instrumentation-django pip install requests
- 创建HelloWorld应用。
- 修改manage.py文件内容。
- 运行项目。
python manage.py runserver --noreload
说明--noreload
参数用于防止manage.main方法执行两次。如果在运行时出现ImportError(symbol not found in flat namespace '_CFRelease')
报错,请执行以下命令下载Grpcio包,然后重新运行项目。pip install grpcio
方法三:在自动埋点的基础上手动埋点
如果您需要在使用OpenTelemetry获得自动埋点能力的同时,添加自定义业务埋点,请在方法二的基础上完成以下操作。
- 下载包。
pip install opentelemetry-exporter-otlp
- 修改manage.py文件,在应用初始化的代码中添加以下内容。
- 请根据接入方式(gRPC或者HTTP)将代码中的
<token>
的<endpoint>
替换成前提条件中获取的接入点信息。 - 请根据实际情况替换代码中的
<service-name>
(服务名)和<host-name>
(主机名)。
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)将代码中的
- 修改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")
- 运行项目。
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 版控制台的应用列表页面选择目标应用,查看链路数据。