100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > opentelemetry+python+jaeger链路追踪相关使用备注

opentelemetry+python+jaeger链路追踪相关使用备注

时间:2022-06-19 21:52:15

相关推荐

opentelemetry+python+jaeger链路追踪相关使用备注

什么是链路追踪:

在分布式微服务架构中, 一个请求从用户发起到接收,后端服务可能要经过多个微服务间调用,及多个功能组件(mysql,redis...)和网络请求(http,upd),在这个过程中,任何地方都可能出现错误,导致此次请求失败; 这时就需要 能够掌握请求中每个阶段节点所做的事情,保证出现问题时,能准确迅速定位; 这种记录 请求每个关键节点信息并能以调用链路顺序的方式展现出来 就是链路追踪;

Instrumentation: 英文文档中 此单词含义是 "仪器仪表";在计算机领域中 为 "能够监测和度量某个系统的性能,分析系统错误,并能将追踪的数据进行记录"; 其实就是 检测数据或埋点数据; 理解此单词含义才能更加明白的阅读相关文档;

为什么需要链路追踪:

能通过记录 找到具体出现问题的微服务及错误栈信息;能清晰梳理出微服务间调用的流程;对于服务治理很有帮助;能迅速判断出接口各种异常位置(如bug/耗时过长)

链路追踪行业规范:

最开始时,各家公司厂商有自己的一套链路追踪的数据结构及展示形式,缺点在于 开发者如果想更换链路追踪系统,则代码中链路追踪部分也要修改,造成迁移难度巨大;

后来意识到这个问题,CNCF(Cloud Native Computing Foundation:云原生计算基金会) 出了 一个OpenTracing(基于API的标准,所有遥测或埋点数据必须通过此API标准发送数据到观测后端服务);

google出了一个OpenCensus(提供了一些语言的库,开发者可以使用这些库将数据发送到OpenCensus支持的观测后端服务,如jaeger,zipkin等等);

时, google的OpenCensus和CNCF的OpenTracing 合并为 Opentelemetry(简称 OTel),归为CNCF孵化维护;

Opentelemetry功能:

提供多种语言的库用于手动和自动 生成/发送 监测(或埋点)数据到 不同观测后端的功能;标准开放的语义定义,确保与后端服务无关的数据收集;

Python中OTel+jaeger实现自动链路追踪功能:

jaeger:uber公司开源的,用go语言实现的一个存储观测数据及提供web端查询的分布式系统; 此工具只支持trace数据格式;

实现步骤:

部署jaeger:使用all in one方式数据存储在内存中,用于开发;生产服需要设置存储Span数据的后台数据服务(如:Elasticsearch,kafka,Cassandra等等)

docker run -d --name jaeger \-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \-e COLLECTOR_OTLP_ENABLED=true \-p 6831:6831/udp \-p 6832:6832/udp \-p 5778:5778 \-p 16686:16686 \-p 4317:4317 \-p 4318:4318 \-p 14250:14250 \-p 14268:14268 \-p 14269:14269 \-p 9411:9411 \jaegertracing/all-in-one:1.37

在flask项目中安装如下包:

pip install opentelemetry-distropip install opentelemetry-propagator-jaegerpip install opentelemetry-exporter-jaeger

在项目虚拟环境中执行如下命令 来 安装自动收集各种监测数据用到的各种包;如mysql,redis,mongo,requests,grpc等等...;此命令会根据此项目目前代码安装可能用到的包;

opentelemetry-bootstrap -a install

python代码部分(代码无法直接运行,需要修改flask的create_app相关代码;)

