diff --git a/packages/traceloop-sdk/pyproject.toml b/packages/traceloop-sdk/pyproject.toml index 53e1c4ddb3..cd1919c104 100644 --- a/packages/traceloop-sdk/pyproject.toml +++ b/packages/traceloop-sdk/pyproject.toml @@ -15,6 +15,7 @@ dependencies = [ "opentelemetry-sdk>=1.38.0,<2", "opentelemetry-exporter-otlp-proto-http>=1.38.0,<2", "opentelemetry-exporter-otlp-proto-grpc>=1.38.0,<2", + "opentelemetry-instrumentation-httpx>=0.59b0", "opentelemetry-instrumentation-logging>=0.59b0", "opentelemetry-instrumentation-requests>=0.59b0", "opentelemetry-instrumentation-sqlalchemy>=0.59b0", diff --git a/packages/traceloop-sdk/traceloop/sdk/instruments.py b/packages/traceloop-sdk/traceloop/sdk/instruments.py index c507d31366..7600e42fee 100644 --- a/packages/traceloop-sdk/traceloop/sdk/instruments.py +++ b/packages/traceloop-sdk/traceloop/sdk/instruments.py @@ -13,6 +13,7 @@ class Instruments(Enum): GOOGLE_GENERATIVEAI = "google_generativeai" GROQ = "groq" HAYSTACK = "haystack" + HTTPX = "httpx" LANCEDB = "lancedb" LANGCHAIN = "langchain" LLAMA_INDEX = "llama_index" diff --git a/packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py b/packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py index 08c52905f2..71cfb1aa1f 100644 --- a/packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py +++ b/packages/traceloop-sdk/traceloop/sdk/tracing/tracing.py @@ -504,6 +504,9 @@ def init_instrumentations( elif instrument == Instruments.HAYSTACK: if init_haystack_instrumentor(): instrument_set = True + elif instrument == Instruments.HTTPX: + if init_httpx_instrumentor(): + instrument_set = True elif instrument == Instruments.LANCEDB: if init_lancedb_instrumentor(): instrument_set = True @@ -735,6 +738,22 @@ def init_haystack_instrumentor(): return False +def init_httpx_instrumentor(): + try: + if is_package_installed("httpx"): + from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor + + instrumentor = HTTPXClientInstrumentor() + if not instrumentor.is_instrumented_by_opentelemetry: + # Note: HTTPXClientInstrumentor doesn't accept excluded_urls param. + # Use OTEL_PYTHON_HTTPX_EXCLUDED_URLS env var instead. + instrumentor.instrument() + return True + except Exception as e: + logging.error(f"Error initializing HTTPX instrumentor: {e}") + return False + + def init_langchain_instrumentor(): try: if is_package_installed("langchain") or is_package_installed("langgraph"):