@@ -176,7 +176,13 @@ def response_hook(span, request, response):
176
176
from opentelemetry .trace import SpanKind , TracerProvider , get_tracer
177
177
from opentelemetry .trace .span import Span
178
178
from opentelemetry .trace .status import Status
179
+ from opentelemetry .utils .http import (
180
+ ExcludeList ,
181
+ get_excluded_urls ,
182
+ parse_excluded_urls ,
183
+ )
179
184
185
+ _excluded_urls_from_env = get_excluded_urls ("HTTPX" )
180
186
_logger = logging .getLogger (__name__ )
181
187
182
188
URL = typing .Tuple [bytes , bytes , typing .Optional [int ], bytes ]
@@ -276,6 +282,7 @@ class SyncOpenTelemetryTransport(httpx.BaseTransport):
276
282
right after the span is created
277
283
response_hook: A hook that receives the span, request, and response
278
284
that is called right before the span ends
285
+ excluded_urls: List of urls that should be excluded from tracing
279
286
"""
280
287
281
288
def __init__ (
@@ -284,6 +291,7 @@ def __init__(
284
291
tracer_provider : typing .Optional [TracerProvider ] = None ,
285
292
request_hook : typing .Optional [RequestHook ] = None ,
286
293
response_hook : typing .Optional [ResponseHook ] = None ,
294
+ excluded_urls : typing .Optional [ExcludeList ] = None ,
287
295
):
288
296
self ._transport = transport
289
297
self ._tracer = get_tracer (
@@ -293,6 +301,7 @@ def __init__(
293
301
)
294
302
self ._request_hook = request_hook
295
303
self ._response_hook = response_hook
304
+ self ._excluded_urls = excluded_urls
296
305
297
306
def __enter__ (self ) -> "SyncOpenTelemetryTransport" :
298
307
self ._transport .__enter__ ()
@@ -317,10 +326,13 @@ def handle_request(
317
326
"""Add request info to span."""
318
327
if context .get_value ("suppress_instrumentation" ):
319
328
return self ._transport .handle_request (* args , ** kwargs )
320
-
321
329
method , url , headers , stream , extensions = _extract_parameters (
322
330
args , kwargs
323
331
)
332
+
333
+ if self ._excluded_urls and self ._excluded_urls .url_disabled (url ):
334
+ return self ._transport .handle_request (* args , ** kwargs )
335
+
324
336
span_attributes = _prepare_attributes (method , url )
325
337
326
338
request_info = RequestInfo (method , url , headers , stream , extensions )
@@ -370,6 +382,7 @@ class AsyncOpenTelemetryTransport(httpx.AsyncBaseTransport):
370
382
right after the span is created
371
383
response_hook: A hook that receives the span, request, and response
372
384
that is called right before the span ends
385
+ excluded_urls: List of urls that should be excluded from tracing
373
386
"""
374
387
375
388
def __init__ (
@@ -378,6 +391,7 @@ def __init__(
378
391
tracer_provider : typing .Optional [TracerProvider ] = None ,
379
392
request_hook : typing .Optional [RequestHook ] = None ,
380
393
response_hook : typing .Optional [ResponseHook ] = None ,
394
+ excluded_urls : typing .Optional [ExcludeList ] = None ,
381
395
):
382
396
self ._transport = transport
383
397
self ._tracer = get_tracer (
@@ -387,6 +401,7 @@ def __init__(
387
401
)
388
402
self ._request_hook = request_hook
389
403
self ._response_hook = response_hook
404
+ self ._excluded_urls = excluded_urls
390
405
391
406
async def __aenter__ (self ) -> "AsyncOpenTelemetryTransport" :
392
407
await self ._transport .__aenter__ ()
@@ -407,12 +422,16 @@ async def handle_async_request(
407
422
httpx .Response ,
408
423
]:
409
424
"""Add request info to span."""
410
- if context .get_value ("suppress_instrumentation" ):
411
- return await self ._transport .handle_async_request (* args , ** kwargs )
412
-
413
425
method , url , headers , stream , extensions = _extract_parameters (
414
426
args , kwargs
415
427
)
428
+
429
+ if self ._excluded_urls and self ._excluded_urls .url_disabled (url ):
430
+ return await self ._transport .handle_async_request (* args , ** kwargs )
431
+
432
+ if context .get_value ("suppress_instrumentation" ):
433
+ return await self ._transport .handle_async_request (* args , ** kwargs )
434
+
416
435
span_attributes = _prepare_attributes (method , url )
417
436
418
437
span_name = _get_default_span_name (
@@ -459,6 +478,7 @@ class _InstrumentedClient(httpx.Client):
459
478
_tracer_provider = None
460
479
_request_hook = None
461
480
_response_hook = None
481
+ _excluded_urls = None
462
482
463
483
def __init__ (self , * args , ** kwargs ):
464
484
super ().__init__ (* args , ** kwargs )
@@ -478,6 +498,7 @@ class _InstrumentedAsyncClient(httpx.AsyncClient):
478
498
_tracer_provider = None
479
499
_request_hook = None
480
500
_response_hook = None
501
+ _excluded_urls = None
481
502
482
503
def __init__ (self , * args , ** kwargs ):
483
504
super ().__init__ (* args , ** kwargs )
@@ -513,11 +534,18 @@ def _instrument(self, **kwargs):
513
534
right after the span is created
514
535
``response_hook``: A hook that receives the span, request, and response
515
536
that is called right before the span ends
537
+ ``excluded_urls``: A string containing a comma-delimited
538
+ list of regexes used to exclude URLs from tracking
516
539
"""
517
540
self ._original_client = httpx .Client
518
541
self ._original_async_client = httpx .AsyncClient
519
542
request_hook = kwargs .get ("request_hook" )
520
543
response_hook = kwargs .get ("response_hook" )
544
+ excluded_urls = kwargs .get ("excluded_urls" )
545
+ if excluded_urls is None :
546
+ excluded_urls = _excluded_urls_from_env
547
+ else :
548
+ excluded_urls = parse_excluded_urls (excluded_urls )
521
549
if callable (request_hook ):
522
550
_InstrumentedClient ._request_hook = request_hook
523
551
_InstrumentedAsyncClient ._request_hook = request_hook
@@ -536,9 +564,11 @@ def _uninstrument(self, **kwargs):
536
564
_InstrumentedClient ._tracer_provider = None
537
565
_InstrumentedClient ._request_hook = None
538
566
_InstrumentedClient ._response_hook = None
567
+ _InstrumentedClient ._excluded_urls = None
539
568
_InstrumentedAsyncClient ._tracer_provider = None
540
569
_InstrumentedAsyncClient ._request_hook = None
541
570
_InstrumentedAsyncClient ._response_hook = None
571
+ _InstrumentedAsyncClient ._excluded_urls = None
542
572
543
573
@staticmethod
544
574
def instrument_client (
0 commit comments