Lightstep from ServiceNow Logo






Lightstep from ServiceNow Logo

Getting Started with OpenTelemetry Alphas: Python

Alex Boten

by Alex Boten

Getting Started with OpenTelemetry Alphas: Python

Explore more OpenTelemetry Blogs

New Alpha versions of the Python OpenTelemetry API and SDK packages have just been released, and it's time to take them for a test drive! This guide walks through installing the required packages, generating tracing information and propagating context across processes via HTTP.


In order to get started with OpenTelemetry in Python, we'll need to install the API and SDK packages. This can be done via pip. Note: this requires Python 3.4 or newer.

pip install opentelemetry-api opentelemetry-sdk

Creating a span

In this first example, we'll use the ConsoleSpanExporter to get us going:

from opentelemetry import trace
from opentelemetry.context import Context
from opentelemetry.sdk.trace import Tracer
from opentelemetry.sdk.trace.export import ConsoleSpanExporter
from opentelemetry.sdk.trace.export import BatchExportSpanProcessor

trace.set_preferred_tracer_implementation(lambda T: Tracer())
tracer = trace.tracer()
# configure the ConsoleSpanExporter as our exporter
span_processor = BatchExportSpanProcessor(ConsoleSpanExporter())
with tracer.start_as_current_span('foo'):
    with tracer.start_as_current_span('bar'):
        with tracer.start_as_current_span('baz'):

After running the code, the tracing information will appear in the console:

AsyncRuntimeContext({'current_span': Span(name="baz", context=SpanContext(trace_id=0xddf0ac0d009a33320781ccac56018ead, span_id=0x2202e5e00e02a985, trace_state={}))})
Span(name="baz", context=SpanContext(trace_id=0xddf0ac0d009a33320781ccac56018ead, span_id=0x2202e5e00e02a985, trace_state={}), kind=SpanKind.INTERNAL, parent=Span(name="bar", context=SpanContext(trace_id=0xddf0ac0d009a33320781ccac56018ead, span_id=0x10a1a831a5210e6a, trace_state={})), start_time=2019-11-05T23:50:06.569282Z, end_time=2019-11-05T23:50:06.569359Z)
Span(name="bar", context=SpanContext(trace_id=0xddf0ac0d009a33320781ccac56018ead, span_id=0x10a1a831a5210e6a, trace_state={}), kind=SpanKind.INTERNAL, parent=Span(name="foo", context=SpanContext(trace_id=0xddf0ac0d009a33320781ccac56018ead, span_id=0xc4beccc7fbb46181, trace_state={})), start_time=2019-11-05T23:50:06.569255Z, end_time=2019-11-05T23:50:06.569482Z)
Span(name="foo", context=SpanContext(trace_id=0xddf0ac0d009a33320781ccac56018ead, span_id=0xc4beccc7fbb46181, trace_state={}), kind=SpanKind.INTERNAL, parent=None, start_time=2019-11-05T23:50:06.569221Z, end_time=2019-11-05T23:50:06.569561Z)

Console output is a great start. Now, let's try sending our traces into Jaeger. The following command will launch the "handy in dev" but "don't use it in PROD" all-in-one Jaeger Docker container:

docker run -d -p 6831:6831/udp -p 16686:16686 jaegertracing/all-in-one:latest

You should be able to visit http://localhost:16686:

pip install opentelemetry-ext-jaeger

With those in place, we can now configure the JaegerSpanExporter to send traces to the container we just launched.

from opentelemetry.ext import jaeger
# create a JaegerSpanExporter
jaeger_exporter = jaeger.JaegerSpanExporter(
    service_name="getting-started-jaeger", agent_host_name="localhost", agent_port=6831,

span_processor = BatchExportSpanProcessor(jaeger_exporter)

Navigating through the Jaeger interface using a browser http://localhost:16686, we should now be able to find the trace that was just created.

Propagating the Context

The next example will walk through making a request from a client to a server, which allows us to test context propagation across process boundaries. Let's start with the dependencies:

pip install flask opentelemetry-ext-wsgi opentelemetry-ext-http-requests

For the server, we'll use the OpenTelemetryMiddleware.

import flask
import requests

from opentelemetry import trace
from opentelemetry.ext import http_requests
from opentelemetry.ext.wsgi import OpenTelemetryMiddleware

app = flask.Flask(__name__)
app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app)

def hello():
    with tracer.start_as_current_span("parent"):
    return "hello"

if __name__ == "__main__":

The client code will make a request to the server using the Requests module, which we'll instrument via the http_request OpenTelemetry extension.

import requests

from opentelemetry import trace
from opentelemetry.ext import http_requests

response = requests.get(url="")

That's it! You're now ready to instrument your Python code with OpenTelemetry! If you're interested in contributing but aren't sure how to, be sure to check out the recent blog post on How to Start Contributing repo if you'd like to get involved!

Interested in joining our team? See our open positions here.

Explore more OpenTelemetry Blogs