# OpenTelemetry with Flask: A Comprehensive Guide for Web Apps

> Learn how to integrate OpenTelemetry with Flask to monitor and trace your web app’s performance with easy-to-follow setup and troubleshooting tips.

Source: https://last9.io/blog/opentelemetry-with-flask/

Observability has become a critical aspect of web application development. If you're working with Flask, a popular microweb framework for Python, you might have heard of OpenTelemetry, the open-source framework that provides a set of APIs, libraries, agents, and instrumentation to enable the collection of metrics, traces, and logs from your applications.

But how do you integrate OpenTelemetry with Flask? And why should you do it in the first place?

In this guide, we’ll walk through the process of setting up OpenTelemetry with Flask, explore the key concepts, and highlight best practices to ensure that your application’s observability is top-notch.

## What is OpenTelemetry?

OpenTelemetry is an open-source project that provides a unified set of APIs, libraries, and tools for collecting distributed traces, metrics, and logs from applications.

With OpenTelemetry, you can collect performance data from your application, track its behavior across microservices, and gain valuable insights into how your system behaves under different conditions.

OpenTelemetry with Flask helps you gain a better understanding of your application’s performance, identify bottlenecks, track errors, and improve the overall user experience.

It works by automatically capturing telemetry data from your application and sending it to your observability backend (like Prometheus, Jaeger, or OpenTelemetry-compatible platforms).

## Why Use OpenTelemetry with Flask?

Flask is a powerful micro-framework, but managing observability can be challenging when your app grows. Flask applications often involve multiple components, from databases to third-party services, making it hard to pinpoint performance issues or bugs.

By integrating OpenTelemetry with Flask, you unlock several benefits:

### End-to-end Tracing

Trace requests from the user’s browser all the way to your backend services, helping you pinpoint latency issues and understand the lifecycle of each request.

### Automatic Metrics Collection

Track key performance indicators like request durations, error rates, and throughput automatically without much setup.

### Log Correlation

Correlate logs with traces and metrics for a more comprehensive view of application health.

### Proactive Issue Detection

Use metrics and traces to detect performance issues, slow queries, and other anomalies before they affect users.

### Improved Debugging

When issues arise, having traces and metrics makes debugging faster and more efficient.

## Setting Up a Virtual Environment for Your Flask Application

Before integrating OpenTelemetry with Flask, set up a clean environment for your application. Using a virtual environment ensures that your project’s dependencies are isolated from your global Python setup. This helps avoid version conflicts and makes managing your project’s libraries more manageable.

Here’s how you can create and set up a virtual environment for your Flask application:

### Step 1: Install virtualenv

First, install virtualenv, a tool for creating isolated Python environments. You can install it using pip:

```
pip install virtualenv
```

### Step 2: Create a Virtual Environment

Once virtualenv is installed, navigate to your project directory and create a new virtual environment by running:

```
virtualenv venv
```

This will create a directory named `venv` within your project folder, containing a fresh Python environment. You can name the virtual environment anything you want, but `venv` is a common convention.

### Step 3: Activate the Virtual Environment

Next, activate the virtual environment to install libraries and run Flask within this isolated environment.

On Windows, run:

```
venv\Scripts\activate
```

On macOS/Linux, run:

```
source venv/bin/activate
```

Once activated, your command prompt will change to show the virtual environment’s name (usually `(venv)`), indicating that you’re now working inside an isolated environment.

### Step 4: Install Flask and Other Dependencies

With your virtual environment activated, you can now install Flask and any other dependencies for your project, including OpenTelemetry.

To install Flask:

```
pip install Flask
```

To install OpenTelemetry and other necessary packages:

```
pip install opentelemetry-api opentelemetry-sdk opentelemetry-instrumentation-flask opentelemetry-exporter-jaeger
```

You can add more packages as needed for your project. All dependencies will be installed locally in the `venv` folder, ensuring your global Python environment remains untouched.

### Step 5: Deactivate the Virtual Environment

When you’re done working in the virtual environment, deactivate it by running:

```
deactivate
```

This will return you to your system’s global Python environment.

### Step 6: Managing Dependencies with `requirements.txt`

To make it easier to manage and share your project’s dependencies, create a `requirements.txt` file. This file contains a list of all the packages installed in your virtual environment.

To generate the `requirements.txt` file, run:

```
pip freeze > requirements.txt
```

Now, anyone else working on the project can create the same environment by running:

```
pip install -r requirements.txt
```

This simplifies setting up the project on a different machine or for a new developer!

### Why Use a Virtual Environment?

**Isolation**

Keep your project dependencies separate from other projects or the system’s global packages.

**Easier Dependency Management**

