From 0415de35a5d327f6b0bb05a8001245defd0db886 Mon Sep 17 00:00:00 2001 From: Peter Giacomo Lombardo Date: Tue, 3 Dec 2019 11:48:14 +0100 Subject: [PATCH] Fixed and improved error capture and reporting --- instana/instrumentation/aiohttp/server.py | 8 +++- tests/apps/app_aiohttp.py | 7 ++- tests/test_aiohttp.py | 52 ++++++++++++++++++++++- 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/instana/instrumentation/aiohttp/server.py b/instana/instrumentation/aiohttp/server.py index 38f94e26..9638bd3c 100644 --- a/instana/instrumentation/aiohttp/server.py +++ b/instana/instrumentation/aiohttp/server.py @@ -52,8 +52,12 @@ async def stan_middleware(request, handler): response.headers['Server-Timing'] = "intid;desc=%s" % scope.span.context.trace_id return response - except Exception: + except Exception as e: logger.debug("aiohttp stan_middleware", exc_info=True) + if scope is not None: + scope.span.set_tag("http.status_code", 500) + scope.span.log_exception(e) + raise finally: if scope is not None: scope.close() @@ -62,7 +66,7 @@ async def stan_middleware(request, handler): @wrapt.patch_function_wrapper('aiohttp.web','Application.__init__') def init_with_instana(wrapped, instance, argv, kwargs): if "middlewares" in kwargs: - kwargs["middlewares"].append(stan_middleware) + kwargs["middlewares"].insert(0, stan_middleware) else: kwargs["middlewares"] = [stan_middleware] diff --git a/tests/apps/app_aiohttp.py b/tests/apps/app_aiohttp.py index e2ffc9da..583edabb 100644 --- a/tests/apps/app_aiohttp.py +++ b/tests/apps/app_aiohttp.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python + #!/usr/bin/env python # -*- coding: utf-8 -*- import asyncio from aiohttp import web @@ -22,6 +22,10 @@ def five_hundred(request): return web.HTTPInternalServerError(reason="I must simulate errors.", text="Simulated server error.") +def raise_exception(request): + raise Exception("Simulated exception") + + def run_server(): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) @@ -30,6 +34,7 @@ def run_server(): app.add_routes([web.get('/', say_hello)]) app.add_routes([web.get('/401', four_hundred_one)]) app.add_routes([web.get('/500', five_hundred)]) + app.add_routes([web.get('/exception', raise_exception)]) runner = web.AppRunner(app) loop.run_until_complete(runner.setup()) diff --git a/tests/test_aiohttp.py b/tests/test_aiohttp.py index 3b59b3ff..92e10857 100644 --- a/tests/test_aiohttp.py +++ b/tests/test_aiohttp.py @@ -510,7 +510,6 @@ async def test(): assert("Server-Timing" in response.headers) self.assertEqual(response.headers["Server-Timing"], "intid;desc=%s" % traceId) - def test_server_custom_header_capture(self): async def test(): with async_tracer.start_active_span('test'): @@ -703,3 +702,54 @@ async def test(): assert("Server-Timing" in response.headers) self.assertEqual(response.headers["Server-Timing"], "intid;desc=%s" % traceId) + + def test_server_get_exception(self): + async def test(): + with async_tracer.start_active_span('test'): + async with aiohttp.ClientSession() as session: + return await self.fetch(session, testenv["aiohttp_server"] + "/exception") + + response = self.loop.run_until_complete(test()) + + spans = self.recorder.queued_spans() + self.assertEqual(3, len(spans)) + + aioserver_span = spans[0] + aioclient_span = spans[1] + test_span = spans[2] + + self.assertIsNone(async_tracer.active_span) + + # Same traceId + traceId = test_span.t + self.assertEqual(traceId, aioclient_span.t) + self.assertEqual(traceId, aioserver_span.t) + + # Parent relationships + self.assertEqual(aioclient_span.p, test_span.s) + self.assertEqual(aioserver_span.p, aioclient_span.s) + + # Error logging + self.assertFalse(test_span.error) + self.assertIsNone(test_span.ec) + self.assertTrue(aioclient_span.error) + self.assertEqual(aioclient_span.ec, 1) + self.assertTrue(aioserver_span.error) + self.assertEqual(aioserver_span.ec, 1) + + self.assertEqual("aiohttp-server", aioserver_span.n) + self.assertEqual(500, aioserver_span.data.http.status) + self.assertEqual(testenv["aiohttp_server"] + "/exception", aioserver_span.data.http.url) + self.assertEqual("GET", aioserver_span.data.http.method) + self.assertIsNotNone(aioserver_span.stack) + self.assertTrue(type(aioserver_span.stack) is list) + self.assertTrue(len(aioserver_span.stack) > 1) + + self.assertEqual("aiohttp-client", aioclient_span.n) + self.assertEqual(500, aioclient_span.data.http.status) + self.assertEqual(testenv["aiohttp_server"] + "/exception", aioclient_span.data.http.url) + self.assertEqual("GET", aioclient_span.data.http.method) + self.assertEqual('Internal Server Error', aioclient_span.data.http.error) + self.assertIsNotNone(aioclient_span.stack) + self.assertTrue(type(aioclient_span.stack) is list) + self.assertTrue(len(aioclient_span.stack) > 1)