Jaeger in Python using OpenTelemetry

Matías Salinas
3 min readMar 18, 2023

--

Introduction

We’ll learn how to integrate a Python API built with Flask with Jaeger, an open-source distributed tracing system, using OpenTelemetry. We’ll start by explaining what Jaeger and OpenTelemetry are and how they can help improve your application’s observability. Then, we’ll demonstrate how to set up a local Jaeger server using Jaeger All-in-One and, finally, how to instrument a Python Flask API to send trace data to Jaeger.

What is Jaeger?

Jaeger is an open-source distributed tracing system that provides monitoring, observability, and troubleshooting capabilities for microservice-based architectures. It helps developers trace the flow of requests across services and gain insights into the performance and behavior of their applications. Jaeger is part of the Cloud Native Computing Foundation (CNCF) and is compatible with the OpenTracing and OpenTelemetry standards.

What is OpenTelemetry?

OpenTelemetry is a CNCF project that aims to provide a single set of APIs, libraries, agents, and instrumentation for distributed tracing and metrics collection. It’s a merger of the OpenTracing and OpenCensus projects and provides a vendor-neutral framework that allows developers to instrument their applications with minimal effort, while also supporting various tracing and metrics backends.

Setting up a local Jaeger server with Jaeger All-in-One

To set up a local Jaeger server for development and testing purposes, we can use Jaeger All-in-One, which is a pre-built Docker image that includes all Jaeger components (Agent, Collector, Query, and Ingester) in a single executable.

First, make sure you have Docker installed on your machine. Then, run the following command to pull and run the Jaeger All-in-One Docker image:

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 14250:14250 \
-p 9411:9411 \
jaegertracing/all-in-one:1.28

After running this command, you’ll have a local Jaeger server running on your machine. You can access the Jaeger UI at http://localhost:16686.

Integrating a Python Flask API with Jaeger using OpenTelemetry

Now that we have a Jaeger server running, let’s create a simple Python Flask API and integrate it with Jaeger using OpenTelemetry. First, install the required dependencies:

pip install Flask opentelemetry-sdk opentelemetry-instrumentation-flask opentelemetry-exporter-jaeger

Next, create a single Python file with the following content:

import uuid
from flask import Flask, jsonify
from opentelemetry import trace
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.instrumentation.flask import FlaskInstrumentor

app = Flask(__name__)

# Configure OpenTelemetry
trace.set_tracer_provider(
TracerProvider(
resource=Resource.create({"service.name": "ms-api"})
)
)

jaeger_exporter = JaegerExporter(
agent_host_name="localhost",
agent_port=6831,
)

# Configure the trace processor
span_processor = BatchSpanProcessor(jaeger_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)

# Instrument Flask
FlaskInstrumentor().instrument_app(app)

@app.route("/")
def hello():
with trace.get_tracer(__name__).start_as_current_span("hello") as span:
tracking_id = str(uuid.uuid4())
span.set_attribute("tracking_id", tracking_id)
return jsonify({"message": "Hello from Flask API!", "tracking_id": tracking_id})

@app.route("/api")
def api():
with trace.get_tracer(__name__).start_as_current_span("api") as span:
tracking_id = str(uuid.uuid4())
span.set_attribute("tracking_id", tracking_id)
return jsonify({"result": "You are at the API endpoint.", "tracking_id": tracking_id})

if __name__ == "__main__":
app.run(debug=True)

# Uninstrument Flask when the application closes
FlaskInstrumentor().uninstrument_app(app)

This example creates a simple Flask API with two routes (“/” and “/api”). It also configures OpenTelemetry to send traces to a Jaeger agent on “localhost” and port 6831. Make sure you have a Jaeger agent running on your machine to receive the traces, as we set up earlier with the Jaeger All-in-One Docker image.

Makes some API calls

curl http://127.0.0.1:5000

After running the application and making some requests to the routes, you should be able to see the traces in the Jaeger UI at http://localhost:16686.

You should see something similar to this

Example repository: https://github.com/msalinas92/jaeger-client-python

Conclusion

We saw how to integrate a Python Flask API with Jaeger using OpenTelemetry. By leveraging Jaeger and OpenTelemetry, you can improve your application’s observability and gain insights into its performance and behavior. The local Jaeger server setup with Jaeger All-in-One is perfect for development and testing purposes, while the instrumentation process with OpenTelemetry is simple and vendor-neutral.

--

--

Matías Salinas
Matías Salinas

No responses yet