Skip to content

Commit 6dece9b

Browse files
committed
move failsafe hook tests to ASGI test suite
1 parent 3d4afe6 commit 6dece9b

File tree

2 files changed

+51
-56
lines changed

2 files changed

+51
-56
lines changed

instrumentation/opentelemetry-instrumentation-asgi/tests/test_asgi_middleware.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,17 @@ async def error_asgi(scope, receive, send):
277277
await send({"type": "http.response.body", "body": b"*"})
278278

279279

280+
class UnhandledException(Exception):
281+
pass
282+
283+
284+
def failing_hook(msg):
285+
def hook(*_):
286+
raise UnhandledException(msg)
287+
288+
return hook
289+
290+
280291
# pylint: disable=too-many-public-methods
281292
class TestAsgiApplication(AsyncAsgiTestBase):
282293
def setUp(self):
@@ -481,6 +492,12 @@ def validate_outputs(
481492
span.instrumentation_scope.name,
482493
"opentelemetry.instrumentation.asgi",
483494
)
495+
if "events" in expected:
496+
self.assertEqual(len(span.events), len(expected["events"]))
497+
for event, expected in zip(span.events, expected["events"]):
498+
self.assertEqual(event.name, expected["name"])
499+
for k, v in expected["attributes"].items():
500+
self.assertEqual(event.attributes[k], v)
484501

485502
async def test_basic_asgi_call(self):
486503
"""Test that spans are emitted as expected."""
@@ -1206,6 +1223,40 @@ def update_expected_hook_results(expected):
12061223
outputs, modifiers=[update_expected_hook_results]
12071224
)
12081225

1226+
async def test_hook_exceptions(self):
1227+
def exception_event(msg):
1228+
return {
1229+
"name": "exception",
1230+
"attributes": {
1231+
"exception.type": f"{__name__}.UnhandledException",
1232+
"exception.message": msg,
1233+
},
1234+
}
1235+
1236+
def update_expected_hook_results(expected):
1237+
for entry in expected:
1238+
if entry["kind"] == trace_api.SpanKind.SERVER:
1239+
entry["events"] = [exception_event("server request")]
1240+
elif entry["name"] == "GET / http receive":
1241+
entry["events"] = [exception_event("client request")]
1242+
elif entry["name"] == "GET / http send":
1243+
entry["events"] = [exception_event("client response")]
1244+
1245+
return expected
1246+
1247+
app = otel_asgi.OpenTelemetryMiddleware(
1248+
simple_asgi,
1249+
server_request_hook=failing_hook("server request"),
1250+
client_request_hook=failing_hook("client request"),
1251+
client_response_hook=failing_hook("client response"),
1252+
)
1253+
self.seed_app(app)
1254+
await self.send_default_request()
1255+
outputs = await self.get_all_output()
1256+
self.validate_outputs(
1257+
outputs, modifiers=[update_expected_hook_results]
1258+
)
1259+
12091260
async def test_asgi_metrics(self):
12101261
app = otel_asgi.OpenTelemetryMiddleware(simple_asgi)
12111262
self.seed_app(app)

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

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2014,59 +2014,3 @@ async def _(*_):
20142014
event.attributes.get(EXCEPTION_TYPE),
20152015
f"{__name__}.UnhandledException",
20162016
)
2017-
2018-
2019-
class TestFailsafeHooks(TestBase):
2020-
"""Tests to ensure FastAPI instrumentation hooks don't tear through"""
2021-
2022-
def setUp(self):
2023-
super().setUp()
2024-
2025-
self.app = fastapi.FastAPI()
2026-
2027-
@self.app.get("/foobar")
2028-
async def _():
2029-
return {"message": "Hello World"}
2030-
2031-
def failing_hook(*_):
2032-
raise UnhandledException("Hook Exception")
2033-
2034-
otel_fastapi.FastAPIInstrumentor().instrument_app(
2035-
self.app,
2036-
server_request_hook=failing_hook,
2037-
client_request_hook=failing_hook,
2038-
client_response_hook=failing_hook,
2039-
)
2040-
self.client = TestClient(self.app)
2041-
2042-
def tearDown(self) -> None:
2043-
super().tearDown()
2044-
with self.disable_logging():
2045-
otel_fastapi.FastAPIInstrumentor().uninstrument_app(self.app)
2046-
2047-
def test_failsafe_hooks(self):
2048-
"""Crashing hooks must not tear through"""
2049-
resp = self.client.get(
2050-
"/foobar",
2051-
)
2052-
2053-
self.assertEqual(200, resp.status_code)
2054-
2055-
def test_failsafe_error_recording(self):
2056-
"""Failing hooks must record the exception on the span"""
2057-
self.client.get(
2058-
"/foobar",
2059-
)
2060-
2061-
spans = self.memory_exporter.get_finished_spans()
2062-
2063-
self.assertEqual(len(spans), 3)
2064-
span = spans[0]
2065-
self.assertEqual(len(span.events), 1)
2066-
event = span.events[0]
2067-
self.assertEqual(event.name, "exception")
2068-
assert event.attributes is not None
2069-
self.assertEqual(
2070-
event.attributes.get(EXCEPTION_TYPE),
2071-
f"{__name__}.UnhandledException",
2072-
)

0 commit comments

Comments
 (0)