You can track exactly what packages your project requires, ensuring consistent setups across machines and teams.

**Preventing Version Conflicts**

Avoids conflicts between different versions of the same package across projects.

With the virtual environment set up, you’re now ready to start building your Flask app and integrating OpenTelemetry for full observability!

## Setting Up OpenTelemetry with Flask: A Step-by-Step Guide

Now, let’s get hands-on and see how to set up OpenTelemetry in your Flask application. Here’s how you can do it in a few simple steps:

### Step 1: Install the Required Packages

To get started, you’ll need to install the necessary OpenTelemetry libraries. You can install them using pip:

```
pip install opentelemetry-api opentelemetry-sdk opentelemetry-instrumentation-flask opentelemetry-exporter-jaeger
```

This command installs:

- **opentelemetry-api**: The core API that defines the interfaces for tracing, metrics, and logs.
- **opentelemetry-sdk**: The SDK implementation of the OpenTelemetry API.
- **opentelemetry-instrumentation-flask**: The Flask-specific integration that automatically instruments your Flask app.
- **opentelemetry-exporter-jaeger**: The Jaeger exporter, sends trace data to Jaeger, a popular observability platform.

You can replace Jaeger with your preferred backend exporter, such as `opentelemetry-exporter-prometheus` for Prometheus integration.

### Step 2: Set Up OpenTelemetry in Your Flask App

Next, you’ll need to configure OpenTelemetry to start capturing data from your Flask app. Here’s a simple example of setting it up:

