Python Instrumentation in Containers
Instrumentation of Python applications in containers with the OpenTelemetry agent
This documentation explains how to instrument Python applications in containers using the zero-code model, with the official OpenTelemetry agent, adapted for use with Elven Observability. The idea is to ensure the collection of traces (and optionally metrics) without code changes, only by adjusting the Dockerfile and environment variables.
Agent installation in the Dockerfile
Add only the necessary packages to the Dockerfile according to your framework. See below for the common packages and those specific to each framework:
Common packages (always install):
RUN pip install \
opentelemetry-distro \
opentelemetry-exporter-otlp \
opentelemetry-instrumentation-requests
FastAPI:
RUN pip install opentelemetry-instrumentation-fastapi
Flask:
RUN pip install opentelemetry-instrumentation-flask
Django:
RUN pip install opentelemetry-instrumentation-django
Important: Do not install unnecessary instrumentations. Ex: apps using Django do not need opentelemetry-instrumentation-fastapi.
Example Dockerfile:
FROM python:3.12-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV DJANGO_SETTINGS_MODULE=config.settings.base
WORKDIR /app
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
netcat-openbsd \
curl \
&& rm -rf /var/lib/apt/lists/*
# Install OpenTelemetry
RUN pip install opentelemetry-distro \
opentelemetry-exporter-otlp \
opentelemetry-instrumentation \
opentelemetry-instrumentation-django \
opentelemetry-instrumentation-requests
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["opentelemetry-instrument", "--", "gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000"]
Environment Variables Configuration
Set the following variables to enable automatic instrumentation and send data to the Elven collector:
- name: OTEL_SERVICE_NAME
value: "python-app"
- name: OTEL_RESOURCE_ATTRIBUTES
value: "service=python-app,environment=production"
- name: OTEL_TRACES_EXPORTER
value: "otlp"
- name: OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
value: "http://your_collector_endpoint.com:4317/v1/traces"
- name: OTEL_METRICS_EXPORTER
value: "otlp"
- name: OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
value: "http://your_collector_endpoint.com:4317/v1/metrics"
Explanation:
OTEL_SERVICE_NAME
: name of the service displayed in Grafana/Tempo.OTEL_RESOURCE_ATTRIBUTES
: extra tags to enrich the traces.OTEL_EXPORTER_OTLP_*
: endpoints for sending the data.
How to start the app with the agent (CMD)
Use the opentelemetry-instrument
command as a wrapper for the application.
See below for examples by framework:
FastAPI (with Uvicorn)
CMD ["opentelemetry-instrument", "--", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Flask
CMD ["opentelemetry-instrument", "--", "python", "app.py"]
Django
CMD ["opentelemetry-instrument", "--", "python", "manage.py", "runserver", "0.0.0.0:8000"]
Info: You can adapt the command according to your entrypoint: gunicorn, uvicorn, waitress, etc.
Examples by Environment
Docker Compose
services:
api:
build: .
environment:
- OTEL_SERVICE_NAME=python-app
- OTEL_RESOURCE_ATTRIBUTES=service=python-app,environment=production
- OTEL_TRACES_EXPORTER=otlp
- OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://your_collector_endpoint.com:4317/v1/traces
- OTEL_METRICS_EXPORTER=otlp
- OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://your_collector_endpoint.com:4317/v1/metrics
Kubernetes
spec:
containers:
- name: python-app
image: python-app:latest
env:
- name: OTEL_SERVICE_NAME
value: "python-app"
- name: OTEL_RESOURCE_ATTRIBUTES
value: "service=python-app,environment=production"
- name: OTEL_TRACES_EXPORTER
value: "otlp"
- name: OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
value: "http://your_collector_endpoint.com:4317/v1/traces"
- name: OTEL_METRICS_EXPORTER
value: "otlp"
- name: OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
value: "http://your_collector_endpoint.com:4317/v1/metrics"
ECS (Fargate ou EC2)
"environment": [
{ "name": "OTEL_SERVICE_NAME", "value": "python-app" },
{ "name": "OTEL_RESOURCE_ATTRIBUTES", "value": "service=python-app,environment=production" },
{ "name": "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "value": "http://your_collector_endpoint.com:4317/v1/traces" },
{ "name": "OTEL_TRACES_EXPORTER", "value": "otlp" },
{ "name": "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT", "value": "http://your_collector_endpoint.com:4317/v1/metrics" },
{ "name": "OTEL_METRICS_EXPORTER", "value": "otlp" }
]
Troubleshooting
Traces not showing: check if the endpoint is accessible and if the CMD uses opentelemetry-instrument correctly.
Application timeout: verify if the collector is online and responding on port 4318.
Duplicate instrumentation: avoid mixing manual instrumentation with the automatic mode.
Dependency error: each framework requires its specific instrumentation, review the pip install.
Best Practices
Give meaningful names to services (
OTEL_SERVICE_NAME=projeto-env-modulo
).Separate environments (
environment=dev
,staging
,production
).Do not expose credentials in environment variables.
Do not use
OTEL_LOG_LEVEL=debug
in production.Test locally with
otel-cli
oucurl
to validate the collector.
Example of .env
.env
OTEL_SERVICE_NAME=python-app
OTEL_RESOURCE_ATTRIBUTES=service=python-app,environment=production
OTEL_TRACES_EXPORTER=otlp
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://your_collector_endpoint.com:4317/v1/traces
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://your_collector_endpoint.com:4317/v1/metrics
OTEL_METRICS_EXPORTER=otlp
Your Python app is now instrumented with Elven Observability, using auto-instrumentation based on OpenTelemetry.
Last updated
Was this helpful?