@@ -442,3 +442,101 @@ def test_mark_span_internal_in_presence_of_span_from_other_framework(self):
442442 self .assertEqual (
443443 span_list [0 ].parent .span_id , span_list [1 ].context .span_id
444444 )
445+
446+
447+ class TestCustomRequestResponseHeaders (
448+ InstrumentationTest , TestBase , WsgiTestBase
449+ ):
450+ def setUp (self ):
451+ super ().setUp ()
452+
453+ self .env_patch = patch .dict (
454+ "os.environ" ,
455+ {
456+ "OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST" : "Custom-Test-Header-1,Custom-Test-Header-2,Custom-Test-Header-3" ,
457+ "OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE" : "content-type,content-length,my-custom-header,invalid-header" ,
458+ },
459+ )
460+ self .env_patch .start ()
461+ self .app = Flask (__name__ )
462+ FlaskInstrumentor ().instrument_app (self .app )
463+
464+ self ._common_initialization ()
465+
466+ def tearDown (self ):
467+ super ().tearDown ()
468+ self .env_patch .stop ()
469+ with self .disable_logging ():
470+ FlaskInstrumentor ().uninstrument_app (self .app )
471+
472+ def test_custom_request_header_added_in_server_span (self ):
473+ headers = {
474+ "Custom-Test-Header-1" : "Test Value 1" ,
475+ "Custom-Test-Header-2" : "TestValue2,TestValue3" ,
476+ }
477+ resp = self .client .get ("/hello/123" , headers = headers )
478+ self .assertEqual (200 , resp .status_code )
479+ span = self .memory_exporter .get_finished_spans ()[0 ]
480+ expected = {
481+ "http.request.header.custom_test_header_1" : ("Test Value 1" ,),
482+ "http.request.header.custom_test_header_2" : (
483+ "TestValue2,TestValue3" ,
484+ ),
485+ }
486+ self .assertEqual (span .kind , trace .SpanKind .SERVER )
487+ self .assertSpanHasAttributes (span , expected )
488+
489+ def test_custom_request_header_not_added_in_internal_span (self ):
490+ tracer = trace .get_tracer (__name__ )
491+ with tracer .start_as_current_span ("test" , kind = trace .SpanKind .SERVER ):
492+ headers = {
493+ "Custom-Test-Header-1" : "Test Value 1" ,
494+ "Custom-Test-Header-2" : "TestValue2,TestValue3" ,
495+ }
496+ resp = self .client .get ("/hello/123" , headers = headers )
497+ self .assertEqual (200 , resp .status_code )
498+ span = self .memory_exporter .get_finished_spans ()[0 ]
499+ not_expected = {
500+ "http.request.header.custom_test_header_1" : ("Test Value 1" ,),
501+ "http.request.header.custom_test_header_2" : (
502+ "TestValue2,TestValue3" ,
503+ ),
504+ }
505+ self .assertEqual (span .kind , trace .SpanKind .INTERNAL )
506+ for key , _ in not_expected .items ():
507+ self .assertNotIn (key , span .attributes )
508+
509+ def test_custom_response_header_added_in_server_span (self ):
510+ resp = self .client .get ("/test_custom_response_headers" )
511+ self .assertEqual (resp .status_code , 200 )
512+ span = self .memory_exporter .get_finished_spans ()[0 ]
513+ expected = {
514+ "http.response.header.content_type" : (
515+ "text/plain; charset=utf-8" ,
516+ ),
517+ "http.response.header.content_length" : ("13" ,),
518+ "http.response.header.my_custom_header" : (
519+ "my-custom-value-1,my-custom-header-2" ,
520+ ),
521+ }
522+ self .assertEqual (span .kind , trace .SpanKind .SERVER )
523+ self .assertSpanHasAttributes (span , expected )
524+
525+ def test_custom_response_header_not_added_in_internal_span (self ):
526+ tracer = trace .get_tracer (__name__ )
527+ with tracer .start_as_current_span ("test" , kind = trace .SpanKind .SERVER ):
528+ resp = self .client .get ("/test_custom_response_headers" )
529+ self .assertEqual (resp .status_code , 200 )
530+ span = self .memory_exporter .get_finished_spans ()[0 ]
531+ not_expected = {
532+ "http.response.header.content_type" : (
533+ "text/plain; charset=utf-8" ,
534+ ),
535+ "http.response.header.content_length" : ("13" ,),
536+ "http.response.header.my_custom_header" : (
537+ "my-custom-value-1,my-custom-header-2" ,
538+ ),
539+ }
540+ self .assertEqual (span .kind , trace .SpanKind .INTERNAL )
541+ for key , _ in not_expected .items ():
542+ self .assertNotIn (key , span .attributes )
0 commit comments