This is a client-side library that can be used to instrument Python apps for distributed trace collection, and to send those traces to Jaeger. See the OpenTracing Python API for additional detail.
apt-get install python-dev
pip install jaeger-client
import opentracing
import logging
import time
from jaeger_client import Config
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,
},
'logging': True,
},
service_name='your-app-name',
)
tracer = config.initialize_tracer()
with opentracing.tracer.start_span('TestSpan') as span:
span.log_event('test message', payload={'life': 42})
with opentracing.tracer.start_span('ChildSpan', child_of=span) as child_span:
span.log_event('down below')
time.sleep(2) # yield to IOLoop to flush the spans - https://github.com/uber/jaeger-client-python/issues/50
tracer.close() # flush any buffered spans
The opentracing-contrib project has a few modules that provide explicit instrumentation support for popular frameworks like Django and Flask.
At Uber we are mostly using the opentracing_instrumentation module that provides:
- explicit instrumentation for HTTP servers, and
- implicit (monkey-patched) instrumentation for several popular libraries like
urllib2
,redis
,requests
, some SQL clients, etc.
The recommended way to initialize the tracer for production use:
from jaeger_client import Config
config = Config(config={}, service_name='your-app-name)
tracer = config.initialize_tracer()
For development, some parameters can be passed via config
dictionary, as in the Getting Started example above. For more details please see the Config class.
The OpenTracing API defines a sampling.priority
standard tag that
can be used to affect the sampling of a span and its children:
from opentracing.ext import tags as ext_tags
span.set_tag(ext_tags.SAMPLING_PRIORITY, 1)
Jaeger Tracer also understands a special HTTP Header jaeger-debug-id
,
which can be set in the incoming request, e.g.
curl -H "jaeger-debug-id: some-correlation-id" http://myhost.com
When Jaeger sees this header in the request that otherwise has no tracing context, it ensures that the new trace started for this request will be sampled in the "debug" mode (meaning it should survive all downsampling that might happen in the collection pipeline), and the root span will have a tag as if this statement was executed:
span.set_tag('jaeger-debug-id', 'some-correlation-id')
This allows using Jaeger UI to find the trace by this tag.
This library internally uses Zipkin Thrift data model and conventions, but if you want to use it directly with other Zipkin libraries & backend, it needs:
- different wire codecs to transmit
trace context as
X-B3-*
headers - a reporter that will submit traces to Zipkin backend over Zipkin-supported transports like Kafka or HTTP
Both of these things are easy to add (e.g. it was done in jaegertracing/jaeger-client-java#34), but it is not a priority for the Uber team since we are using a different backend. We will welcome PRs that provide that functionality.