文档

通过Jaeger上报Python应用数据

更新时间:

通过Jaeger为应用埋点并上报链路数据至可观测链路 OpenTelemetry 版后,可观测链路 OpenTelemetry 版即可开始监控应用,您可以查看应用拓扑、调用链路、异常事务、慢事务和SQL分析等一系列监控数据。本文介绍如何使用Jaeger为Python应用埋点并上报数据。

重要

为获得更丰富的功能、更先进的链路追踪能力,以及最佳使用体验,建议您使用OpenTelemetry协议将应用接入可观测链路 OpenTelemetry 版

我们为您提供了详细的OpenTelemetry接入指南和最佳实践,帮助您快速上手可观测链路 OpenTelemetry 版。更多信息,请参见接入应用

前提条件

获取接入点信息

  1. 登录ARMS控制台,在左侧导航栏单击接入中心

  2. 服务端应用区域单击Jaeger卡片。

  3. 在弹出的Jaeger面板中选择数据需要上报的地域。

    说明

    初次接入的地域将会自动进行资源初始化。

  4. 选择连接方式上报方式,然后复制接入点信息。

    • 连接方式:若您的服务部署在阿里云上,且所属地域与选择的接入地域一致,推荐使用阿里云内网方式,否则选择公网方式。

    • 上报方式:根据客户端支持的协议类型选择HTTP或gRPC协议上报数据。

    image.png

背景信息

数据是如何上报的?

  • 不通过Jaeger Agent而直接上报数据的原理如下图所示。

    image
  • 通过Jaeger Agent上报数据的原理如下图所示。

    image

注意事项

  • 针对Python语言,最新v1.25版本的Jaeger仅支持通过Jaeger Agent而不支持直接使用HTTP协议上报调用链路数据。更多信息,请参见Jaeger官方文档

  • 针对Python语言,最新v1.25版本的Jaeger仅支持通过UDP协议从Jaeger Client端上报至Jaeger Agent端。由于UDP协议并不保证通信的可靠性,因此为了保证调用链路数据的可靠性,一般情况下需要将Jaeger Client端和Jaeger Agent端运行在同一个主机内。

步骤一:搭建环境

本文演示示例中对Docker、Jaeger Agent、Jaeger Client和Python的版本要求如下。

Docker和Jaeger Agent环境

Docker版本:20.10.7

Jaeger Agent版本:1.25

  1. 在DockerHub中执行以下命令拉取v1.25版本的Jaeger Agent镜像。

    docker pull jaegertracing/jaeger-agent:1.25
  2. 执行以下命令运行v1.25版本的Jaeger Agent。

    docker run -d --name jaeger-agent  -p 5775:5775/udp -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778/tcp jaegertracing/jaeger-agent:1.25 --reporter.type=grpc --reporter.grpc.host-port=<endpoint>(填写对应的接入点信息) --agent.tags=<auth>(填写对应的认证信息)
    说明

    请将<endpoint><auth>替换成控制台集群配置页面相应客户端地域的接入点信息。获取接入点信息的方法,请参见前提条件。

Python和Jaeger Client环境

Python版本:3.8.5

Jaeger Client版本:4.6.0

在Python中安装以下Python包配置Jaeger Client环境。

certifi==2021.5.30
charset-normalizer==2.0.4
idna==3.2
jaeger-client==4.6.0
opentracing==2.4.0
requests==2.26.0
six==1.16.0
threadloop==1.0.2
thrift==0.13.0
tornado==6.1
urllib3==1.26.6

步骤二:创建Tracer对象

  1. 创建包含如下内容的Python文件。

    通过以下代码创建Tracer对象,并通过Tracer对象创建Span来上报数据至可观测链路 OpenTelemetry 版后台。

    import logging
    import time
    from jaeger_client import Config
    
    
    def construct_span(tracer):
        with tracer.start_span('AliyunTestSpan') as span:
            span.log_kv({'event': 'test message', 'life': 42})
            print("tracer.tages: ", tracer.tags)
            with tracer.start_span('AliyunTestChildSpan', child_of=span) as child_span:
                span.log_kv({'event': 'down below'})
            return span
    
    
    if __name__ == "__main__":
        log_level = logging.DEBUG
        logging.getLogger('').handlers = []
        logging.basicConfig(format='%(asctime)s %(message)s', level=log_level)
    
        config = Config(
            config={ # usually read from some yaml config
                'sampler': {
                    'type': 'const',
                    'param': 1,
                },
                'local_agent': {
                    # 注意这里是指定了JaegerAgent的host和port。
                    # 根据官方建议为了保证数据可靠性,JaegerClient和JaegerAgent运行在同一台主机内,因此reporting_host填写为127.0.0.1。
                    'reporting_host': '127.0.0.1',
                    'reporting_port': 6831,
                },
                'logging': True,
            },
            #这里填写应用名称
            service_name="mytest3",
            validate=True
        )
    
        # this call also sets opentracing.tracer
        tracer = config.initialize_tracer()
    
        span = construct_span(tracer)
    
        time.sleep(2)   # yield to IOLoop to flush the spans - https://github.com/jaegertracing/jaeger-client-python/issues/50
        tracer.close()  # flush any buffered spans
  2. 执行新建的Python文件。

在控制台查看数据

  1. 登录ARMS控制台,在左侧导航栏选择应用监控 > 应用列表

  2. 应用列表页面顶部选择目标地域,然后单击目标应用名称。

    说明

    语言列显示image图标的应用为接入应用监控的应用,显示-图标的应用为接入可观测链路 OpenTelemetry 版的应用。

  3. 应用总览页面,您可以查看该应用的性能关键指标和拓扑图详情。

    图1.应用总览界面

  4. 在左侧导航栏单击应用详情

    应用详情页面,您可以查看该应用的概览信息。图2.应用详情-概览界面

  5. 应用详情页面单击调用链路页签。

    调用链路页签,您可以查看该应用的调用链路。图3.应用详情-调用链路界面

参考信息

此处提供了Jaeger常见的使用方法,更多信息,请参见Jaeger官方文档

  • 创建Trace。

    from jaeger_client import Config
    
    def init_jaeger_tracer(service_name='your-app-name'):
        config = Config(config={}, service_name=service_name)
        return config.initialize_tracer()
  • 创建和结束Span。

    # 开始无Parent的Span。
    tracer.start_span('TestSpan') 
    # 开始有Parent的Span。
    tracer.start_span('ChildSpan', child_of=span)
    # 结束Span。
     span.finish()
  • 透传SpanContext。

    # 将spanContext透传到下一个Span中(序列化)。
    tracer.inject(
            span_context=span.context, format=Format.TEXT_MAP, carrier=carrier
        )
    # 解析透传过来的spanContxt(反序列化)。
    span_ctx = tracer.extract(format=Format.TEXT_MAP, carrier={})