手动插桩
trace_utils.py
定义了两个函数,一个是创建数据处理管道,一个是创建tracer。tracer将用于产生span。 在这里使用了SDK和API,SDK是遥测数据处理的实现,API则是被开发者调用来产生span的。
python
# OTel API
from opentelemetry import trace as trace_api
# OTel SDK
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, BatchSpanProcessor
from resource_utils import create_resource
def create_tracing_pipeline()-> BatchSpanProcessor:
# write spans straight to console (stdout)
console_exporter = ConsoleSpanExporter()
# push spans to one or more SpanExporters
span_processor = BatchSpanProcessor(console_exporter)
return span_processor
# function to create a tracer with the given name and version
def create_tracer(name:str, version:str)->trace_api.Tracer:
provider = TracerProvider(
resource=create_resource(name, version)
)
provider.add_span_processor(create_tracing_pipeline())
trace_api.set_tracer_provider(provider)
tracer = trace_api.get_tracer(name, version)
return tracerresource_utils.py
定义了资源的属性,方便辨识遥测信号的来源。这里使用了Semantic Convention来遵循标准并避免拼写错误。
python
from opentelemetry.sdk.resources import Resource
from opentelemetry.semconv.resource import ResourceAttributes
def create_resource(name: str, version: str) -> Resource:
svc_resource = Resource.create(
{
ResourceAttributes.SERVICE_NAME: name,
ResourceAttributes.SERVICE_VERSION: version
}
)
return svc_resourceapp.py
对Flask的端点“/”对应的函数index进行插桩。
先使用tracer装饰器,这样可以自动处理span的创建、开始和结束。 在index函数内部使用get_current_span方法获取当前环境中的span,为这个span设置属性,设置属性的时候使用Semantic Convention提供的属性名。
python
@app.route("/")
@tracer.start_as_current_span("index")
def index():
span = trace_api.get_current_span()
span.set_attributes(
{
SpanAttributes.HTTP_METHOD: request.method,
SpanAttributes.URL_PATH: request.path,
SpanAttributes.HTTP_RESPONSE_STATUS_CODE: 200,
}
)
do_stuff()
current_time = time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime())
return f"Hello, World! It's currently {current_time}"如何在不同应用中传递OTel的Context? 当一个请求经过不同的服务,用traceid来标识它,将traceid放到请求的header里,下一个服务收到请求的时候从header提取traceid使用OTel提供的attach方法来设置Context,当此请求在当前服务结束后使用deatach方法取消销毁Context?
python
from flask import Flask, make_response, request
from trace_utils import create_tracer
from opentelemetry import trace as trace_api
from opentelemetry.semconv.trace import SpanAttributes
from opentelemetry import context
from opentelemetry.propagate import inject,extract
@app.teardown_request
def teardown_request_func(err):
previous_context = request.environ.get("previous_ctx_token",None)
if previous_context:
context.detach(previous_context)
@app.before_request
def before_request_func():
ctx = extract(request.headers)
previous_ctx = context.attach(ctx)
request.environ["previous_ctx_token"] = previous_ctx
@app.route("/users", methods=["GET"])
@tracer.start_as_current_span("users")
def get_user():
user, status = db.get_user(123)
data = {}
if user is not None:
data = {"id": user.id, "name": user.name, "address": user.address}
response = make_response(data, status)
return response