针对ASGI框架的Zipkin集成。

starlette-zipkin的Python项目详细描述


特点

  • sentry-asgi为样板
  • 基于aiozipkin-异步兼容zipkin库的客户端
  • 服务器(任何与zipkin2.0兼容的服务器都可以工作)-Jaeger示例
  • 跟踪http流量的中间件
  • 将跟踪标头注入响应
  • 从请求中提取跟踪标头
  • 上下文变量,每个传入请求的范围-可能用于检测较低级别操作的跟踪

快速入门

运行跟踪服务器

捷格一体机

按照https://www.jaegertracing.io/docs/1.13/getting-started/中的说明操作

$ docker run -d --name jaeger \
  -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
  -p 5775:5775/udp \
  -p 6831:6831/udp \
  -p 6832:6832/udp \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 14268:14268 \
  -p 9411:9411 \
  jaegertracing/all-in-one:latest

位于http://localhost:16686/的跟踪查询

添加中间件

^{pr2}$

默认情况下,客户端发射到http://localhost:9411。在

所有流量在http://localhost:16686/处捕获并可用

jaeger

高级教程

对于较低级别的跟踪工具,有两个辅助函数可用:

  • get_root_span-返回与当前请求相对应的span实例
  • get_tracer-返回与当前请求相对应的跟踪程序实例
import json
import asyncio
import uvicorn
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route

from starlette_zipkin import (
    ZipkinMiddleware,
    ZipkinConfig,
    get_root_span,
    get_tracer,
    B3Headers,
    UberHeaders
)


async def homepage(request):
    root_span = get_root_span()
    tracer = get_tracer()

    with tracer.new_child(root_span.context) as child_span:
        # ! if headers not explicitly provided,\
        # root span from middleware injects headers
        # and becomes the parent for subsequet services
        headers = child_span.context.make_headers()
        child_span.name("NewParent")
        child_span.annotate(
            "Child, sleeps for 1, injects headers and becomes parent"
        )
        await asyncio.sleep(1)
        return JSONResponse({"hello": "world"}, headers=headers)


routes = [
    Route("/", JSONResponse({"status": "OK"})),
    Route("/homepage", homepage),
]

app = Starlette(debug=True, routes=routes)

config = ZipkinConfig(
    host="localhost",
    port=9411,
    service_name="service_name",
    sample_rate=1.0,
    inject_response_headers=True,
    force_new_trace=False,
    json_encoder=json.dumps,
    header_formatter=B3Headers
)
app.add_middleware(ZipkinMiddleware, config=config)

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, log_level="info", reload=True)

这样,我们就可以在其他服务的呼叫中进行跟进。这里我们使用同一个服务器,但将跟踪头传递给后续调用以演示未来的跨度:

逐步示例:

  1. 客户端发送

    GET /homepage HTTP/1.1
    Host: localhost:8000
    User-Agent: PostmanRuntime/7.15.2
    Accept: */*
    Cache-Control: no-cache
    Postman-Token: 519bda7e-bb9c-40c4-a9a5-c8df5524ced2,189c4252-322a-415d-a637-ecdca9a79cb0
    Host: localhost:8000
    Accept-Encoding: gzip, deflate
    Connection: keep-alive
    cache-control: no-cache
    

    服务器响应

    X-B3-TraceId: ddfc5b2181e08d3360e4072522c5235a
    X-B3-SpanId: 34dcd9a29c01efe2
    X-B3-Flags: 0
    X-B3-Sampled: 1
    x-b3-parentspanid: b9872416ce86e870
    
    {"hello":"world"}
    
  2. 客户机通过从标头传递上下文来跟踪第一个跟踪

    GET /homepage HTTP/1.1
    Host: localhost:8000
    X-B3-TraceId: ddfc5b2181e08d3360e4072522c5235a
    X-B3-SpanId: 34dcd9a29c01efe2
    X-B3-Flags: 0
    X-B3-Sampled: 1
    x-b3-parentspanid: b9872416ce86e870
    User-Agent: PostmanRuntime/7.15.2
    Accept: */*
    Cache-Control: no-cache
    Postman-Token: 2eb6d43a-ed2c-4291-b0c4-c41335e40f6b,bd6376b5-4ab9-45bd-91ab-10f4831547e7
    Host: localhost:8000
    Accept-Encoding: gzip, deflate
    Connection: keep-alive
    cache-control: no-cache
    

    服务器响应(同样使用一组新的可选跟踪ID)

    X-B3-TraceId: ddfc5b2181e08d3360e4072522c5235a
    X-B3-SpanId: 3c550de9d7cb62aa
    X-B3-Flags: 0
    X-B3-Sampled: 1
    x-b3-parentspanid: ecb56ce4eba6aed5
    
    {
    "hello": "world"
    }
    

这两个调用都由Jaeger收集并在WebUI中提供

配置

要更改中间件配置,请提供一个config对象(这里的默认值如下所示)

import json
from starlette_zipkin import ZipkinMiddleware, ZipkinConfig, B3Headers

config = ZipkinConfig(
    host="localhost",
    port=9411,
    service_name="service_name",
    sample_rate=1.0,
    inject_response_headers=True,
    force_new_trace=False,
    json_encoder=json.dumps,
    header_formatter=B3Headers
)

app = Starlette()

app.add_middleware(ZipkinMiddleware, config=config)

其中:

  • host = "localhost"
    • 默认本地主机,需要设置为指向收集跟踪的代理(例如jaeger agent)
  • port = 9411
    • 默认端口,需要设置为指向收集跟踪的代理(例如jaeger agent)
    • 9411是zipkin客户机/代理(和jaeger代理)的默认值
    • 确保可接近
  • service_name = "service_name"
    • 服务的名称
  • sample_rate = 1.0
    • zipkin采样率,默认每个呼叫采样
  • inject_response_headers = True
    • 自动插入响应标头
  • force_new_trace = False
    • 如果传入请求包含跟踪标头,则不创建子跟踪
  • json_encoder=json.dumps
    • 可以提供json编码器,默认为json转储。它用于为jaegerui格式化字典。在
  • header_formatter=B3Headers
    • 默认为b3标题格式。可以切换到UberHeaders,这意味着uber-trace-id格式。在

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
使用java从mysql备份特定的表   方法引用中的java错误返回类型:无法转换反应器。果心出版商单核反应堆。果心出版商单声道?扩展R>   java为什么我的e4应用程序插件不能被调用   swing为什么在java中JComboBox的ListCellRenderer上出现类强制转换异常?   java无直接方法<init>(Ljava/lang/reflect/method;IL2/Converter;)V类Lretrofit2/ParameterHandler$Body   java监控BufferedInputStream下载进度   java Springboot外部文件数据库配置   java Selenium WebDriver StaleElementReferenceException在使用click()时出现异常   在java中对传递给静态函数的参数的更改   为什么x==(x=y)和(x=y)=x不一样?   java我应该为我的应用程序创建一个片段吗?   java HashMap何时以及如何将bucket从链表转换为红黑树?   java文件读/写的正确顺序   在java中在哪里使用对象类?   javacom。数据税。驾驶员果心例外情况。InvalidQueryException:未配置的表架构\u键空间   Java如何在Arangodb上创建边?