OpenTelemetry urllib Instrumentation
This library enables automatic tracing of HTTP requests made using Python's built-in `urllib` library. Part of the `opentelemetry-python-contrib` project, it is currently in beta (version 0.61b0 as of March 2026) and receives frequent updates.
Warnings
- gotcha Instrumentation must be enabled before the `urllib` module is first used. If `urllib` is imported or used before `URLLibInstrumentor().instrument()` is called, requests made prior to instrumentation will not be traced.
- gotcha The library is currently in beta (`0.x.y` versions), meaning its API and produced telemetry (semantic conventions) may be subject to breaking changes between minor versions. This can impact dashboards or alerting built on specific attribute names.
- gotcha To capture HTTP request and response headers as span attributes, you must explicitly configure environment variables like `OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_REQUEST` and `OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_RESPONSE`.
- gotcha When using pre-forking web servers (e.g., Gunicorn with multiple workers), auto-instrumentation can lead to inconsistencies or break metrics generation due to issues with background threads and locks in child processes.
- gotcha By default, OpenTelemetry instrumentations do not provide a backend for storing, querying, or visualizing telemetry data. You need to integrate with an OpenTelemetry-compatible backend (e.g., Jaeger, Prometheus, commercial APMs) to utilize the collected traces.
Install
-
pip install opentelemetry-instrumentation-urllib opentelemetry-sdk
Imports
- URLLibInstrumentor
from opentelemetry.instrumentation.urllib import URLLibInstrumentor
Quickstart
import os
from urllib import request
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
from opentelemetry.instrumentation.urllib import URLLibInstrumentor
# Configure OpenTelemetry SDK
provider = TracerProvider()
processor = SimpleSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
# Instrument urllib
URLLibInstrumentor().instrument()
# Make a request using urllib.request
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("my-urllib-request"):
try:
req = request.Request('http://httpbin.org/get')
response = request.urlopen(req)
print(f"Response Status: {response.getcode()}")
print(f"Response Data (first 100 chars): {response.read(100).decode()}")
except Exception as e:
print(f"Error during request: {e}")