Skip to content

Commit 416246c

Browse files
committed
urllib: add support for capturing request and response headers
1 parent 4531513 commit 416246c

File tree

2 files changed

+404
-2
lines changed

2 files changed

+404
-2
lines changed

instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,15 @@ def response_hook(span: Span, request: Request, response: HTTPResponse):
135135
)
136136
from opentelemetry.trace import Span, SpanKind, Tracer, get_tracer
137137
from opentelemetry.util.http import (
138+
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_REQUEST,
139+
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_RESPONSE,
140+
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS,
138141
ExcludeList,
142+
get_custom_header_attributes,
143+
get_custom_headers,
139144
get_excluded_urls,
145+
normalise_request_header_name,
146+
normalise_response_header_name,
140147
parse_excluded_urls,
141148
redact_url,
142149
sanitize_method,
@@ -169,6 +176,9 @@ def _instrument(self, **kwargs: Any):
169176
``response_hook``: An optional callback which is invoked right before the span is finished processing a response
170177
``excluded_urls``: A string containing a comma-delimited
171178
list of regexes used to exclude URLs from tracking
179+
``captured_request_headers``: A comma-separated list of regexes to match against request headers to capture
180+
``captured_response_headers``: A comma-separated list of regexes to match against response headers to capture
181+
``sensitive_headers``: A comma-separated list of regexes to match against captured headers to be sanitized
172182
"""
173183
# initialize semantic conventions opt-in if needed
174184
_OpenTelemetrySemanticConventionStability._initialize()
@@ -205,6 +215,24 @@ def _instrument(self, **kwargs: Any):
205215
else parse_excluded_urls(excluded_urls)
206216
),
207217
sem_conv_opt_in_mode=sem_conv_opt_in_mode,
218+
captured_request_headers=kwargs.get(
219+
"captured_request_headers",
220+
get_custom_headers(
221+
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_REQUEST
222+
),
223+
),
224+
captured_response_headers=kwargs.get(
225+
"captured_response_headers",
226+
get_custom_headers(
227+
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_CLIENT_RESPONSE
228+
),
229+
),
230+
sensitive_headers=kwargs.get(
231+
"sensitive_headers",
232+
get_custom_headers(
233+
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS
234+
),
235+
),
208236
)
209237

210238
def _uninstrument(self, **kwargs: Any):
@@ -223,6 +251,9 @@ def _instrument(
223251
response_hook: _ResponseHookT = None,
224252
excluded_urls: ExcludeList | None = None,
225253
sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT,
254+
captured_request_headers: list[str] | None = None,
255+
captured_response_headers: list[str] | None = None,
256+
sensitive_headers: list[str] | None = None,
226257
):
227258
"""Enables tracing of all requests calls that go through
228259
:code:`urllib.Client._make_request`"""
@@ -275,6 +306,15 @@ def _instrumented_open_call(
275306
)
276307
_set_http_url(labels, url, sem_conv_opt_in_mode)
277308

309+
labels.update(
310+
get_custom_header_attributes(
311+
request.headers,
312+
captured_request_headers,
313+
sensitive_headers,
314+
normalise_request_header_name,
315+
)
316+
)
317+
278318
with tracer.start_as_current_span(
279319
span_name, kind=SpanKind.CLIENT, attributes=labels
280320
) as span:
@@ -310,6 +350,16 @@ def _instrumented_open_call(
310350
labels, f"{ver_[:1]}.{ver_[:-1]}", sem_conv_opt_in_mode
311351
)
312352

353+
if span.is_recording():
354+
response_headers_to_set = get_custom_header_attributes(
355+
result.headers,
356+
captured_response_headers,
357+
sensitive_headers,
358+
normalise_response_header_name,
359+
)
360+
for header, value in response_headers_to_set.items():
361+
span.set_attribute(header, value)
362+
313363
if exception is not None and _report_new(sem_conv_opt_in_mode):
314364
span.set_attribute(ERROR_TYPE, type(exception).__qualname__)
315365
labels[ERROR_TYPE] = type(exception).__qualname__

0 commit comments

Comments
 (0)