- Lab
- Core Tech

Guided: Implement OpenTelemetry for Python Observability
This Guided Code Lab offers an engaging, hands-on experience for beginner to intermediate Python developers eager to enhance their observability skills. In this lab, you’ll manage a FastAPI-based microservice powering a critical e-commerce app. You’ll monitor health, diagnose performance issues, and use custom metrics to measure throughput—gaining hands-on experience with each. You’ll learn how to integrate OpenTelemetry into a Python application. You’ll start by installing and configuring the OpenTelemetry SDK, then progress to instrumenting Python code to capture distributed traces and custom metrics. You’ll explore how to export telemetry data to Jaeger, an observability platform, to visualize and analyze application performance. By the end of this lab, you’ll have the skills to implement observability in real-world Python applications, enabling you to monitor system health, pinpoint issues, and optimize performance across APIs, data pipelines, and microservices.

Path Info
Table of Contents
-
Challenge
Introduction and Set Up FastAPI
In this lab, you'll be working with the backend API for a bicycle parts manufacturer. The API is built using Python's FastAPI library and provides routes to manage various bike parts as they are removed from or added to the company's inventory.
Start by getting familiar with the code for the FastAPI application.
Review the
main.py
file. Make a note of the routes the application exposes for requests and the HTTP port the API server will use to listen for requests.The routes include:
/parts
: This route returns all the parts in the database./part/{PART_NUMBER}
: This route returns or updates details for a specific part.
The lab includes a virtual environment directory named
venv
. FastAPI applications typically use an additional layer of infrastructure to run properly. The bike parts API depends on Uvicorn, a Python web server that can be used to run FastAPI applications with minimal configuration and maximum performance.Uvicorn supports the Asynchronous Server Gateway Interface (ASGI) standard, which ensures compatibility with a wide range of Python web frameworks, including FastAPI. Now that the lab environment is configured to run the API for the bike parts manager, the next step is to configure OpenTelemetry.
-
Challenge
Install and Configure the OpenTelementry SDK
With the FastAPI application in place, the next step is to set up OpenTelemetry to collect observability data. OpenTelemetry provides distributed tracing and metrics capabilities, allowing you to monitor application performance and diagnose issues effectively.
The OpenTelemetry SDK consists of multiple components, including the core SDK, instrumentors, and exporters. This lab requires the following OpenTelemetry dependencies:
opentelemetry-sdk
: The core OpenTelemetry SDKopentelemetry-instrumentation-fastapi
: Library for instrumenting FastAPI applicationsopentelemetry-exporter-otlp-proto-grpc
: Library for exporting telemetry data using the OpenTelemetry Protocol (OTLP)
In the next task, you will install each of these dependencies using
pip
. Before integrating OpenTelemetry into the FastAPI application, it's important to verify that the SDK is correctly installed and understand how OpenTelemetry applications are instrumented.Open and review the file
examples/2_opentelemetry_sdk.py
, which demonstrates a basic OpenTelemetry setup:- It initializes a TracerProvider and assigns a service name.
- It configures a ConsoleSpanExporter to print trace data to the terminal.
- It registers a SimpleSpanProcessor to process spans.
- It generates a test span with a simple print statement. You have confirmed that OpenTelemetry is installed and observed how an application is instrumented with OpenTelemetry. Now apply these concepts in the next step by instrumenting the FastAPI application.
-
Challenge
Instrument the FastAPI Application
Instrumentation enables OpenTelemetry to capture trace data for incoming requests, helping you monitor request flow and performance.
Now that you've seen basic instrumentation, use a similar approach to to instrument the FastAPI application by updating the
main.py
file to include OpenTelemetry tracing.Modify
main.py
to include OpenTelemetry instrumentation. At this point, the FastAPI application is instrumented to allow traces to be reported for incoming requests. The next step is to collect custom metrics. -
Challenge
Collect Custom Metrics
Now that your FastAPI application is instrumented for tracing, the next step is to collect custom metrics. While traces help monitor request flows and performance bottlenecks, metrics provide quantitative insights into application behavior over time.
Before modifying the FastAPI application, review how a custom metric is defined and collected using OpenTelemetry. Now that you've seen how a counter metric works, apply the concept to the FastAPI application. Use these steps to observe the custom metric:
-
In the first Terminal, start the application.
-
In the second Terminal, run the following
curl
command a few times to update the "Brake Lever" inventory:curl -X 'PUT' 'http://127.0.0.1:9000/part/1?count=50'
-
Check the first Terminal for metric data to be printed every 15 seconds.
-
Stop the application using
Control
+C
. -
In the final telemetry output, look for the
metrics
report forupdate_count
. The value for"part_name": "Brake Lever"
should match the number of times you rancurl
. In this step, you explored how OpenTelemetry collects custom metrics and applied that knowledge to the FastAPI application.
While exporting metrics to the console is useful for quick validation, visualizing OpenTelemetry data in a dedicated observability tool provides deeper insights. A structured interface allows you to explore traces and metrics more effectively, making it easier to analyze application performance and identify issues.
In the next step, you'll configure the FastAPI application to export telemetry data to Jaeger, a powerful tool for visualizing and analyzing trace data.
-
-
Challenge
Export Traces to Jaeger
Now that the FastAPI application is collecting traces and custom metrics, the next step is to export telemetry data to Jaeger, a distributed tracing platform.
Jaeger allows you to visualize traces and diagnose performance bottlenecks in a structured way. In addition, the graphical interface makes working with traces much easier compared to using the Terminal. ### View the Example Traces in Jaeger
-
Open the Jaeger UI by selecting the lab's Web Browser tab and ensure the URL is
localhost:16686
. Then select the Open in a new browser tab button. -
In the Jaeger UI, look for Service and select example-export from the drop-down menu. Then select the button labeled Find Traces.
The display should update with the following:
- Dots on a graph with axes for Duration and Time
- A list of traces below the graph
-
Select one of the dots or one of the items from the list. This opens a timeline view for the trace and the spans it includes.
-
Near the top, left-side of the view, make a note of the information displayed including:
- Trace Start
- Duration
- Services
- Depth
- Total Spans
-
Under Service & Operation, select the trace name, example-export example-span. Under the newly displayed text example-span, expand the items under Tags: and Process:.
-
Using the drop-down menu on the far right side of the interface, experiment with different views of the trace by selecting:
- Trace Graph
- Trace Statistics
- Trace Spans Table
- Trace Flamegraph
- Trace JSON (will open in a new tab)
- Trace JSON (unadjusted) (will open in a new tab)
Update the
main.py
script to send traces to Jaeger.Send Traces to Jaeger from the FastAPI Application
After
main.py
is configured to export OpenTelemetry traces to Jaeger, start the application and verify that traces are being sent.- Select the file tab for
main.py
. - Select the first Terminal and then select the Run button.
- Confirm the application starts and is running on
http://127.0.0.1:9000
. - In the second Terminal, use
curl
to send several requests tohttp://localhost:9000/parts
. - Go to the Web Browser tab where the Jaeger interface is open and select Search in the top navigation bar.
- Under Service, select parts-manager and then select Find Traces. Confirm the display updates with traces for the Parts Manager API. Select one of the traces from the list.
- Expand the various parts of the timeline view under Service & Operation. In this step, you configured the FastAPI application to export traces to Jaeger using the OTLP exporter. With traces now visible in Jaeger's UI, you can analyze request flow, detect performance bottlenecks, and better understand how the application behaves under different conditions.
Exporting traces to a structured observability tool provides a significant advantage over viewing raw logs, allowing for deeper insights into latency, dependencies, and request patterns.
The next step is to use Jaegar to analyze telemetry data and optimize the application based on the collected traces.
-
-
Challenge
Analyze Telemetry and Optimize Application
Now that the FastAPI application is exporting traces to Jaeger, it's time to analyze telemetry data and make optimizations based on what you observe. In this step, you will identify a performance bottleneck, resolve the issue, and verify that the application performance has improved.
Generate Traces by Updating a Part
Send multiple PUT requests to update the inventory count for the Brake Lever part (ID:
1
).These requests will generate traces in Jaeger, allowing you to identify a performance issue.
Analyze Traces in Jaeger
- Navigate to the Jaeger UI to inspect the traces you just generated.
- Select parts-manager from the service dropdown.
- Click Find Traces.
- Open one of the traces for the
PUT /part/1
request. - Notice that the
PUT
request duration is between 1 and 3 seconds. - Review the details on the Jaegar interface to observe the request's Duration.
The file
parts_manager.py
contains the backend logic for managing parts.
A
time.sleep()
call has been added to the backend to simulate network latency in the application.Optimize the application by removing the artificial latency from the backend script.
Confirm Improved Performance
-
If the FastAPI application is still running in the first Terminal, stop it by typing
Control
+C
. -
Restart the application by pressing the Run button.
-
In the second Terminal, repeat the command to update a part:
curl -X PUT "http://127.0.0.1:9000/part/1?count=10"
-
Return to the Jaeger UI and select:
- Search
- Service:
parts-manager
- Operation:
PUT /part/{part_id}
- Find Traces
-
Select the checkbox next to two traces, one that was created before the code was updated and another that was created after the update.
Tip: Use the timestamp on the far right side of each trace to help determine when the trace was created.
-
Select Compare Traces.
-
On the updated display, compare the duration for the traces labeled as A and B. The trace representing the updated
parts-manager.py
should have a much shorter duration than the previous trace. In this step, you analyzed trace data using Jaeger to identify a bottleneck in the FastAPI application. By removing the delay, you improved the performance of the application's update operation.
What's a lab?
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Provided environment for hands-on practice
We will provide the credentials and environment necessary for you to practice right within your browser.
Guided walkthrough
Follow along with the author’s guided walkthrough and build something new in your provided environment!
Did you know?
On average, you retain 75% more of your learning if you get time for practice.