Instrument a Python application
Follow this article to install the upstream OpenTelemetry distribution for Python and auto-instrument your application running on Linux for Grafana Cloud Application Observability.
Alternatively, if you need a instrumentation solution for Python supported by Grafana, use Grafana Beyla.
Before you begin
The is the first step to get telemetry data into Application Observability, you need:
- A Python development environment.
- A Python application to instrument using Python 3 or higher.
Install the SDK
Install OpenTelemetry SDK:
pip install opentelemetry-distro[otlp]
opentelemetry-bootstrap -a install
Instrument your application
Export the following environment variables before running your application to configure auto-instrumentation:
export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
export OTEL_LOGS_EXPORTER=otlp
Global Interpreter Lock
OpenTelemetry Python uses a Global Interpreter Lock (GIL) that can cause performance issues when using a web server that spawns multiple processes to serve requests in parallel.
To avoid this, you have to register a post_fork
hook that will be called after each worker process is forked.
Note
Other web servers, such as uWSGI, can be instrumented in the same way (@postfork
instead ofpost_fork
).
Use this gunicorn.conf.py
file (gunicorn app -c gunicorn.conf.py
) in addition to the
Python production instrumentation guide.
import logging
from uuid import uuid4
from opentelemetry import metrics, trace
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import (
OTLPLogExporter,
)
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
OTLPMetricExporter,
)
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
OTLPSpanExporter,
)
# support for logs is currently experimental
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.resources import SERVICE_INSTANCE_ID
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# your gunicorn config here
# bind = "127.0.0.1:8000"
collector_endpoint = "http://localhost:4317"
def post_fork(server, worker):
server.log.info("Worker spawned (pid: %s)", worker.pid)
resource = Resource.create(
attributes={
# each worker needs a unique service.instance.id to distinguish the created metrics in prometheus
SERVICE_INSTANCE_ID: str(uuid4()),
"worker": worker.pid,
}
)
tracer_provider = TracerProvider(resource=resource)
tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(endpoint=collector_endpoint)))
trace.set_tracer_provider(tracer_provider)
metrics.set_meter_provider(
MeterProvider(
resource=resource,
metric_readers=[(PeriodicExportingMetricReader(
OTLPMetricExporter(endpoint=collector_endpoint)
))],
)
)
logger_provider = LoggerProvider(resource=resource)
logger_provider.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter(endpoint=collector_endpoint)))
logging.getLogger().addHandler(LoggingHandler(level=logging.NOTSET, logger_provider=logger_provider))
Test your instrumentation
To test if you successfully instrumented your application and are producing telemetry data, run the application. The console output should print references to metrics and logs.
opentelemetry-instrument flask run -p 8080
Example application
See the Rolldice service for a complete example setup.
Next steps
- Create a free Grafana Cloud account
- Configure your telemetry data destination:
- Grafana Cloud OTLP endpoint: for a quick local development and testing setup
- OpenTelemetry Collector: for a robust and scalable production setup
- Observe your services in Application Observability