Skip to content

Commit 899679a

Browse files
committed
Update FastAPI implementation
1 parent 2c056d9 commit 899679a

File tree

2 files changed

+39
-15
lines changed

2 files changed

+39
-15
lines changed

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

+36-12
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ def instrument_app(
227227
app.add_middleware(
228228
OpenTelemetryMiddleware,
229229
excluded_urls=excluded_urls,
230-
default_span_details=_get_route_details,
230+
default_span_details=_get_default_span_details,
231231
server_request_hook=server_request_hook,
232232
client_request_hook=client_request_hook,
233233
client_response_hook=client_response_hook,
@@ -300,7 +300,7 @@ def __init__(self, *args, **kwargs):
300300
self.add_middleware(
301301
OpenTelemetryMiddleware,
302302
excluded_urls=_InstrumentedFastAPI._excluded_urls,
303-
default_span_details=_get_route_details,
303+
default_span_details=_get_default_span_details,
304304
server_request_hook=_InstrumentedFastAPI._server_request_hook,
305305
client_request_hook=_InstrumentedFastAPI._client_request_hook,
306306
client_response_hook=_InstrumentedFastAPI._client_response_hook,
@@ -315,27 +315,51 @@ def __del__(self):
315315
_InstrumentedFastAPI._instrumented_fastapi_apps.remove(self)
316316

317317

318-
def _get_route_details(scope):
319-
"""Callback to retrieve the fastapi route being served.
318+
def _get_default_span_details(scope):
319+
"""
320+
Callback to retrieve span name and attributes from scope.
321+
322+
Args:
323+
scope: A Starlette scope
324+
Returns:
325+
A tuple of span name and attributes
326+
"""
327+
route = _get_route_details(scope)
328+
method = scope.get("method", "")
329+
attributes = {}
330+
if route:
331+
attributes[SpanAttributes.HTTP_ROUTE] = route
332+
if method and route: # http
333+
span_name = f"{method} {route}"
334+
elif route: # websocket
335+
span_name = route
336+
else: # fallback
337+
span_name = method
338+
return span_name, attributes
339+
320340

341+
def _get_route_details(scope):
342+
"""
343+
Function to retrieve Starlette route from scope.
344+
321345
TODO: there is currently no way to retrieve http.route from
322346
a starlette application from scope.
323-
324347
See: https://github.com/encode/starlette/pull/804
348+
349+
Args:
350+
scope: A Starlette scope
351+
Returns:
352+
A string containing the route or None
325353
"""
326354
app = scope["app"]
327355
route = None
356+
328357
for starlette_route in app.routes:
329358
match, _ = starlette_route.matches(scope)
330359
if match == Match.FULL:
331360
route = starlette_route.path
332361
break
333362
if match == Match.PARTIAL:
334363
route = starlette_route.path
335-
# method only exists for http, if websocket
336-
# leave it blank.
337-
span_name = route or scope.get("method", "")
338-
attributes = {}
339-
if route:
340-
attributes[SpanAttributes.HTTP_ROUTE] = route
341-
return span_name, attributes
364+
return route
365+

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ def test_instrument_app_with_instrument(self):
106106
spans = self.memory_exporter.get_finished_spans()
107107
self.assertEqual(len(spans), 3)
108108
for span in spans:
109-
self.assertIn("/foobar", span.name)
109+
self.assertIn("GET /foobar", span.name)
110110

111111
def test_uninstrument_app(self):
112112
self._client.get("/foobar")
@@ -138,15 +138,15 @@ def test_basic_fastapi_call(self):
138138
spans = self.memory_exporter.get_finished_spans()
139139
self.assertEqual(len(spans), 3)
140140
for span in spans:
141-
self.assertIn("/foobar", span.name)
141+
self.assertIn("GET /foobar", span.name)
142142

143143
def test_fastapi_route_attribute_added(self):
144144
"""Ensure that fastapi routes are used as the span name."""
145145
self._client.get("/user/123")
146146
spans = self.memory_exporter.get_finished_spans()
147147
self.assertEqual(len(spans), 3)
148148
for span in spans:
149-
self.assertIn("/user/{username}", span.name)
149+
self.assertIn("GET /user/{username}", span.name)
150150
self.assertEqual(
151151
spans[-1].attributes[SpanAttributes.HTTP_ROUTE], "/user/{username}"
152152
)

0 commit comments

Comments
 (0)