OpenTelemetry HTTPX Instrumentation

raw JSON →
0.61b0 verified Tue May 12 auth: no python install: verified

OpenTelemetry HTTPX Instrumentation provides automatic tracing for HTTPX, a modern HTTP client for Python supporting both synchronous and asynchronous APIs. It is part of the OpenTelemetry Python Contrib project, which is actively developed and receives frequent beta releases, generally aligning with the core OpenTelemetry Python SDK's release cadence.

pip install opentelemetry-instrumentation-httpx opentelemetry-sdk opentelemetry-exporter-otlp-proto-http httpx
error HttpX instrumentation does not work on classes that extend httpx client
cause The OpenTelemetry HTTPX instrumentation monkey-patches `httpx.Client` and `httpx.AsyncClient` by replacing them with instrumented versions. If a subclass of `httpx.Client` or an instance of `httpx.Client` is created before `HTTPXClientInstrumentor().instrument()` is called, it will use the original, uninstrumented classes.
fix
Ensure that HTTPXClientInstrumentor().instrument() is called at the very beginning of your application's startup, before any httpx.Client or httpx.AsyncClient subclasses are defined or instances are created.
error httpx instrumentation doesn't work for `httpx.get`, `httpx.post`, etc.
cause When using the functional API (`httpx.get`, `httpx.post`, etc.) directly without explicitly creating an `httpx.Client` instance, the global instrumentation might not correctly capture these calls in some configurations or older versions of the library.
fix
While HTTPXClientInstrumentor().instrument() is intended to instrument all clients, including those implicitly used by functional calls, explicitly creating and using an httpx.Client or httpx.AsyncClient instance after instrumentation is a more robust approach. Alternatively, ensure your OpenTelemetry SDK and instrumentation packages are up-to-date.
error ModuleNotFoundError: No module named 'opentelemetry.instrumentation.httpx'
cause This error occurs because the `opentelemetry-instrumentation-httpx` package is either not installed, installed in a different Python environment than the one running the application, or there is a conflict with OpenTelemetry's namespace packages.
fix
Install the package using pip install opentelemetry-instrumentation-httpx. Verify that you are running your application with the same Python environment where the package was installed, and ensure opentelemetry-sdk is also installed.
error httpx instrumentation does not work when proxy is set
cause The default `opentelemetry-instrumentation-httpx` might not correctly apply tracing to HTTPX clients when a proxy is configured, leading to missing traces for requests made through the proxy.
fix
A known fix involves patching self._mounts in the _InstrumentedClient to use SyncOpenTelemetryTransport directly. This indicates that the instrumentation might not be correctly wrapping the transport layer when proxies are involved. Check the latest library versions for a permanent fix or refer to GitHub issues for workarounds.
breaking OpenTelemetry's HTTP Semantic Conventions have been stabilized, leading to attribute name changes (e.g., `http.url` to `url.full`, `http.status_code` to `http.response.status_code`).
fix Update to the latest instrumentation version. To facilitate migration, set the environment variable `OTEL_SEMCONV_STABILITY_OPT_IN=http/dup` to emit both old and new attributes during transition, then switch to `http` to emit only stable attributes.
gotcha HTTPX clients or their subclasses instantiated *before* `HTTPXClientInstrumentor().instrument()` is called will not be instrumented. This is particularly relevant when using libraries that internally create HTTPX clients (e.g., `openai-python`).
fix Ensure `HTTPXClientInstrumentor().instrument()` is called as early as possible in your application's lifecycle, preferably before any HTTPX clients are created. For single-client instrumentation, use `HTTPXClientInstrumentor.instrument_client(client_instance)`.
gotcha Pre-fork servers (like Gunicorn with multiple workers) can cause issues with metrics generation when using OpenTelemetry auto-instrumentation due to threading and lock inconsistencies in child processes.
fix Consider using a single worker for pre-fork servers or exploring workarounds like programmatic auto-instrumentation or specific configurations for your deployment environment. Refer to OpenTelemetry troubleshooting guides for detailed strategies.
gotcha By default, sensitive HTTP headers and request/response bodies are not captured or are sanitized. Directly logging or capturing raw payloads can expose sensitive data.
fix Use the environment variable `OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS` with a comma-delimited list of header names (regex supported) to redact values. For custom payload logging, implement `request_hook` and `response_hook` functions, being mindful of data sensitivity.
gotcha Networking requests via HTTPX may fail with `SSL: CERTIFICATE_VERIFY_FAILED` errors, particularly in minimal container environments (e.g., `python:*-slim` Docker images). This indicates a missing or outdated root CA certificate bundle required to verify SSL connections.
fix Ensure your environment has the necessary root CA certificates installed. For Debian-based Docker images, this typically means adding `RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*` to your Dockerfile. For other environments, ensure your system's SSL certificate store is up-to-date and correctly configured.
gotcha When running in minimal environments (e.g., Alpine Docker images), SSL certificate validation for HTTPS requests may fail with `CERTIFICATE_VERIFY_FAILED`. This is an environmental issue due to missing root CA certificates, not a bug in the instrumentation, but it prevents HTTPX requests from completing.
fix Ensure your environment has the necessary CA certificates installed (e.g., `apk add ca-certificates` on Alpine Linux, or mount appropriate certificate bundles). For testing, you can disable SSL verification in HTTPX by passing `verify=False` to the `httpx.Client` constructor, but this is not recommended for production environments.
python os / libc status wheel install import disk
3.10 alpine (musl) wheel - 0.41s 34.6M
3.10 alpine (musl) - - 0.45s 34.4M
3.10 slim (glibc) wheel 4.5s 0.28s 36M
3.10 slim (glibc) - - 0.34s 35M
3.11 alpine (musl) wheel - 0.59s 38.3M
3.11 alpine (musl) - - 0.72s 38.0M
3.11 slim (glibc) wheel 4.4s 0.51s 39M
3.11 slim (glibc) - - 0.55s 39M
3.12 alpine (musl) wheel - 0.73s 29.8M
3.12 alpine (musl) - - 0.83s 29.5M
3.12 slim (glibc) wheel 3.7s 0.73s 31M
3.12 slim (glibc) - - 0.78s 30M
3.13 alpine (musl) wheel - 0.40s 29.5M
3.13 alpine (musl) - - 0.46s 29.2M
3.13 slim (glibc) wheel 3.6s 0.40s 30M
3.13 slim (glibc) - - 0.48s 30M
3.9 alpine (musl) wheel - 0.36s 33.8M
3.9 alpine (musl) - - 0.39s 33.7M
3.9 slim (glibc) wheel 5.2s 0.36s 35M
3.9 slim (glibc) - - 0.34s 35M

This quickstart demonstrates how to set up the OpenTelemetry SDK and instrument both synchronous and asynchronous HTTPX clients. After running, you should see trace information printed to the console (if using ConsoleSpanExporter).

import asyncio
import httpx
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, BatchSpanProcessor
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
import os

# Configure OpenTelemetry SDK
resource = Resource.create({"service.name": os.environ.get("OTEL_SERVICE_NAME", "httpx-client-app")})
provider = TracerProvider(resource=resource)
processor = BatchSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)

# Instrument all HTTPX clients
HTTPXClientInstrumentor().instrument()

async def make_async_request():
    print("\nMaking async HTTPX request...")
    async with httpx.AsyncClient() as client:
        response = await client.get("https://example.com")
        print(f"Async request status: {response.status_code}")

def make_sync_request():
    print("\nMaking sync HTTPX request...")
    with httpx.Client() as client:
        response = client.get("https://example.com")
        print(f"Sync request status: {response.status_code}")

if __name__ == "__main__":
    make_sync_request()
    asyncio.run(make_async_request())
    print("\nTraces should be printed above (if ConsoleSpanExporter is used).")