@@ -189,11 +189,13 @@ def client_response_hook(span: Span, message: dict):
189
189
---
190
190
"""
191
191
192
+ from __future__ import annotations
193
+
192
194
import typing
193
195
import urllib
194
196
from functools import wraps
195
197
from timeit import default_timer
196
- from typing import Tuple
198
+ from typing import Any , Awaitable , Callable , Tuple , cast
197
199
198
200
from asgiref .compatibility import guarantee_single_callable
199
201
@@ -332,55 +334,28 @@ def collect_request_attributes(scope):
332
334
return result
333
335
334
336
335
- def collect_custom_request_headers_attributes (scope ):
336
- """returns custom HTTP request headers to be added into SERVER span as span attributes
337
- Refer specification https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-request-and-response-headers
337
+ def collect_custom_headers_attributes (
338
+ scope_or_response_message : dict [str , Any ],
339
+ sanitize : SanitizeValue ,
340
+ header_regexes : list [str ],
341
+ normalize_names : Callable [[str ], str ],
342
+ ) -> dict [str , str ]:
338
343
"""
344
+ Returns custom HTTP request or response headers to be added into SERVER span as span attributes.
339
345
340
- sanitize = SanitizeValue (
341
- get_custom_headers (
342
- OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS
343
- )
344
- )
345
-
346
- # Decode headers before processing.
347
- headers = {
348
- _key .decode ("utf8" ): _value .decode ("utf8" )
349
- for (_key , _value ) in scope .get ("headers" )
350
- }
351
-
352
- return sanitize .sanitize_header_values (
353
- headers ,
354
- get_custom_headers (
355
- OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST
356
- ),
357
- normalise_request_header_name ,
358
- )
359
-
360
-
361
- def collect_custom_response_headers_attributes (message ):
362
- """returns custom HTTP response headers to be added into SERVER span as span attributes
363
- Refer specification https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-request-and-response-headers
346
+ Refer specifications:
347
+ - https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-request-and-response-headers
364
348
"""
365
-
366
- sanitize = SanitizeValue (
367
- get_custom_headers (
368
- OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS
369
- )
370
- )
371
-
372
349
# Decode headers before processing.
373
- headers = {
350
+ headers : dict [ str , str ] = {
374
351
_key .decode ("utf8" ): _value .decode ("utf8" )
375
- for (_key , _value ) in message .get ("headers" )
352
+ for (_key , _value ) in scope_or_response_message .get ("headers" )
353
+ or cast ("list[tuple[bytes, bytes]]" , [])
376
354
}
377
-
378
355
return sanitize .sanitize_header_values (
379
356
headers ,
380
- get_custom_headers (
381
- OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE
382
- ),
383
- normalise_response_header_name ,
357
+ header_regexes ,
358
+ normalize_names ,
384
359
)
385
360
386
361
@@ -493,6 +468,9 @@ def __init__(
493
468
tracer_provider = None ,
494
469
meter_provider = None ,
495
470
meter = None ,
471
+ http_capture_headers_server_request : list [str ] | None = None ,
472
+ http_capture_headers_server_response : list [str ] | None = None ,
473
+ http_capture_headers_sanitize_fields : list [str ] | None = None ,
496
474
):
497
475
self .app = guarantee_single_callable (app )
498
476
self .tracer = trace .get_tracer (
@@ -540,7 +518,41 @@ def __init__(
540
518
self .client_response_hook = client_response_hook
541
519
self .content_length_header = None
542
520
543
- async def __call__ (self , scope , receive , send ):
521
+ # Environment variables as constructor parameters
522
+ self .http_capture_headers_server_request = (
523
+ http_capture_headers_server_request
524
+ or (
525
+ get_custom_headers (
526
+ OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST
527
+ )
528
+ )
529
+ or None
530
+ )
531
+ self .http_capture_headers_server_response = (
532
+ http_capture_headers_server_response
533
+ or (
534
+ get_custom_headers (
535
+ OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE
536
+ )
537
+ )
538
+ or None
539
+ )
540
+ self .http_capture_headers_sanitize_fields = SanitizeValue (
541
+ http_capture_headers_sanitize_fields
542
+ or (
543
+ get_custom_headers (
544
+ OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS
545
+ )
546
+ )
547
+ or []
548
+ )
549
+
550
+ async def __call__ (
551
+ self ,
552
+ scope : dict [str , Any ],
553
+ receive : Callable [[], Awaitable [dict [str , Any ]]],
554
+ send : Callable [[dict [str , Any ]], Awaitable [None ]],
555
+ ) -> None :
544
556
"""The ASGI application
545
557
546
558
Args:
@@ -583,7 +595,14 @@ async def __call__(self, scope, receive, send):
583
595
584
596
if current_span .kind == trace .SpanKind .SERVER :
585
597
custom_attributes = (
586
- collect_custom_request_headers_attributes (scope )
598
+ collect_custom_headers_attributes (
599
+ scope ,
600
+ self .http_capture_headers_sanitize_fields ,
601
+ self .http_capture_headers_server_request ,
602
+ normalise_request_header_name ,
603
+ )
604
+ if self .http_capture_headers_server_request
605
+ else {}
587
606
)
588
607
if len (custom_attributes ) > 0 :
589
608
current_span .set_attributes (custom_attributes )
@@ -658,7 +677,7 @@ def _get_otel_send(
658
677
expecting_trailers = False
659
678
660
679
@wraps (send )
661
- async def otel_send (message ):
680
+ async def otel_send (message : dict [ str , Any ] ):
662
681
nonlocal expecting_trailers
663
682
with self .tracer .start_as_current_span (
664
683
" " .join ((server_span_name , scope ["type" ], "send" ))
@@ -685,7 +704,14 @@ async def otel_send(message):
685
704
and "headers" in message
686
705
):
687
706
custom_response_attributes = (
688
- collect_custom_response_headers_attributes (message )
707
+ collect_custom_headers_attributes (
708
+ message ,
709
+ self .http_capture_headers_sanitize_fields ,
710
+ self .http_capture_headers_server_response ,
711
+ normalise_response_header_name ,
712
+ )
713
+ if self .http_capture_headers_server_response
714
+ else {}
689
715
)
690
716
if len (custom_response_attributes ) > 0 :
691
717
server_span .set_attributes (
0 commit comments