链路追踪是应用可观测性的重要组成部分,它可以帮助我们快速定位问题,提高应用的可用性和稳定性。 今天我们来看看如何使用 opentelemetry 与 jaeger 实现 flask 应用的链路追踪。
OpenTelemetry is a collection of tools, APIs, and SDKs. Use it to instrument, generate, collect, and export telemetry data (metrics, logs, and traces) to help you analyze your software’s performance and behavior.
OpenTelemetry 是一个用于收集、生成、导出遥测数据(metrics、logs、traces)的工具集合,它可以帮助我们分析软件的性能和行为。
Jaeger 是一个开源的分布式跟踪系统,它可以收集、存储和分析应用的链路追踪数据。
Jaeger 支持 Opentelemetry 协议,可以直接从 OpenTelemetry 收集数据。
Jaeger 有多种部署方式,在开发环境下最简单的方式是使用 Jaeger 官方提供的 all-in-one 镜像。
## make sure to expose only the ports you use in your deployment scenario!
docker run -d --name jaeger \
-e COLLECTOR_OTLP_ENABLED=true \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-p 5775:5775/udp \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 14250:14250 \
-p 14268:14268 \
-p 14269:14269 \
-p 4317:4317 \
-p 4318:4318 \
-p 9411:9411 \
jaegertracing/all-in-one:1.42
访问 http://localhost:16686 查看 Jaeger 的 UI。
首先安装一下相关依赖。
pip install flask opentelemetry-instrumentation-flask opentelemetry-exporter-jaeger
编辑main.py
,定义一个简单的 flask 应用。
from flask import Flask
from opentelemetry import trace
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
def configure_trace(app: Flask):
trace.set_tracer_provider(
TracerProvider(resource=Resource.create({SERVICE_NAME: app.name}))
)
trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(
JaegerExporter(
agent_host_name="localhost",
agent_port=6831,
)
)
)
FlaskInstrumentor().instrument_app(app)
app = Flask(__name__)
configure_trace(app)
@app.get("/")
def hello():
return "Hello, World!"
在configure_trace
函数中,我们配置了 opentelemetry 的 TracerProvider,它是一个全局的单例,用于创建 tracer。
然后创建了一个 JaegerExporter 并添加为 Provider 的 Processor,它会将收集到的数据发送到 Jaeger。
最后使用 FlaskInstrumentor 来为 flask 应用添加 opentelemetry 的中间件。
运行应用并访问 http://localhost:5000。
flask --app=main:app run --reload
刷新 Jaeger 的 UI,选择main
服务,点击”Find Traces”,可以看到之前的访问已经被成功追踪。
点击具体的 trace 可以看到详细的链路信息,包括请求的路径、响应时间等信息。
我们可以使用 opentelemetry 的 API 来追踪细致的业务逻辑。
@app.get("/")
def hello():
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("step-1") as span:
span.add_event("step-1-event", {"key": "value"})
time.sleep(0.1)
with tracer.start_as_current_span("step-2"):
with tracer.start_as_current_span("step-2-1"):
time.sleep(0.05)
with tracer.start_as_current_span("step-2-2"):
time.sleep(0.05)
return "Hello, World!"
通过trace.get_tracer(__name__)
获取到 tracer,然后使用 with start_as_current_span(span_name)
创建一个 span,可以进行具体业务逻辑的追踪。
上述代码中,我们创建了两个 span,分别是step-1
和step-2
(拥有两个子 span),并且在step-1
中添加了一个 event。
重新访问 http://localhost:5000,刷新 Jaeger 的 UI,可以看到新的 trace 已经被成功追踪,并且可以追踪到每一个 span 的开始时间、结束时间、耗时等信息。
也可以切换视图,查看 Trace 的树状结构和火焰图,从不同的角度分析链路。
业务流程中,我们经常会调用外部服务,比如远程 API、数据库、缓存、消息队列等,我们可以使用 opentelemetry 的 API 来追踪这些外部服务的调用。
首先需要安装对应的 opentelemetry-instrumentation 库。
pip install redis pymongo requests opentelemetry-instrumentation-redis opentelemetry-instrumentation-pymongo opentelemetry-instrumentation-requests
修改main.py
,增加响应配置。
from flask import Flask
from opentelemetry import trace
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.pymongo import PymongoInstrumentor
from opentelemetry.instrumentation.redis import RedisInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
def configure_trace(app: Flask):
trace.set_tracer_provider(
TracerProvider(resource=Resource.create({SERVICE_NAME: app.name}))
)
trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(
JaegerExporter(
agent_host_name="localhost",
agent_port=6831,
)
)
)
FlaskInstrumentor().instrument_app(app)
RequestsInstrumentor().instrument()
PymongoInstrumentor().instrument()
RedisInstrumentor().instrument()
增加一个新的路由。
@app.get("/external-services")
def external_services():
requests.get("https://httpbin.org/delay/1")
MongoClient().test.test.find_one()
Redis().incr("key")
return "OK"
我们在external_services
函数中调用了三个外部服务,分别是一次远程请求、一次数据库查询和一次缓存操作。
访问 http://localhost:5000/external-services ,刷新 Jaeger 的 UI,可以看到对应的 trace 已经被成功追踪。
trace 信息中提供了每一个外部服务调用详细信息,包括 http 请求的路径、响应状态码、数据库查询的语句、缓存操作的 key 等。
调整到火焰图视图,可以清楚地看到本次请求的绝大多数时间用在了对”https://httpbin.org/delay/1"的 http 请求中(毕竟服务器延迟了一秒才返回响应内容)。
找到了性能瓶颈,也就能针对性优化代码。
@app.get("/external-services")
def external_services():
requests.head("https://www.baidu.com")
MongoClient().test.test.find_one()
Redis().incr("key")
return "OK"
重新访问 http://localhost:5000/external-services ,可以看到请求的响应时间得到了极大的优化。
通过集成 opentelemetry 与 jaeger,我们可以很方便地在 Flask 应用中追踪业务逻辑和外部服务的调用,从而更好地分析和优化业务流程。
在下一篇文章中,我们将介绍如何在复杂系统中使用 opentelemetry 进行跨服务追踪。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有