@@ -414,3 +414,103 @@ def done(_):
414414 assert test_span
415415 # Failure path must mark the span errored
416416 assert twisted_client_span .ec == 1
417+
418+ def test_agent_request_200 (self ) -> None :
419+ """Twisted Agent.request 200 — exercises _finish_tracing success path
420+ (lines 109-111, 126-129 in client.py)."""
421+ response , failure = self ._make_request ("/" )
422+
423+ assert failure is None
424+ assert response is not None
425+ assert response .code == 200
426+
427+ time .sleep (0.5 )
428+ spans = self .recorder .queued_spans ()
429+
430+ twisted_client_span = get_first_span_by_name (spans , "twisted-client" )
431+ test_span = get_first_span_by_name (spans , "sdk" )
432+
433+ assert twisted_client_span
434+ assert test_span
435+
436+ # Same trace
437+ assert twisted_client_span .t == test_span .t
438+ assert twisted_client_span .p == test_span .s
439+
440+ assert twisted_client_span .data ["http" ]["status" ] == 200
441+ assert twisted_client_span .data ["http" ]["method" ] == "GET"
442+ assert not twisted_client_span .ec
443+
444+ def test_agent_request_500_marks_errored (self ) -> None :
445+ """Twisted Agent.request 500 — exercises `status_code >= 400` branch
446+ (lines 113-114 in client.py)."""
447+ response , failure = self ._make_request ("/500" )
448+
449+ assert failure is None
450+ assert response is not None
451+ assert response .code == 500
452+
453+ time .sleep (0.5 )
454+ spans = self .recorder .queued_spans ()
455+
456+ twisted_client_span = get_first_span_by_name (spans , "twisted-client" )
457+ test_span = get_first_span_by_name (spans , "sdk" )
458+
459+ assert twisted_client_span
460+ assert test_span
461+
462+ assert twisted_client_span .data ["http" ]["status" ] == 500
463+ assert twisted_client_span .ec == 1
464+
465+ def test_agent_request_response_headers (self ) -> None :
466+ """Twisted Agent.request captures response headers — exercises
467+ extract_custom_headers in _finish_tracing (lines 117-121 in client.py)."""
468+ from instana .singletons import agent as instana_agent
469+
470+ original = instana_agent .options .extra_http_headers
471+ instana_agent .options .extra_http_headers = [
472+ "X-Capture-This-Too" ,
473+ "X-Capture-That-Too" ,
474+ ]
475+
476+ try :
477+ response , failure = self ._make_request ("/response_headers" )
478+ finally :
479+ instana_agent .options .extra_http_headers = original
480+
481+ assert failure is None
482+ assert response is not None
483+
484+ time .sleep (0.5 )
485+ spans = self .recorder .queued_spans ()
486+
487+ twisted_client_span = get_first_span_by_name (spans , "twisted-client" )
488+ assert twisted_client_span
489+
490+ assert "X-Capture-This-Too" in twisted_client_span .data ["http" ]["header" ]
491+ assert (
492+ twisted_client_span .data ["http" ]["header" ]["X-Capture-This-Too" ]
493+ == "this too"
494+ )
495+ assert "X-Capture-That-Too" in twisted_client_span .data ["http" ]["header" ]
496+ assert (
497+ twisted_client_span .data ["http" ]["header" ]["X-Capture-That-Too" ]
498+ == "that too"
499+ )
500+
501+ def test_agent_request_query_params_scrubbed (self ) -> None :
502+ """Twisted Agent.request with query params — exercises param scrubbing
503+ (lines 56-61 in client.py) and sets http.params on the span."""
504+ response , failure = self ._make_request ("/" , params = {"secret" : "topsecret" })
505+
506+ assert failure is None
507+ assert response is not None
508+
509+ time .sleep (0.5 )
510+ spans = self .recorder .queued_spans ()
511+
512+ twisted_client_span = get_first_span_by_name (spans , "twisted-client" )
513+ assert twisted_client_span
514+
515+ assert twisted_client_span .data ["http" ]["params" ] == "secret=<redacted>"
516+ assert twisted_client_span .data ["http" ]["url" ].endswith ("/" )
0 commit comments