通過OpenTelemetry為應用埋點并上報鏈路數據至可觀測鏈路 OpenTelemetry 版后,可觀測鏈路 OpenTelemetry 版即可開始監控應用,您可以查看應用拓撲、調用鏈路、異常事務、慢事務和SQL分析等一系列監控數據。本文介紹如何使用OpenTelemetry Python Agent/SDK進行自動或手動埋點并上報數據。
推薦您優先接入阿里云自研Python Agent。
相比開源實現,阿里云 Python 探針提供對常見大模型框架(llama-index、dify、langchain、openai、通義千問等)的可觀測性,提供更豐富的指標、鏈路及持續剖析數據。詳細信息,請參見開始監控Python應用。
前提條件
新版控制臺
登錄可觀測鏈路 OpenTelemetry 版控制臺,在左側導航欄單擊接入中心。
在開源框架區域單擊OpenTelemetry卡片。
在彈出的OpenTelemetry面板中選擇數據需要上報的地域。
說明初次接入的地域將會自動進行資源初始化。
選擇連接方式和上報方式,然后復制接入點信息。
連接方式:若您的服務部署在阿里云上,且所屬地域與選擇的接入地域一致,推薦使用阿里云內網方式,否則選擇公網方式。
上報方式:根據客戶端支持的協議類型選擇HTTP或gRPC協議上報數據。
舊版控制臺
在左側導航欄單擊集群配置,然后在右側頁面單擊接入點信息頁簽。
在頁面頂部選擇需要接入的地域,然后在集群信息區域打開顯示Token開關。
在客戶端采集工具區域單擊OpenTelemetry。
在相關信息列中,獲取接入點信息。
說明如果應用部署于阿里云生產環境,則選擇阿里云VPC網絡接入點,否則選擇公網接入點。
背景信息
OpenTelemetry提供了若干自動埋點插件,支持為常見框架自動創建Span,支持的框架列表如下,完整信息請參見OpenTelemetry官方文檔。
版本~= V.N
表示≥ V.N
且== V.*
,例如,aiohttp ~= 3.0
表示aiohttp版本要求aiohttp ≥ 3.0
且aiohttp == 3.*
。
OpenTelemetry插件 | 支持的Package以及版本 |
aio_pika - [7.2.0, 10.0.0) | |
aiohttp ~= 3.0 | |
aiohttp ~= 3.0 | |
aiopg - [0.13.0, 2.0.0) | |
asgiref ~= 3.0 | |
asyncpg ≥ 0.12.0 | |
aws_lambda | |
boto ~= 2.0 | |
boto3 ~= 1.0 | |
botocore ~= 1.0 | |
| |
celery - [4.0, 6.0) | |
confluent-kafka - [1.8.2, 2.2.0] | |
dbapi | |
django ≥ 1.10 | |
elasticsearch ≥ 2.0 | |
falcon - [1.4.1, 4.0.0) | |
fastapi ~= 0.58 | |
flask - [1.0, 3.0) | |
grpcio ~= 1.27 | |
httpx ≥ 0.18.0 | |
jinja2 - [2.7, 4.0) | |
kafka-python ≥ 2.0 | |
logging | |
mysql-connector-python ~= 8.0 | |
mysqlclient < 3 | |
pika≥ 0.12.0 | |
psycopg2 ≥ 2.7.3.1 | |
pymemcache - [1.3.5, 5) | |
pymongo - [3.1, 5.0) | |
PyMySQL < 2 | |
pyramid ≥ 1.7 | |
redis ≥ 2.6 | |
remoulade ≥ 0.50 | |
requests ~= 2.0 | |
sqlalchemy | |
sqlite3 | |
starlette ~= 0.13.0 | |
psutil ≥ 5 | |
tornado ≥ 5.1.1 | |
tortoise-orm ≥ 0.17.0 | |
urllib | |
urllib3 - [1.0.0, 3.0.0) | |
wsgi |
示例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))
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
方法三:在自動埋點基礎上手動埋點
如果您需要在使用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 版控制臺的應用列表頁面選擇目標應用,查看鏈路數據。