Python OpenTelemetry instrumentation
Osuite ingests OpenTelemetry data over OTLP. For Python, the OpenTelemetry distro (opentelemetry-distro) auto-instruments common frameworks, database drivers, and HTTP clients with no code changes, and the opentelemetry-instrument wrapper starts your process with that instrumentation attached. This page covers the shared setup; the per-framework guides below add the run command and gotchas specific to each stack.
Two ways to instrument
Section titled “Two ways to instrument”There are two paths, and every Python guide in this section uses one or both of them.
- Zero-code, with
opentelemetry-instrument— install the distro, runopentelemetry-bootstrapto add the instrumentors for the libraries you already use, then launch your app through theopentelemetry-instrumentwrapper. No import or SDK code in your application. This is the default for Django, FastAPI, and Flask. - Programmatic SDK setup — configure the providers and exporters yourself in a small module and register the instrumentors from code. Use this when you cannot change the launch command, or when the process forks after startup (Gunicorn, uWSGI, Celery), where the exporter’s background thread must be created in each worker rather than inherited across the fork.
Prerequisites
Section titled “Prerequisites”- Python 3.8 or newer.
- A running Python service you can restart.
- Your Osuite ingest token and region, taken from your Osuite account.
Install the packages
Section titled “Install the packages”-
Install the distro and the OTLP exporter.
Terminal window pip install opentelemetry-distro opentelemetry-exporter-otlp -
Let bootstrap detect your installed libraries and add the matching instrumentors.
Terminal window opentelemetry-bootstrap -a install
opentelemetry-bootstrap -a install reads your environment, finds supported libraries (Django, FastAPI, Flask, Celery, SQLAlchemy, psycopg, redis, requests, and more), and installs the corresponding opentelemetry-instrumentation-* packages. Rerun it whenever you add a dependency you want traced.
Configure the exporter
Section titled “Configure the exporter”Set these environment variables wherever the service runs. They are read by both the opentelemetry-instrument wrapper and the programmatic SDK.
export OTEL_SERVICE_NAME="<service-name>"export OTEL_RESOURCE_ATTRIBUTES="service.environment=production"export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.<region>.osuite.io:443"export OTEL_EXPORTER_OTLP_HEADERS="x-osuite-ingest-token=<your-ingest-token>"export OTEL_LOGS_EXPORTER="otlp"export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED="true"OTEL_SERVICE_NAMEis how the service appears in Osuite.service.environmentinOTEL_RESOURCE_ATTRIBUTESseparates production, staging, and development.OTEL_LOGS_EXPORTER=otlpandOTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=trueroute records from the standardloggingmodule to Osuite with the active trace ID attached, so logs correlate with traces. Traces and metrics export over OTLP by default.
Run with opentelemetry-instrument
Section titled “Run with opentelemetry-instrument”Prefix your normal start command with opentelemetry-instrument:
opentelemetry-instrument python app.pyThe wrapper configures the SDK from the environment variables above and activates every instrumentor that bootstrap installed. Your framework, outbound HTTP calls, and database queries are traced without touching application code. See each framework guide for the exact command and reload/fork caveats.
Programmatic setup
Section titled “Programmatic setup”When the wrapper does not fit — a forking server, or an entry point you cannot prefix — configure the SDK in a module imported before your application code. The exporters read OTEL_EXPORTER_OTLP_ENDPOINT and OTEL_EXPORTER_OTLP_HEADERS from the environment, and the resource is populated from OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES.
import logging
from opentelemetry import tracefrom opentelemetry.sdk.trace import TracerProviderfrom opentelemetry.sdk.trace.export import BatchSpanProcessorfrom opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporterfrom opentelemetry.sdk._logs import LoggerProvider, LoggingHandlerfrom opentelemetry.sdk._logs.export import BatchLogRecordProcessorfrom opentelemetry.exporter.otlp.proto.grpc._log_exporter import OTLPLogExporter
def configure_telemetry(): tracer_provider = TracerProvider() tracer_provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter())) trace.set_tracer_provider(tracer_provider)
logger_provider = LoggerProvider() logger_provider.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter())) logging.getLogger().addHandler(LoggingHandler(logger_provider=logger_provider))In programmatic mode the instrumentors are not activated for you — call each one after configure_telemetry(), for example DjangoInstrumentor().instrument() or FastAPIInstrumentor.instrument_app(app). The framework guides show the exact call.
Framework guides
Section titled “Framework guides”Verify in Osuite
Section titled “Verify in Osuite”What you should see
Start the service under opentelemetry-instrument, send a request, and the service name appears in APM within a minute, emitting request-rate and latency data. Logs written through the standard logging module appear in the Logs explorer with the trace ID attached.