OpenTelemetry Python API
raw JSON → 1.40.0 verified Tue May 12 auth: no python install: verified quickstart: verified
OpenTelemetry Python API package. Current version: 1.40.0 (Mar 2026). TWO separate packages: 'opentelemetry-api' (interfaces + no-op implementations) and 'opentelemetry-sdk' (actual implementation). Installing only opentelemetry-api produces silent no-ops — all tracing calls succeed but nothing is recorded or exported. Must also install opentelemetry-sdk AND configure a TracerProvider AND call trace.set_tracer_provider(). Exporters (OTLP, Jaeger, Zipkin) are separate packages. All packages must be the same version.
pip install opentelemetry-api opentelemetry-sdk Common errors
error Warning: No TracerProvider configured, using NoopTracerProvider. All tracing operations will be no-ops. ↓
cause The opentelemetry-sdk package is not installed, or a TracerProvider from opentelemetry.sdk.trace has not been created and globally registered using trace.set_tracer_provider() before any tracing occurs. The opentelemetry-api package alone provides no-op implementations.
fix
Install
opentelemetry-sdk and configure a TracerProvider with a SpanProcessor and SpanExporter, then set it as the global provider early in your application's lifecycle.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
# 1. Create a TracerProvider
provider = TracerProvider()
# 2. Configure an exporter and processor (e.g., ConsoleSpanExporter for testing)
span_processor = SimpleSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(span_processor)
# 3. Set the global TracerProvider (MUST be done before getting a tracer)
trace.set_tracer_provider(provider)
# Now get a tracer and create spans as normal
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("my-operation"):
print("This span will be recorded and exported!") error ModuleNotFoundError: No module named 'opentelemetry.sdk' ↓
cause The required OpenTelemetry SDK package has not been installed in the current Python environment, or there's a Python environment mismatch or namespace package conflict. This error also appears for other missing OpenTelemetry-related modules, such as specific instrumentation libraries or exporters.
fix
Ensure all necessary OpenTelemetry packages are installed in the active Python environment. For example, use
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http. Verify the correct Python environment is active if the issue persists.
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
# If using auto-instrumentation, also install the distro and specific instrumentations:
pip install opentelemetry-distro opentelemetry-instrumentation-requests # Example for requests library error WARNING: opentelemetry.trace:Overriding of current TracerProvider is not allowed. ↓
cause The `trace.set_tracer_provider()` function has been called more than once in the application's lifecycle. This often happens when multiple parts of an application or different libraries attempt to initialize and set the global `TracerProvider` independently.
fix
Ensure
trace.set_tracer_provider() is called only once, typically at the very beginning of your application's startup. Centralize OpenTelemetry initialization to prevent multiple components from trying to set the global provider.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
def initialize_telemetry():
provider = TracerProvider()
span_processor = SimpleSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(span_processor)
trace.set_tracer_provider(provider)
# Call this once, e.g., in your main application file or entry point
initialize_telemetry()
# Subsequent calls to trace.set_tracer_provider() will result in the warning. error AttributeError: 'ProxyTracerProvider' object has no attribute 'add_span_processor' ↓
cause This error occurs when `trace.get_tracer_provider()` is called before a concrete `TracerProvider` from `opentelemetry.sdk.trace` has been set using `trace.set_tracer_provider()`. In such cases, `get_tracer_provider()` returns a `NoopTracerProvider` or `ProxyTracerProvider`, which does not have SDK-specific methods like `add_span_processor`.
fix
Always ensure
trace.set_tracer_provider() is called with an instance of opentelemetry.sdk.trace.TracerProvider *before* attempting to call SDK-specific methods like add_span_processor on the globally retrieved TracerProvider.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
# Correct order: Set the concrete provider first
provider = TracerProvider()
trace.set_tracer_provider(provider)
# Now, when you get the provider, it will be the actual SDK provider
# (or a proxy that correctly delegates to it if using newer SDK versions)
actual_provider = trace.get_tracer_provider()
span_processor = SimpleSpanProcessor(ConsoleSpanExporter())
actual_provider.add_span_processor(span_processor) # This will now work Warnings
breaking Installing only 'opentelemetry-api' gives silent no-ops. All tracing calls succeed without errors but nothing is recorded. Must also install 'opentelemetry-sdk'. ↓
fix pip install opentelemetry-api opentelemetry-sdk
breaking trace.get_tracer() returns NoopTracer until trace.set_tracer_provider() is called. Forgetting this line means all spans are silently discarded. Warning: 'No TracerProvider configured, using NoopTracerProvider' only shows with debug logging enabled. ↓
fix Always call trace.set_tracer_provider(provider) after creating TracerProvider, before any trace.get_tracer() calls.
breaking Exporters are separate packages not included in opentelemetry-sdk. OTLP requires 'opentelemetry-exporter-otlp'. Jaeger requires 'opentelemetry-exporter-jaeger'. ConsoleSpanExporter is included in SDK. ↓
fix pip install opentelemetry-exporter-otlp for production. Use ConsoleSpanExporter for local development.
breaking All opentelemetry-* packages must be the same version. Mixing versions (e.g. api=1.20, sdk=1.25) causes ImportError or unexpected behavior. ↓
fix Pin all packages to same version: pip install 'opentelemetry-api==1.40.0' 'opentelemetry-sdk==1.40.0' 'opentelemetry-exporter-otlp==1.40.0'
gotcha Auto-instrumentation packages (opentelemetry-instrumentation-fastapi etc.) are in the separate 'opentelemetry-python-contrib' repo — not in the main SDK. Must be installed separately. ↓
fix pip install opentelemetry-instrumentation-fastapi opentelemetry-instrumentation-sqlalchemy etc.
gotcha provider.shutdown() must be called on app exit to flush buffered spans. Without it, spans in the BatchSpanProcessor queue are lost on process exit. ↓
fix Call provider.shutdown() in app shutdown handler or use atexit.register(provider.shutdown).
gotcha service.name resource attribute is not set by default. Without it, traces appear as 'unknown_service' in your backend. ↓
fix Resource.create({'service.name': 'my-service'}) or set OTEL_SERVICE_NAME env var.
Install
pip install opentelemetry-exporter-otlp pip install opentelemetry-instrumentation-fastapi opentelemetry-instrumentation-sqlalchemy Install compatibility verified last tested: 2026-05-12
python os / libc variant status wheel install import disk
3.10 alpine (musl) opentelemetry-api - - 0.11s 22.1M
3.10 alpine (musl) opentelemetry-exporter-otlp - - 0.12s 50.0M
3.10 alpine (musl) opentelemetry-instrumentation-fastapi - - 0.11s 22.6M
3.10 slim (glibc) opentelemetry-api - - 0.07s 23M
3.10 slim (glibc) opentelemetry-exporter-otlp - - 0.08s 48M
3.10 slim (glibc) opentelemetry-instrumentation-fastapi - - 0.07s 23M
3.11 alpine (musl) opentelemetry-api - - 0.19s 24.4M
3.11 alpine (musl) opentelemetry-exporter-otlp - - 0.20s 53.2M
3.11 alpine (musl) opentelemetry-instrumentation-fastapi - - 0.20s 24.9M
3.11 slim (glibc) opentelemetry-api - - 0.16s 25M
3.11 slim (glibc) opentelemetry-exporter-otlp - - 0.15s 51M
3.11 slim (glibc) opentelemetry-instrumentation-fastapi - - 0.15s 25M
3.12 alpine (musl) opentelemetry-api - - 0.15s 16.1M
3.12 alpine (musl) opentelemetry-exporter-otlp - - 0.17s 44.8M
3.12 alpine (musl) opentelemetry-instrumentation-fastapi - - 0.15s 16.7M
3.12 slim (glibc) opentelemetry-api - - 0.15s 17M
3.12 slim (glibc) opentelemetry-exporter-otlp - - 0.15s 43M
3.12 slim (glibc) opentelemetry-instrumentation-fastapi - - 0.15s 17M
3.13 alpine (musl) opentelemetry-api - - 0.14s 15.8M
3.13 alpine (musl) opentelemetry-exporter-otlp - - 0.15s 44.4M
3.13 alpine (musl) opentelemetry-instrumentation-fastapi - - 0.14s 16.3M
3.13 slim (glibc) opentelemetry-api - - 0.14s 16M
3.13 slim (glibc) opentelemetry-exporter-otlp - - 0.14s 42M
3.13 slim (glibc) opentelemetry-instrumentation-fastapi - - 0.14s 17M
3.9 alpine (musl) opentelemetry-api - - 0.10s 21.6M
3.9 alpine (musl) opentelemetry-exporter-otlp - - 0.10s 49.3M
3.9 alpine (musl) opentelemetry-instrumentation-fastapi - - 0.11s 22.1M
3.9 slim (glibc) opentelemetry-api - - 0.10s 22M
3.9 slim (glibc) opentelemetry-exporter-otlp - - 0.10s 47M
3.9 slim (glibc) opentelemetry-instrumentation-fastapi - - 0.10s 23M
Imports
- TracerProvider setup wrong
# Wrong: API only — all no-ops, nothing exported from opentelemetry import trace tracer = trace.get_tracer(__name__) # returns NoopTracer # Wrong: forgot to call set_tracer_provider — still no-op from opentelemetry.sdk.trace import TracerProvider provider = TracerProvider() tracer = trace.get_tracer(__name__) # still NoopTracer — provider not registeredcorrectfrom opentelemetry import trace from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter from opentelemetry.sdk.resources import Resource # Configure provider with resource and exporter resource = Resource.create({'service.name': 'my-service'}) provider = TracerProvider(resource=resource) exporter = OTLPSpanExporter(endpoint='http://localhost:4317') processor = BatchSpanProcessor(exporter) provider.add_span_processor(processor) # MUST register globally before any tracing trace.set_tracer_provider(provider) # Get tracer tracer = trace.get_tracer(__name__) # Use tracer with tracer.start_as_current_span('my-operation') as span: span.set_attribute('user.id', '42') # do work
Quickstart verified last tested: 2026-04-23
# pip install opentelemetry-api opentelemetry-sdk
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
from opentelemetry.sdk.resources import Resource
# Setup — do this once at app startup
resource = Resource.create({'service.name': 'my-service', 'service.version': '1.0.0'})
provider = TracerProvider(resource=resource)
# ConsoleSpanExporter for local dev — replace with OTLPSpanExporter in production
provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))
# Register globally — MUST be before any trace.get_tracer() calls
trace.set_tracer_provider(provider)
# Get tracer
tracer = trace.get_tracer(__name__)
# Create spans
with tracer.start_as_current_span('main-operation') as span:
span.set_attribute('env', 'production')
with tracer.start_as_current_span('db-query') as child:
child.set_attribute('db.system', 'postgresql')
child.set_attribute('db.statement', 'SELECT * FROM users')
# do DB work
# Flush remaining spans on shutdown
provider.shutdown()