Skip to content

Commit dc3b8f3

Browse files
authored
Fixed and improved error capture and reporting (#202)
1 parent aa1bc4c commit dc3b8f3

File tree

3 files changed

+63
-4
lines changed

3 files changed

+63
-4
lines changed

instana/instrumentation/aiohttp/server.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,12 @@ async def stan_middleware(request, handler):
5252
response.headers['Server-Timing'] = "intid;desc=%s" % scope.span.context.trace_id
5353

5454
return response
55-
except Exception:
55+
except Exception as e:
5656
logger.debug("aiohttp stan_middleware", exc_info=True)
57+
if scope is not None:
58+
scope.span.set_tag("http.status_code", 500)
59+
scope.span.log_exception(e)
60+
raise
5761
finally:
5862
if scope is not None:
5963
scope.close()
@@ -62,7 +66,7 @@ async def stan_middleware(request, handler):
6266
@wrapt.patch_function_wrapper('aiohttp.web','Application.__init__')
6367
def init_with_instana(wrapped, instance, argv, kwargs):
6468
if "middlewares" in kwargs:
65-
kwargs["middlewares"].append(stan_middleware)
69+
kwargs["middlewares"].insert(0, stan_middleware)
6670
else:
6771
kwargs["middlewares"] = [stan_middleware]
6872

tests/apps/app_aiohttp.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/usr/bin/env python
1+
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33
import asyncio
44
from aiohttp import web
@@ -22,6 +22,10 @@ def five_hundred(request):
2222
return web.HTTPInternalServerError(reason="I must simulate errors.", text="Simulated server error.")
2323

2424

25+
def raise_exception(request):
26+
raise Exception("Simulated exception")
27+
28+
2529
def run_server():
2630
loop = asyncio.new_event_loop()
2731
asyncio.set_event_loop(loop)
@@ -30,6 +34,7 @@ def run_server():
3034
app.add_routes([web.get('/', say_hello)])
3135
app.add_routes([web.get('/401', four_hundred_one)])
3236
app.add_routes([web.get('/500', five_hundred)])
37+
app.add_routes([web.get('/exception', raise_exception)])
3338

3439
runner = web.AppRunner(app)
3540
loop.run_until_complete(runner.setup())

tests/test_aiohttp.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,6 @@ async def test():
510510
assert("Server-Timing" in response.headers)
511511
self.assertEqual(response.headers["Server-Timing"], "intid;desc=%s" % traceId)
512512

513-
514513
def test_server_custom_header_capture(self):
515514
async def test():
516515
with async_tracer.start_active_span('test'):
@@ -703,3 +702,54 @@ async def test():
703702
assert("Server-Timing" in response.headers)
704703
self.assertEqual(response.headers["Server-Timing"], "intid;desc=%s" % traceId)
705704

705+
706+
def test_server_get_exception(self):
707+
async def test():
708+
with async_tracer.start_active_span('test'):
709+
async with aiohttp.ClientSession() as session:
710+
return await self.fetch(session, testenv["aiohttp_server"] + "/exception")
711+
712+
response = self.loop.run_until_complete(test())
713+
714+
spans = self.recorder.queued_spans()
715+
self.assertEqual(3, len(spans))
716+
717+
aioserver_span = spans[0]
718+
aioclient_span = spans[1]
719+
test_span = spans[2]
720+
721+
self.assertIsNone(async_tracer.active_span)
722+
723+
# Same traceId
724+
traceId = test_span.t
725+
self.assertEqual(traceId, aioclient_span.t)
726+
self.assertEqual(traceId, aioserver_span.t)
727+
728+
# Parent relationships
729+
self.assertEqual(aioclient_span.p, test_span.s)
730+
self.assertEqual(aioserver_span.p, aioclient_span.s)
731+
732+
# Error logging
733+
self.assertFalse(test_span.error)
734+
self.assertIsNone(test_span.ec)
735+
self.assertTrue(aioclient_span.error)
736+
self.assertEqual(aioclient_span.ec, 1)
737+
self.assertTrue(aioserver_span.error)
738+
self.assertEqual(aioserver_span.ec, 1)
739+
740+
self.assertEqual("aiohttp-server", aioserver_span.n)
741+
self.assertEqual(500, aioserver_span.data.http.status)
742+
self.assertEqual(testenv["aiohttp_server"] + "/exception", aioserver_span.data.http.url)
743+
self.assertEqual("GET", aioserver_span.data.http.method)
744+
self.assertIsNotNone(aioserver_span.stack)
745+
self.assertTrue(type(aioserver_span.stack) is list)
746+
self.assertTrue(len(aioserver_span.stack) > 1)
747+
748+
self.assertEqual("aiohttp-client", aioclient_span.n)
749+
self.assertEqual(500, aioclient_span.data.http.status)
750+
self.assertEqual(testenv["aiohttp_server"] + "/exception", aioclient_span.data.http.url)
751+
self.assertEqual("GET", aioclient_span.data.http.method)
752+
self.assertEqual('Internal Server Error', aioclient_span.data.http.error)
753+
self.assertIsNotNone(aioclient_span.stack)
754+
self.assertTrue(type(aioclient_span.stack) is list)
755+
self.assertTrue(len(aioclient_span.stack) > 1)

0 commit comments

Comments
 (0)