Skip to content

Commit 55e9c43

Browse files
committed
record FastAPI hook exceptions in active span
1 parent 6c48703 commit 55e9c43

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A
209209
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
210210
from opentelemetry.metrics import MeterProvider, get_meter
211211
from opentelemetry.semconv.attributes.http_attributes import HTTP_ROUTE
212-
from opentelemetry.trace import TracerProvider, get_tracer
212+
from opentelemetry.trace import Span, TracerProvider, get_tracer
213213
from opentelemetry.util.http import (
214214
get_excluded_urls,
215215
parse_excluded_urls,
@@ -296,11 +296,18 @@ def instrument_app(
296296
def build_middleware_stack(self: Starlette) -> ASGIApp:
297297
def failsafe(func):
298298
@functools.wraps(func)
299-
def wrapper(*args, **kwargs):
299+
def wrapper(span: Span, *args, **kwargs):
300300
try:
301-
func(*args, **kwargs)
302-
except Exception: # pylint: disable=W0718
303-
pass
301+
func(span, *args, **kwargs)
302+
except Exception as exc: # pylint: disable=W0718
303+
span.record_exception(exc)
304+
# span.set_status(Status(StatusCode.ERROR, str(exc)))
305+
# if span.is_recording():
306+
# span.set_attribute(
307+
# ErrorAttributes.ERROR_TYPE, type(exc).__qualname__
308+
# )
309+
# if span.record_exception
310+
# span.end()
304311

305312
return wrapper
306313

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@
5959
from opentelemetry.semconv._incubating.attributes.net_attributes import (
6060
NET_HOST_PORT,
6161
)
62+
from opentelemetry.semconv.attributes.exception_attributes import (
63+
EXCEPTION_TYPE,
64+
)
6265
from opentelemetry.semconv.attributes.http_attributes import (
6366
HTTP_REQUEST_METHOD,
6467
HTTP_RESPONSE_STATUS_CODE,
@@ -1981,3 +1984,22 @@ def test_failsafe_hooks(self):
19811984
)
19821985

19831986
self.assertEqual(200, resp.status_code)
1987+
1988+
def test_failsafe_error_recording(self):
1989+
"""Failing hooks must record the exception on the span"""
1990+
self.client.get(
1991+
"/foobar",
1992+
)
1993+
1994+
spans = self.memory_exporter.get_finished_spans()
1995+
1996+
self.assertEqual(len(spans), 3)
1997+
span = spans[0]
1998+
self.assertEqual(len(span.events), 1)
1999+
event = span.events[0]
2000+
self.assertEqual(event.name, "exception")
2001+
assert event.attributes is not None
2002+
self.assertEqual(
2003+
event.attributes.get(EXCEPTION_TYPE),
2004+
f"{__name__}.UnhandledException",
2005+
)

0 commit comments

Comments
 (0)