import jsonimport osfrom random import randintimport tracebackimport clickfrom flask import requestfrom opentelemetry.instrumentation.flask import FlaskInstrumentorfrom opentelemetry.instrumentation.grpc import GrpcInstrumentorClientfrom opentelemetry.instrumentation.pymongo import PymongoInstrumentorfrom opentelemetry.instrumentation.redis import RedisInstrumentorfrom opentelemetry.instrumentation.requests import RequestsInstrumentorfrom opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentorfrom opentelemetry.propagators.jaeger import JaegerPropagatorfrom opentelemetry.trace import Spanfrom app import create_appfrom app.utils import json_successos.environ["LC_ALL"] = "en_US.utf-8"os.environ["LANG"] = "en_US.utf-8"from opentelemetry import tracefrom opentelemetry.exporter.jaeger.thrift import JaegerExporterfrom opentelemetry.sdk.resources import SERVICE_NAME, Resource, SERVICE_NAMESPACEfrom opentelemetry.sdk.trace import TracerProviderfrom opentelemetry.sdk.trace.export import SimpleSpanProcessorfrom opentelemetry.propagate import set_global_textmap# 设置 全局的从请求头中获取trace信息的方式为 Jaeger的uber-trace-id;其他的方式如 b3 等等;# 设置此选项,使微服务间能够根据 http请求头的uber-trace-id 将 跨多个微服务的请求归为同一个trace中,方便查看set_global_textmap(JaegerPropagator())# 设置trace的服务名及命令空间resource = Resource(attributes={SERVICE_NAME: "project_name",SERVICE_NAMESPACE: "test_env",})# 设置trace数据导出服务 为jaeger; 通过jaeger服务的6831(UPD协议)端口上传;jaeger_exporter = JaegerExporter(agent_host_name="localhost",agent_port=6831,)# 设置traceprovider = TracerProvider(resource=resource)# 将trace中每个span数据发送给jaeger的方式,SimpleSpanProcessor(直接传输),其他如:BatchSpanProcessor(批量传输),ConcurrentMultiSpanProcessor(多线程并发传输)...processor = SimpleSpanProcessor(jaeger_exporter)provider.add_span_processor(processor)trace.set_tracer_provider(provider)# 自动生成span数据的各种涉及到IO的插件部分; 如 requests,grpc,mongo,redis,sqlalchemy等等;# 所有python可用自动埋点的插件在 /Rgcsh/opentelemetry-python-contrib/tree/main/instrumentation 目录下# 注意 多数插件必须在 flask app生成之前定义;否则无法自动生成span(埋点失败)RequestsInstrumentor().instrument()GrpcInstrumentorClient().instrument()SQLAlchemyInstrumentor().instrument(enable_commenter=True, commenter_options={})PymongoInstrumentor().instrument()RedisInstrumentor().instrument()app = create_app()def request_hook(span: Span, _):"""flask请求进入时 在before_request中的hook函数;可以将一些请求数据(如请求参数等等) 放到span中:param span::param _::return:"""def request_params():""" 获取当前请求的参数"""request_params = dict()# 获取请求参数request_params.update(request.args.to_dict())# 获取form表单中的参数request_params.update(request.form.to_dict())# 获取json参数json_params = Nonetry:json_params = getattr(request, "json", None)except Exception:passif isinstance(json_params, dict):request_params.update(json_params)if len(str(request_params)) > 1000:return "部分截取入参:" + str(request_params)[-1000:]return request_params# 在span中添加一些额外的数据,值不能 为dict类型(否则无法显示在jaeger UI上);span.set_attributes({"request.params": json.dumps(request_params()) or '',"request.uid": request.headers.get("Access-User") or ''})# 对flask框架进行埋点,基本就是 生成一个请求相关的span数据# 此插件必须在flask app生成之后调用FlaskInstrumentor().instrument_app(app, request_hook=request_hook)# 获取一个全局的trace,在手动埋点时使用tracer = trace.get_tracer(__name__)@app.route("/roll", methods=["POST"])def roll_dice():"""一个测试路由:return:"""# 手动设置span数据with tracer.start_as_current_span("do_roll") as rollspan:res = randint(1, 6)rollspan.set_attribute("roll.value", res)# 遇到错误时,可以通过此方式上传 错误栈span;rollspan.set_attributes({"error": "true", "stacktrace": traceback.format_exc()})return json_success()@mand()@click.option("--port", "-p", help="Server run port", default=8080)@click.option("--host", "-h", help="Server run host", default="0.0.0.0")def start(host, port):""" 开启实例:param host: 监听的主机:param port: 监听的端口"""app.run(host=host, port=int(port))if __name__ == "__main__":start()

监测效果:

代码示例说明:

微服务间通过请求头中的uber-trace-id的值作为trace_id的值来关联,保证他们属于同一个trace;

每个自动化生成检测数据 插件有其自身的 参数可以定义,实现额外的自定义功能;

总结:

opentelemetry(OTel)提供了常用语言(java,go,python等等)的库供开发者使用,用于自动或手动 生成检测数据并传输到众多后端检测服务中 的功能;

OTel python sdk推荐使用>=python3.7版本,但是在python3.6中也能使用,只是时间精度只能达到毫秒级别,无法达到纳秒级别;

作为开发者需要做的就是使用OTel及出现问题时,会使用web ui工具排查问题即可;

相关链接:

Getting Started — Jaeger documentation

OpenTelemetry - CNCF · GitHub

GitHub - open-telemetry/opentelemetry-python: OpenTelemetry Python API and SDK

GitHub - open-telemetry/opentelemetry-python-contrib: OpenTelemetry instrumentation for Python modules

Getting Started | OpenTelemetry

OpenTelemetry-Python API Reference — OpenTelemetry Python documentation

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。