From d4560b4f31a6bafcef0948f42cae7a6dda2383e7 Mon Sep 17 00:00:00 2001 From: brettlangdon Date: Mon, 9 Aug 2021 16:43:00 -0400 Subject: [PATCH 1/3] Fix issue with tagging non-string Flask view args fixes #2756 --- ddtrace/contrib/flask/patch.py | 4 +- ...non-string-view-args-ed0283ddb1541e27.yaml | 4 ++ tests/contrib/flask/test_request.py | 44 +++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/fix-flask-non-string-view-args-ed0283ddb1541e27.yaml diff --git a/ddtrace/contrib/flask/patch.py b/ddtrace/contrib/flask/patch.py index 2f7725fcba3..a510a8567b9 100644 --- a/ddtrace/contrib/flask/patch.py +++ b/ddtrace/contrib/flask/patch.py @@ -481,7 +481,9 @@ def _traced_request(pin, wrapped, instance, args, kwargs): if not span.get_tag(FLASK_VIEW_ARGS) and request.view_args and config.flask.get("collect_view_args"): for k, v in request.view_args.items(): - span._set_str_tag(u".".join((FLASK_VIEW_ARGS, k)), v) + # DEV: Do not use `_set_str_tag` here since view args can be string/int/float/path/uuid/etc + # https://flask.palletsprojects.com/en/1.1.x/api/#url-route-registrations + span.set_tag(u".".join((FLASK_VIEW_ARGS, k)), v) except Exception: log.debug('failed to set tags for "flask.request" span', exc_info=True) diff --git a/releasenotes/notes/fix-flask-non-string-view-args-ed0283ddb1541e27.yaml b/releasenotes/notes/fix-flask-non-string-view-args-ed0283ddb1541e27.yaml new file mode 100644 index 00000000000..9c8dd804c0a --- /dev/null +++ b/releasenotes/notes/fix-flask-non-string-view-args-ed0283ddb1541e27.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - | + Fixes error with tagging non-string Flask view args. diff --git a/tests/contrib/flask/test_request.py b/tests/contrib/flask/test_request.py index 58fc8467ef4..2811e556dc6 100644 --- a/tests/contrib/flask/test_request.py +++ b/tests/contrib/flask/test_request.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- +import json + import flask from flask import abort +from flask import jsonify from flask import make_response from ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY @@ -82,6 +85,47 @@ def index(): self.assertEqual(handler_span.resource, "/") self.assertEqual(req_span.error, 0) + def test_request(self): + """ + When making a request to an endpoint with non-string url params + We create the expected spans + """ + + @self.app.route("/route_params////") + def route_params(first, second, third, fourth): + return jsonify( + { + "first": first, + "second": second, + "third": third, + "fourth": fourth, + } + ) + + res = self.client.get("/route_params/test/100/5.5/some/sub/path") + self.assertEqual(res.status_code, 200) + data = json.loads(res.data) + + assert data == { + "first": "test", + "second": 100, + "third": 5.5, + "fourth": "some/sub/path", + } + + spans = self.get_spans() + self.assertEqual(len(spans), 8) + + root = spans[0] + assert root.name == "flask.request" + assert root.get_tag(http.URL) == "http://localhost/route_params/test/100/5.5/some/sub/path" + assert root.get_tag("flask.endpoint") == "route_params" + assert root.get_tag("flask.url_rule") == "/route_params////" + assert root.get_tag("flask.view_args.first") == "test" + assert root.get_metric("flask.view_args.second") == 100.0 + assert root.get_metric("flask.view_args.third") == 5.5 + assert root.get_tag("flask.view_args.fourth") == "some/sub/path" + def test_request_query_string_trace(self): """Make sure when making a request that we create the expected spans and capture the query string.""" From c7ab560e988e2459d754c9cd04debbd63c015655 Mon Sep 17 00:00:00 2001 From: brettlangdon Date: Mon, 9 Aug 2021 16:46:59 -0400 Subject: [PATCH 2/3] fix test method name --- tests/contrib/flask/test_request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/contrib/flask/test_request.py b/tests/contrib/flask/test_request.py index 2811e556dc6..885e517c45e 100644 --- a/tests/contrib/flask/test_request.py +++ b/tests/contrib/flask/test_request.py @@ -85,7 +85,7 @@ def index(): self.assertEqual(handler_span.resource, "/") self.assertEqual(req_span.error, 0) - def test_request(self): + def test_route_params_request(self): """ When making a request to an endpoint with non-string url params We create the expected spans From 5b7fad8ab8d2415c95b82c5cfdaf063d44509ff0 Mon Sep 17 00:00:00 2001 From: brettlangdon Date: Mon, 9 Aug 2021 17:15:32 -0400 Subject: [PATCH 3/3] fix json decoding when we have bytes --- tests/contrib/flask/test_request.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/contrib/flask/test_request.py b/tests/contrib/flask/test_request.py index 885e517c45e..1a628de0226 100644 --- a/tests/contrib/flask/test_request.py +++ b/tests/contrib/flask/test_request.py @@ -104,7 +104,10 @@ def route_params(first, second, third, fourth): res = self.client.get("/route_params/test/100/5.5/some/sub/path") self.assertEqual(res.status_code, 200) - data = json.loads(res.data) + if isinstance(res.data, bytes): + data = json.loads(res.data.decode()) + else: + data = json.loads(res.data) assert data == { "first": "test",