```
from flask import Flask
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
from opentelemetry.instrumentation.flask import FlaskInstrumentor

# Initialize the Flask app
app = Flask(__name__)

# Set up OpenTelemetry tracing
trace.set_tracer_provider(TracerProvider())
jaeger_exporter = JaegerExporter(
    agent_host_name='localhost',  # Your Jaeger agent's host
    agent_port=6831,  # The port your Jaeger agent is listening on
)
span_processor = BatchSpanProcessor(jaeger_exporter)
trace.get_tracer_provider().add_span_processor(span_processor)

# Instrument Flask with OpenTelemetry
FlaskInstrumentor().instrument_app(app)

@app.route('/')
def hello():
    return "Hello, OpenTelemetry with Flask!"

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

In this example:

- **Tracer Provider**: We set up the OpenTelemetry TracerProvider, which handles the tracing of requests.
- **Jaeger Exporter**: The Jaeger exporter sends trace data to a Jaeger instance running locally. If you’re using another observability backend, you’ll need to use the appropriate exporter.
- **Flask Instrumentation**: The `FlaskInstrumentor().instrument_app(app)` line automatically instruments your Flask app to capture request data and generate spans.

### Step 3: Verify the Integration

Once the setup is complete, run your Flask application:

```
python app.py
```

Now, visit **http://127.0.0.1:5000/** in your browser. If everything is set up correctly, you should see traces generated in your chosen observability backend (like Jaeger or Prometheus).

You can visualize the traces and analyze the performance of each HTTP request, which will help you identify bottlenecks and troubleshoot issues.

## Best Practices for Using OpenTelemetry with Flask

### Instrument Everything

Ensure that all your major components—such as databases, external APIs, and background tasks—are instrumented. This provides a complete picture of your application’s performance.

### Use Contextual Data

Add metadata to your spans (e.g., user ID, request ID) to make it easier to trace individual requests through your application.

### Set Sampling Rates

OpenTelemetry provides sampling options. For production environments, set a reasonable sampling rate to avoid overwhelming your observability backend with too much data.

### Monitor Performance Regularly

Use the collected metrics and traces to regularly monitor your Flask app. Set up alerts to get notified of any performance degradation or unusual activity.

### Optimize Your Backend

Depending on your observability backend (e.g., Jaeger, Prometheus), consider optimizing the setup for performance. For instance, make sure your tracing backend can handle a large volume of requests if you're scaling your Flask app.

Use the collected metrics and traces to monitor your Flask app regularly. Set up alerts to be notified of any performance degradation or unusual activity.

## How to Send Traces from a Flask App to Last9 with OpenTelemetry

### Prerequisites

Before you begin, make sure you have the following:

- A Flask application set up and running.
- A Last9 account with a created cluster and OTLP credentials (including:
  - `endpoint`
  - `auth_header` from the Integrations page).

### Installing OpenTelemetry Packages

To get started, install the necessary OpenTelemetry packages by running the following command:

```
pip install python-dotenv opentelemetry-distro opentelemetry-exporter-otlp
```

Next, install the required instrumentation packages:

```
opentelemetry-bootstrap -a install
```

For more information on these packages, visit the [OpenTelemetry Python Libraries](https://opentelemetry-python.readthedocs.io/en/stable/).

### Setting Up Environment Variables

After installing the packages, configure your environment variables by running:

```
export OTEL_SERVICE_NAME=flask-app
export OTEL_EXPORTER_OTLP_ENDPOINT=<ENDPOINT>
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=<BASIC_AUTH_HEADER>"
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
```

Make sure to replace `<BASIC_AUTH_HEADER>` it with the URL-encoded version of your basic auth header.

### Running the Application

With the environment variables set, start your Flask application by running:

```
opentelemetry-instrument flask run
```

### Visualizing Your Data

Once your Flask app is running, you can view the trace data in the APM dashboard on Last9. This will allow you to gain insights into your application's performance, such as latency, errors, and overall system health.

## Troubleshooting Tips for Common Instrumentation Issues

When integrating OpenTelemetry with Flask or any other application, it's common to encounter issues during the instrumentation process. Here are some troubleshooting tips to help you resolve common problems:

### 1\. Missing or Incomplete Traces

**Issue**: You notice that traces are missing or incomplete in your observability backend.

**Solution**:

- **Check if the OpenTelemetry SDK is initialized properly**: Ensure that your tracing provider and exporters are set up correctly. If you missed any setup steps or environment variables, traces may not be sent.
- **Verify service name**: Ensure the `OTEL_SERVICE_NAME` environment variable is set correctly. A missing or incorrect service name may cause traces to be recorded but not properly categorized in the backend.
- **Check your network connection**: Make sure that the endpoint for your trace exporter (e.g., Jaeger, OTLP) is reachable. Network issues or incorrect endpoint URLs can block data transmission.

### 2\. Environment Variables Not Set Properly

**Issue**: The application is not sending any traces despite the instrumentation code being in place.

**Solution**:

- **Double-check the environment variables**: Any incorrect values, such as typos in the OTLP endpoint or missing authorization headers, can prevent OpenTelemetry from exporting the data.
- **If working locally**: Ensure that the environment variables are exported in the shell session where you're running your Flask app.
- **Use `printenv` or `echo $VAR_NAME`**: Verify the values of the environment variables at runtime to ensure they are correctly set.

### 3\. High Latency in Tracing Data

**Issue**: Traces are showing high latency or delay in the dashboard.

**Solution**:

- **Adjust sampling rates**: In a production environment, you might be using a low sampling rate to avoid overloading your backend. If latency is a concern, try increasing the sample rate or optimizing trace capture logic.
- **Optimize export batch settings**: In OpenTelemetry, traces are exported in batches. You can adjust the batch size and the flush interval to fine-tune how quickly traces are sent. For example, the default setting might be too slow for high-throughput systems.
- **Review exporter configuration**: Ensure the exporter is properly configured to send traces promptly. Check for any errors or timeouts in the exporter logs.

### 4\. Errors in OpenTelemetry Initialization

**Issue**: OpenTelemetry fails to start or throws errors on startup.

**Solution**:

- **Check the logs**: Both OpenTelemetry and the Flask application should provide error messages if initialization fails. Look for missing dependencies or incorrect versions of libraries.
- **Verify compatibility**: Ensure you’re using compatible versions of OpenTelemetry packages and the Flask integration library. An incompatible version might cause failures.
- **Reinstall dependencies**: Sometimes, a clean install helps. Remove the `venv` folder and reinstall the packages to make sure everything is set up correctly.

## Exporter Options in OpenTelemetry: Setup and Troubleshooting

OpenTelemetry supports various exporters to send trace and metric data to backends for analysis. Understanding how to configure and troubleshoot these exporters is crucial for ensuring smooth telemetry data flow. Here are some common exporter options and troubleshooting tips:

### 1\. OTLP Exporter

The OpenTelemetry Protocol (OTLP) exporter is widely used to send telemetry data (traces, metrics, logs) to OpenTelemetry-compatible backends.

**Troubleshooting OTLP Issues**:

- **Check endpoint URL**: If the OTLP endpoint is incorrect or unreachable, traces won’t be sent. Double-check the URL format and ensure the server is running.
- **Authorization header**: If using a secured endpoint, ensure the `Authorization` header is correctly set in your environment variables. Incorrect or missing headers may result in authentication errors.
- **Timeouts**: OTLP exporters can time out if the network is slow or the backend is not responsive. Consider increasing the timeout duration in the exporter settings and monitoring network performance.

### 2\. Jaeger Exporter

Jaeger is a popular open-source distributed tracing system. OpenTelemetry can send traces to Jaeger using the Jaeger exporter.

**Troubleshooting Jaeger Exporter Issues**:

- **Jaeger Agent Availability**: Ensure the Jaeger agent is running and reachable. If using Jaeger in a containerized environment (e.g., Docker), make sure the container is exposed correctly to the Flask application.
- **Check the Agent Port**: By default, Jaeger’s agent runs on port 5775. Verify that the port is open and the Flask application can reach it. Adjust the `agent_host_name` and `agent_port` if necessary.
- **Jaeger Sampling**: Jaeger supports sampling, which might cause some traces to be dropped. If you’re not seeing all traces, ensure your sampling configuration is aligned with your needs.

### 3\. Prometheus Exporter

Prometheus is a widely used tool for metrics monitoring, and OpenTelemetry provides an exporter to send metrics to Prometheus.

**Troubleshooting Prometheus Exporter Issues**:

- **Ensure Prometheus Scrapes Your Metrics**: Prometheus scrapes metrics from exporters periodically. Ensure your Flask app is correctly exposing the `/metrics` endpoint for Prometheus to scrape. You can test this by visiting the `/metrics` URL manually to check the output.
- **Verify Prometheus Configuration**: In the Prometheus server configuration, ensure your application’s scrape endpoint is correctly added to the `scrape_configs` section.
- **Check for Metric Name Conflicts**: If Prometheus scrapes too many metrics or conflicts arise with existing names, it can hinder data analysis. Keep track of your metric names and avoid conflicts with other Prometheus metrics.

### 4\. Zipkin Exporter

Zipkin is another distributed tracing backend compatible with OpenTelemetry.

**Troubleshooting Zipkin Exporter Issues**:

- **Zipkin Server**: Ensure the Zipkin server is running and reachable. If using Zipkin in a containerized setup (e.g., Docker), verify that the container is exposed correctly.
- **Exporter Configuration**: Double-check your Zipkin exporter settings, including endpoint and port configurations. Incorrect URLs or ports may prevent trace data from being sent.
- **Sample Rate**: Zipkin uses a sample rate to determine which traces to keep. If your sample rate is too low, some traces might be omitted. Adjust the sample rate to ensure you capture the necessary traces.

## **Conclusion**

Integrating OpenTelemetry with Flask significantly boosts the observability of your web application. It allows you to trace, measure, and monitor performance across your system, making it easier to identify and resolve issues efficiently.

For a managed observability solution, [Last9](https://last9.io/) offers support for OpenTelemetry and Prometheus, providing a unified view of metrics, logs, and traces.

It’s especially beneficial for teams managing distributed systems and microservices, giving you a comprehensive insight into your infrastructure and services.

[Schedule a demo](https://last9.io/schedule-demo/) to learn more!

## FAQs

**1\. How do I install OpenTelemetry in my Flask application?**  
To install OpenTelemetry in your Flask application, run the following commands to set up the necessary packages:

```
pip install python-dotenv opentelemetry-distro opentelemetry-exporter-otlp opentelemetry-bootstrap -a install
```

These packages will help instrument your Flask app and send traces to your chosen exporter, such as Last9.

**2\. What are the environment variables needed for OpenTelemetry with Flask?**  
To properly configure OpenTelemetry, set the following environment variables:

```
export OTEL_SERVICE_NAME=flask-app
export OTEL_EXPORTER_OTLP_ENDPOINT=<ENDPOINT>
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=<BASIC_AUTH_HEADER>"
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=otlp
```

Replace `<ENDPOINT>` with your Last9 OTLP endpoint and `<BASIC_AUTH_HEADER>` with your encoded authorization header.

**3\. What should I do if traces are missing or not appearing in Last9?**  
If you’re not seeing traces in Last9, try the following troubleshooting steps:

- Double-check your environment variables, especially the OTLP endpoint and authorization header.
- Ensure that your Flask app is running with OpenTelemetry instrumentation by using the command `opentelemetry-instrument flask run`.
- Verify that your backend is accessible and configured correctly to receive data.

**4\. Can I use a different exporter with OpenTelemetry in Flask?**  
Yes, OpenTelemetry supports multiple exporters, including Jaeger, Zipkin, and Prometheus. You can configure your Flask app to export traces and metrics to any of these backends by:

- Installing the relevant exporter packages.
- Adjusting your environment variables to match the exporter’s endpoint and authorization settings.

**5\. How do I troubleshoot if OpenTelemetry is not sending traces to my exporter?**  
If OpenTelemetry is not sending traces to your exporter, consider these steps:

- Verify that the exporter configuration (endpoint, headers) is correct.
- Ensure your network connection allows the application to communicate with the backend.
- Check for any error messages or logs that might indicate network issues or misconfiguration.
- Confirm that the OpenTelemetry SDK is initialized properly and that all necessary libraries are installed.
