Zipkin integration for ASGI frameworks.
Project description
AioZipkin middleware for Starlette/FastApi
Features
- Using sentry-asgi as a boilerplate
- Client - based on
aiozipkin
- async compatible zipkin library - Server (any zipkin 2.0 compatible server will work) - Jaeger examples
- Middleware tracing http traffic
- Injecting tracing headers to responses
- Extracting tracing headers from requests
- Context variable with the span for every incoming request - possible to instrument tracing of lower level operations
Quick start
Run tracing server
Jaeger all-in-one
Follow instructions at https://www.jaegertracing.io/docs/latest/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
Trace queries at http://localhost:16686/
Add middleware
import uvicorn
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
from starlette_zipkin import ZipkinMiddleware
routes = [
Route("/", JSONResponse({"status": "OK"})),
]
app = Starlette(debug=True, routes=routes)
app.add_middleware(ZipkinMiddleware)
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000, log_level="info", reload=True)
By default the client emits to http://localhost:9411
.
All traffic is captured and available at http://localhost:16686/
Advanced Tutorial
To instrument tracing at lower levels, two helper functions are available:
get_root_span
- returns the span instance corresponding to current requestget_tracer
- returns the tracer instance corresponding to current requesttrace
- create span in the trace
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,
trace,
B3Headers,
UberHeaders
)
async def homepage(request):
with trace("NewParent") 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.kind("SERVER")
# possible span kinds
# CLIENT = "CLIENT"
# SERVER = "SERVER"
# PRODUCER = "PRODUCER"
# CONSUMER = "CONSUMER"
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)
This way we are able to followup at the call from a different service. Here we use the same server, but pass the tracing headers to subsequent calls to demonstrate future spans:
Configuration
To change the middleware configuration, provide a config object (here with default values being as shown)
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)
where:
host = "localhost"
- default local host, needs to be set to point at the agent that collects traces (e.g. jaeger-agent)
port = 9411
- default port, needs to be set to point at the agent that collects traces (e.g. jaeger-agent)
- 9411 is default for zipkin client/agent (and jaeger-agent)
- make sure to make accessible
service_name = "service_name"
- name of the service
sample_rate = 1.0
- zipkin sampling rate, default samples every call
inject_response_headers = True
- automatically inject response headers
force_new_trace = False
- if
True
, does not create child traces if incoming request contains tracing headers
- if
json_encoder=json.dumps
- json encoder can be provided, defaults to json dumps. It is used to format dictionaries for Jaeger UI.
header_formatter=B3Headers
- defaults to b3 headers format. Can be switched to UberHeaders, which imply the
uber-trace-id
format.
- defaults to b3 headers format. Can be switched to UberHeaders, which imply the
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file starlette-zipkin-0.3.0.tar.gz
.
File metadata
- Download URL: starlette-zipkin-0.3.0.tar.gz
- Upload date:
- Size: 10.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.2.0 pkginfo/1.8.3 requests/2.28.1 setuptools/65.3.0 requests-toolbelt/0.9.1 tqdm/4.64.1 CPython/3.8.10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3c8270d2de79fb07e97b7ab1649550e3dfa9fd27c63a62f971cbe0cf24f4c1cc |
|
MD5 | 829f90d74339a650aa29112d24421fa7 |
|
BLAKE2b-256 | 820248cb903e2ee36b3eb5e78c0a5c8589a6150bf6656f096335c5addd149999 |
File details
Details for the file starlette_zipkin-0.3.0-py3-none-any.whl
.
File metadata
- Download URL: starlette_zipkin-0.3.0-py3-none-any.whl
- Upload date:
- Size: 10.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.2.0 pkginfo/1.8.3 requests/2.28.1 setuptools/65.3.0 requests-toolbelt/0.9.1 tqdm/4.64.1 CPython/3.8.10
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 36144dbb6e358961861f2e9f2dc6d27a94f6d9980ad22a04fb7ea82f584a25b1 |
|
MD5 | fc571be63f6b49148d11be48a754887a |
|
BLAKE2b-256 | 6ea5329f1e88c69494451a4f8305767518a6160536db83beae294f4b0f94cb0f |