Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f728abb

Browse files
committedMay 2, 2021
feat: Enable passing explicit urls to exclude from instrumentation in fastapi
1 parent cb35cc4 commit f728abb

File tree

3 files changed

+64
-6
lines changed

3 files changed

+64
-6
lines changed
 

‎instrumentation/opentelemetry-instrumentation-fastapi/README.rst

+5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ Usage
5151
5252
FastAPIInstrumentor.instrument_app(app)
5353
54+
You can also pass the list of urls to exclude explicitly to the instrumentation call:
55+
56+
.. code-block:: python
57+
from opentelemetry.util.http import ExcludeList
58+
FastAPIInstrumentor.instrument_app(app, ExcludeList("client/.*/info,healthcheck"))
5459
5560
References
5661
----------

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

+18-5
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,19 @@ class FastAPIInstrumentor(BaseInstrumentor):
3232
_original_fastapi = None
3333

3434
@staticmethod
35-
def instrument_app(app: fastapi.FastAPI, tracer_provider=None):
36-
"""Instrument an uninstrumented FastAPI application.
37-
"""
35+
def instrument_app(
36+
app: fastapi.FastAPI,
37+
tracer_provider=None,
38+
excluded_urls=None,
39+
):
40+
"""Instrument an uninstrumented FastAPI application."""
3841
if not getattr(app, "is_instrumented_by_opentelemetry", False):
42+
if excluded_urls is None:
43+
excluded_urls = _excluded_urls
44+
3945
app.add_middleware(
4046
OpenTelemetryMiddleware,
41-
excluded_urls=_excluded_urls,
47+
excluded_urls=excluded_urls,
4248
span_details_callback=_get_route_details,
4349
tracer_provider=tracer_provider,
4450
)
@@ -47,6 +53,7 @@ def instrument_app(app: fastapi.FastAPI, tracer_provider=None):
4753
def _instrument(self, **kwargs):
4854
self._original_fastapi = fastapi.FastAPI
4955
_InstrumentedFastAPI._tracer_provider = kwargs.get("tracer_provider")
56+
_InstrumentedFastAPI._excluded_urls = kwargs.get("excluded_urls")
5057
fastapi.FastAPI = _InstrumentedFastAPI
5158

5259
def _uninstrument(self, **kwargs):
@@ -55,12 +62,18 @@ def _uninstrument(self, **kwargs):
5562

5663
class _InstrumentedFastAPI(fastapi.FastAPI):
5764
_tracer_provider = None
65+
_excluded_urls = None
5866

5967
def __init__(self, *args, **kwargs):
6068
super().__init__(*args, **kwargs)
69+
excluded_urls = (
70+
_InstrumentedFastAPI._excluded_urls
71+
if _InstrumentedFastAPI._excluded_urls is not None
72+
else _excluded_urls
73+
)
6174
self.add_middleware(
6275
OpenTelemetryMiddleware,
63-
excluded_urls=_excluded_urls,
76+
excluded_urls=excluded_urls,
6477
span_details_callback=_get_route_details,
6578
tracer_provider=_InstrumentedFastAPI._tracer_provider,
6679
)

‎instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py

+41-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from opentelemetry.sdk.resources import Resource
2323
from opentelemetry.semconv.trace import SpanAttributes
2424
from opentelemetry.test.test_base import TestBase
25-
from opentelemetry.util.http import get_excluded_urls
25+
from opentelemetry.util.http import get_excluded_urls, ExcludeList
2626

2727

2828
class TestFastAPIManualInstrumentation(TestBase):
@@ -31,6 +31,17 @@ def _create_app(self):
3131
self._instrumentor.instrument_app(app)
3232
return app
3333

34+
def _create_app_explicit_excluded_urls(self):
35+
app = self._create_fastapi_app()
36+
to_exclude = "/user/123,/foobar"
37+
excluded_urls = [
38+
excluded_url.strip() for excluded_url in to_exclude.split(",")
39+
]
40+
self._instrumentor.instrument_app(
41+
app, excluded_urls=ExcludeList(excluded_urls)
42+
)
43+
return app
44+
3445
def setUp(self):
3546
super().setUp()
3647
self.env_patch = patch.dict(
@@ -84,6 +95,17 @@ def test_fastapi_excluded_urls(self):
8495
spans = self.memory_exporter.get_finished_spans()
8596
self.assertEqual(len(spans), 0)
8697

98+
def test_fastapi_excluded_urls_not_env(self):
99+
"""Ensure that given fastapi routes are excluded when passed explicitly (not in the environment)"""
100+
app = self._create_app_explicit_excluded_urls()
101+
client = TestClient(app)
102+
client.get("/user/123")
103+
spans = self.memory_exporter.get_finished_spans()
104+
self.assertEqual(len(spans), 0)
105+
client.get("/foobar")
106+
spans = self.memory_exporter.get_finished_spans()
107+
self.assertEqual(len(spans), 0)
108+
87109
@staticmethod
88110
def _create_fastapi_app():
89111
app = fastapi.FastAPI()
@@ -124,6 +146,24 @@ def _create_app(self):
124146
self._instrumentor.instrument(tracer_provider=tracer_provider)
125147
return self._create_fastapi_app()
126148

149+
def _create_app_explicit_excluded_urls(self):
150+
resource = Resource.create({"key1": "value1", "key2": "value2"})
151+
tracer_provider, exporter = self.create_tracer_provider(
152+
resource=resource
153+
)
154+
self.memory_exporter = exporter
155+
156+
to_exclude = "/user/123,/foobar"
157+
excluded_urls = [
158+
excluded_url.strip() for excluded_url in to_exclude.split(",")
159+
]
160+
self._instrumentor.uninstrument() # Disable previous instrumentation (setUp)
161+
self._instrumentor.instrument(
162+
tracer_provider=tracer_provider,
163+
excluded_urls=ExcludeList(excluded_urls),
164+
)
165+
return self._create_fastapi_app()
166+
127167
def test_request(self):
128168
self._client.get("/foobar")
129169
spans = self.memory_exporter.get_finished_spans()

0 commit comments

Comments
 (0)
Please sign in to comment.