diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py index b54772a1fb..7047482d31 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py @@ -210,12 +210,20 @@ async def _(param: str): @app.get("/healthzz") async def _(): return {"message": "ok"} + + @app.get("/error") + async def _(): + raise UnhandledException("This is an unhandled exception") app.mount("/sub", app=sub_app) return app +class UnhandledException(Exception): + pass + + class TestBaseManualFastAPI(TestBaseFastAPI): @classmethod def setUpClass(cls): @@ -404,6 +412,26 @@ def test_fastapi_excluded_urls(self): spans = self.memory_exporter.get_finished_spans() self.assertEqual(len(spans), 0) + def test_fastapi_unhandled_exception(self): + """If the application has an unhandled error the instrumentation should capture that a 500 response is returned.""" + try: + self._client.get("/error") + except UnhandledException: + pass + else: + self.fail("Expected UnhandledException") + + spans = self.memory_exporter.get_finished_spans() + self.assertEqual(len(spans), 3) + for span in spans: + self.assertIn("GET /error", span.name) + self.assertEqual( + span.attributes[SpanAttributes.HTTP_ROUTE], "/error" + ) + self.assertEqual( + span.attributes[SpanAttributes.HTTP_STATUS_CODE], 500 + ) + def test_fastapi_excluded_urls_not_env(self): """Ensure that given fastapi routes are excluded when passed explicitly (not in the environment)""" app = self._create_app_explicit_excluded_urls()