Skip to content

Commit a9632d3

Browse files
samuelcolvinocelotl
authored andcommitted
feat: add header extraction parameters to FastAPIInstrumentor().instrument_app (open-telemetry#2241)
* add header parameters to FastAPIInstrumentor().instrument_app * add changelog * move open-telemetry#2072 changelog to unreleased * remove accidental pprint * linting * future annotations for fastapi * same logic for instrument() * Fix lint * Fix test case --------- Co-authored-by: Diego Hurtado <ocelotl@users.noreply.github.com>
1 parent f478267 commit a9632d3

File tree

3 files changed

+571
-10
lines changed

3 files changed

+571
-10
lines changed

CHANGELOG.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
216216
([#2367](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2367))
217217

218218

219+
### Added
220+
- `opentelemetry-instrumentation-fastapi` Add support for configuring header extraction via runtime constructor parameters
221+
([#2241](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2241))
222+
219223
## Version 1.23.0/0.44b0 (2024-02-23)
220224

221225
- Drop support for 3.7
@@ -236,6 +240,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
236240
### Added
237241

238242
- `opentelemetry-instrumentation-psycopg` Initial release for psycopg 3.x
243+
- `opentelemetry-instrumentation-asgi` Add support for configuring ASGI middleware header extraction via runtime constructor parameters
244+
([#2026](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2026))
239245

240246
## Version 1.22.0/0.43b0 (2023-12-14)
241247

@@ -275,8 +281,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
275281
([#1948](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1948))
276282
- Added schema_url (`"https://opentelemetry.io/schemas/1.11.0"`) to all metrics and traces
277283
([#1977](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1977))
278-
- Add support for configuring ASGI middleware header extraction via runtime constructor parameters
279-
([#2026](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/2026))
280284

281285
### Fixed
282286

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

+32-7
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
8686
Request headers
8787
***************
8888
To capture HTTP request headers as span attributes, set the environment variable
89-
``OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST`` to a comma delimited list of HTTP header names.
89+
``OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST`` to a comma delimited list of HTTP header names,
90+
or pass the ``http_capture_headers_server_request`` keyword argument to the ``instrument_app`` method.
9091
91-
For example,
92+
For example using the environment variable,
9293
::
9394
9495
export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST="content-type,custom_request_header"
@@ -120,9 +121,10 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
120121
Response headers
121122
****************
122123
To capture HTTP response headers as span attributes, set the environment variable
123-
``OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE`` to a comma delimited list of HTTP header names.
124+
``OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE`` to a comma delimited list of HTTP header names,
125+
or pass the ``http_capture_headers_server_response`` keyword argument to the ``instrument_app`` method.
124126
125-
For example,
127+
For example using the environment variable,
126128
::
127129
128130
export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE="content-type,custom_response_header"
@@ -155,10 +157,12 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
155157
******************
156158
In order to prevent storing sensitive data such as personally identifiable information (PII), session keys, passwords,
157159
etc, set the environment variable ``OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS``
158-
to a comma delimited list of HTTP header names to be sanitized. Regexes may be used, and all header names will be
159-
matched in a case-insensitive manner.
160+
to a comma delimited list of HTTP header names to be sanitized, or pass the ``http_capture_headers_sanitize_fields``
161+
keyword argument to the ``instrument_app`` method.
160162
161-
For example,
163+
Regexes may be used, and all header names will be matched in a case-insensitive manner.
164+
165+
For example using the environment variable,
162166
::
163167
164168
export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SANITIZE_FIELDS=".*session.*,set-cookie"
@@ -171,6 +175,9 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
171175
API
172176
---
173177
"""
178+
179+
from __future__ import annotations
180+
174181
import logging
175182
from importlib.metadata import PackageNotFoundError, distribution
176183
from typing import Collection
@@ -227,6 +234,9 @@ def instrument_app(
227234
tracer_provider=None,
228235
meter_provider=None,
229236
excluded_urls=None,
237+
http_capture_headers_server_request: list[str] | None = None,
238+
http_capture_headers_server_response: list[str] | None = None,
239+
http_capture_headers_sanitize_fields: list[str] | None = None,
230240
):
231241
"""Instrument an uninstrumented FastAPI application."""
232242
if not hasattr(app, "_is_instrumented_by_opentelemetry"):
@@ -265,6 +275,9 @@ def instrument_app(
265275
# Pass in tracer/meter to get __name__and __version__ of fastapi instrumentation
266276
tracer=tracer,
267277
meter=meter,
278+
http_capture_headers_server_request=http_capture_headers_server_request,
279+
http_capture_headers_server_response=http_capture_headers_server_response,
280+
http_capture_headers_sanitize_fields=http_capture_headers_sanitize_fields,
268281
)
269282
app._is_instrumented_by_opentelemetry = True
270283
if app not in _InstrumentedFastAPI._instrumented_fastapi_apps:
@@ -314,6 +327,15 @@ def _instrument(self, **kwargs):
314327
_InstrumentedFastAPI._client_response_hook = kwargs.get(
315328
"client_response_hook"
316329
)
330+
_InstrumentedFastAPI._http_capture_headers_server_request = kwargs.get(
331+
"http_capture_headers_server_request"
332+
)
333+
_InstrumentedFastAPI._http_capture_headers_server_response = (
334+
kwargs.get("http_capture_headers_server_response")
335+
)
336+
_InstrumentedFastAPI._http_capture_headers_sanitize_fields = (
337+
kwargs.get("http_capture_headers_sanitize_fields")
338+
)
317339
_excluded_urls = kwargs.get("excluded_urls")
318340
_InstrumentedFastAPI._excluded_urls = (
319341
_excluded_urls_from_env
@@ -368,6 +390,9 @@ def __init__(self, *args, **kwargs):
368390
# Pass in tracer/meter to get __name__and __version__ of fastapi instrumentation
369391
tracer=tracer,
370392
meter=meter,
393+
http_capture_headers_server_request=_InstrumentedFastAPI._http_capture_headers_server_request,
394+
http_capture_headers_server_response=_InstrumentedFastAPI._http_capture_headers_server_response,
395+
http_capture_headers_sanitize_fields=_InstrumentedFastAPI._http_capture_headers_sanitize_fields,
371396
)
372397
self._is_instrumented_by_opentelemetry = True
373398
_InstrumentedFastAPI._instrumented_fastapi_apps.add(self)

0 commit comments

Comments
 (0)