From b6b17739a7a9f0ff54ad1f2b1b03278bfd43db35 Mon Sep 17 00:00:00 2001 From: Dimitra Paraskevopoulou Date: Mon, 4 Oct 2021 10:44:18 +0200 Subject: [PATCH] Sanic exception bug fix (#338) * fixing bug causing out of index * added one additional test case --- instana/instrumentation/sanic_inst.py | 22 ++++--- instana/version.py | 2 +- tests/apps/sanic_app/server.py | 10 ++- tests/frameworks/test_sanic.py | 87 ++++++++++++++++++++++++++- 4 files changed, 109 insertions(+), 12 deletions(-) diff --git a/instana/instrumentation/sanic_inst.py b/instana/instrumentation/sanic_inst.py index bac2ce945..c51b2727a 100644 --- a/instana/instrumentation/sanic_inst.py +++ b/instana/instrumentation/sanic_inst.py @@ -17,17 +17,21 @@ @wrapt.patch_function_wrapper('sanic.exceptions', 'SanicException.__init__') def exception_with_instana(wrapped, instance, args, kwargs): - message = kwargs.get("message", args[0]) - status_code = kwargs.get("status_code") - span = async_tracer.active_span + try: + message = kwargs.get("message") or args[0] + status_code = kwargs.get("status_code") + span = async_tracer.active_span - if all([span, status_code, message]) and (500 <= status_code <= 599): - span.set_tag("http.error", message) - try: + if all([span, status_code, message]) and (500 <= status_code <= 599): + span.set_tag("http.error", message) + try: + wrapped(*args, **kwargs) + except Exception as exc: + span.log_exception(exc) + else: wrapped(*args, **kwargs) - except Exception as exc: - span.log_exception(exc) - else: + except Exception: + logger.debug("exception_with_instana: ", exc_info=True) wrapped(*args, **kwargs) diff --git a/instana/version.py b/instana/version.py index 2cd3e5641..2026450fa 100644 --- a/instana/version.py +++ b/instana/version.py @@ -3,4 +3,4 @@ # Module version file. Used by setup.py and snapshot reporting. -VERSION = '1.35.3' +VERSION = '1.35.4' diff --git a/tests/apps/sanic_app/server.py b/tests/apps/sanic_app/server.py index 2cf712fcf..47b4d747d 100644 --- a/tests/apps/sanic_app/server.py +++ b/tests/apps/sanic_app/server.py @@ -1,12 +1,13 @@ # (c) Copyright IBM Corp. 2021 # (c) Copyright Instana Inc. 2021 +import instana + from sanic import Sanic from sanic.exceptions import SanicException from tests.apps.sanic_app.simpleview import SimpleView from tests.apps.sanic_app.name import NameView from sanic.response import text -import instana app = Sanic('test') @@ -19,6 +20,13 @@ async def uuid_handler(request, foo_id: int): async def test_request_args(request): raise SanicException("Something went wrong.", status_code=500) +@app.route("/instana_exception") +async def test_request_args(request): + raise SanicException(description="Something went wrong.", status_code=500) + +@app.route("/wrong") +async def test_request_args(request): + raise SanicException(message="Something went wrong.", status_code=400) @app.get("/tag/") async def tag_handler(request, tag): diff --git a/tests/frameworks/test_sanic.py b/tests/frameworks/test_sanic.py index 00f5c85ac..884d12805 100644 --- a/tests/frameworks/test_sanic.py +++ b/tests/frameworks/test_sanic.py @@ -127,6 +127,92 @@ def test_404(self): assert (asgi_span.data['http']['error'] is None) assert (asgi_span.data['http']['params'] is None) + def test_sanic_exception(self): + result = None + with tracer.start_active_span('test'): + result = requests.get(testenv["sanic_server"] + '/wrong') + + self.assertEqual(result.status_code, 400) + + spans = tracer.recorder.queued_spans() + self.assertEqual(len(spans), 3) + + span_filter = lambda span: span.n == "sdk" and span.data['sdk']['name'] == 'test' + test_span = get_first_span_by_filter(spans, span_filter) + self.assertIsNotNone(test_span) + + span_filter = lambda span: span.n == "urllib3" + urllib3_span = get_first_span_by_filter(spans, span_filter) + self.assertIsNotNone(urllib3_span) + + span_filter = lambda span: span.n == 'asgi' + asgi_span = get_first_span_by_filter(spans, span_filter) + self.assertIsNotNone(asgi_span) + + self.assertTraceContextPropagated(test_span, urllib3_span) + self.assertTraceContextPropagated(urllib3_span, asgi_span) + + self.assertIn("X-INSTANA-T", result.headers) + self.assertEqual(result.headers["X-INSTANA-T"], asgi_span.t) + self.assertIn("X-INSTANA-S", result.headers) + self.assertEqual(result.headers["X-INSTANA-S"], asgi_span.s) + self.assertIn("X-INSTANA-L", result.headers) + self.assertEqual(result.headers["X-INSTANA-L"], '1') + self.assertIn("Server-Timing", result.headers) + self.assertEqual(result.headers["Server-Timing"], ("intid;desc=%s" % asgi_span.t)) + + self.assertIsNone(asgi_span.ec) + assert (asgi_span.data['http']['host'] == '127.0.0.1:1337') + assert (asgi_span.data['http']['path'] == '/wrong') + assert (asgi_span.data['http']['path_tpl'] == '/wrong') + assert (asgi_span.data['http']['method'] == 'GET') + assert (asgi_span.data['http']['status'] == 400) + assert (asgi_span.data['http']['error'] is None) + assert (asgi_span.data['http']['params'] is None) + + def test_500_instana_exception(self): + result = None + with tracer.start_active_span('test'): + result = requests.get(testenv["sanic_server"] + '/instana_exception') + + self.assertEqual(result.status_code, 500) + + spans = tracer.recorder.queued_spans() + self.assertEqual(len(spans), 4) + + span_filter = lambda span: span.n == "sdk" and span.data['sdk']['name'] == 'test' + test_span = get_first_span_by_filter(spans, span_filter) + self.assertIsNotNone(test_span) + + span_filter = lambda span: span.n == "urllib3" + urllib3_span = get_first_span_by_filter(spans, span_filter) + self.assertIsNotNone(urllib3_span) + + span_filter = lambda span: span.n == 'asgi' + asgi_span = get_first_span_by_filter(spans, span_filter) + self.assertIsNotNone(asgi_span) + + self.assertTraceContextPropagated(test_span, urllib3_span) + self.assertTraceContextPropagated(urllib3_span, asgi_span) + + self.assertIn("X-INSTANA-T", result.headers) + self.assertEqual(result.headers["X-INSTANA-T"], asgi_span.t) + self.assertIn("X-INSTANA-S", result.headers) + self.assertEqual(result.headers["X-INSTANA-S"], asgi_span.s) + self.assertIn("X-INSTANA-L", result.headers) + self.assertEqual(result.headers["X-INSTANA-L"], '1') + self.assertIn("Server-Timing", result.headers) + self.assertEqual(result.headers["Server-Timing"], ("intid;desc=%s" % asgi_span.t)) + + self.assertEqual(asgi_span.ec, 1) + assert (asgi_span.data['http']['host'] == '127.0.0.1:1337') + assert (asgi_span.data['http']['path'] == '/instana_exception') + assert (asgi_span.data['http']['path_tpl'] == '/instana_exception') + assert (asgi_span.data['http']['method'] == 'GET') + assert (asgi_span.data['http']['status'] == 500) + assert (asgi_span.data['http']['error'] is None) + assert (asgi_span.data['http']['params'] is None) + def test_500(self): result = None with tracer.start_active_span('test'): @@ -213,7 +299,6 @@ def test_path_templates(self): assert (asgi_span.data['http']['error'] is None) assert (asgi_span.data['http']['params'] is None) - def test_secret_scrubbing(self): result = None with tracer.start_active_span('test'):