Skip to content

Commit 91d910e

Browse files
mergify[bot]ZStriker19brettlangdon
authored
fix: Flask incorrect resource naming when error thrown in middleware (#3274) (#3284)
Before this change, if an error was thrown in the middleware, we would just get <method> <status_code> as the resource name. With this change, we get <method> <path> which means the error will be grouped with the rest of the endpoint's hits/errors. Co-authored-by: Brett Langdon <[email protected]> Co-authored-by: Kyle Verhoog <[email protected]> (cherry picked from commit 706a1d3) Co-authored-by: Zachary Groves <[email protected]> Co-authored-by: Brett Langdon <[email protected]>
1 parent d11938b commit 91d910e

File tree

3 files changed

+44
-19
lines changed

3 files changed

+44
-19
lines changed

ddtrace/contrib/flask/patch.py

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ def unpatch():
262262
def _wrap_start_response(func, span, request):
263263
def traced_start_response(status_code, headers):
264264
code, _, _ = status_code.partition(" ")
265+
# If values are accessible, set the resource as `<method> <path>` and add other request tags
266+
_set_request_tags(span)
265267

266268
# Override root span resource name to be `<method> 404` for 404 requests
267269
# DEV: We do this because we want to make it easier to see all unknown requests together
@@ -467,25 +469,9 @@ def _traced_request(pin, wrapped, instance, args, kwargs):
467469
if not pin.enabled or not span:
468470
return wrapped(*args, **kwargs)
469471

470-
try:
471-
request = flask._request_ctx_stack.top.request
472-
473-
# DEV: This name will include the blueprint name as well (e.g. `bp.index`)
474-
if not span.get_tag(FLASK_ENDPOINT) and request.endpoint:
475-
span.resource = u" ".join((request.method, request.endpoint))
476-
span._set_str_tag(FLASK_ENDPOINT, request.endpoint)
477-
478-
if not span.get_tag(FLASK_URL_RULE) and request.url_rule and request.url_rule.rule:
479-
span.resource = u" ".join((request.method, request.url_rule.rule))
480-
span._set_str_tag(FLASK_URL_RULE, request.url_rule.rule)
481-
482-
if not span.get_tag(FLASK_VIEW_ARGS) and request.view_args and config.flask.get("collect_view_args"):
483-
for k, v in request.view_args.items():
484-
# DEV: Do not use `_set_str_tag` here since view args can be string/int/float/path/uuid/etc
485-
# https://flask.palletsprojects.com/en/1.1.x/api/#url-route-registrations
486-
span.set_tag(u".".join((FLASK_VIEW_ARGS, k)), v)
487-
except Exception:
488-
log.debug('failed to set tags for "flask.request" span', exc_info=True)
472+
# This call may be unnecessary since we try to add the tags earlier
473+
# We just haven't been able to confirm this yet
474+
_set_request_tags(span)
489475

490476
with pin.tracer.trace(
491477
".".join(("flask", name)), service=trace_utils.int_service(pin, config.flask, pin)
@@ -518,3 +504,25 @@ def traced_jsonify(wrapped, instance, args, kwargs):
518504

519505
with pin.tracer.trace("flask.jsonify"):
520506
return wrapped(*args, **kwargs)
507+
508+
509+
def _set_request_tags(span):
510+
try:
511+
request = flask._request_ctx_stack.top.request
512+
513+
# DEV: This name will include the blueprint name as well (e.g. `bp.index`)
514+
if not span.get_tag(FLASK_ENDPOINT) and request.endpoint:
515+
span.resource = u" ".join((request.method, request.endpoint))
516+
span._set_str_tag(FLASK_ENDPOINT, request.endpoint)
517+
518+
if not span.get_tag(FLASK_URL_RULE) and request.url_rule and request.url_rule.rule:
519+
span.resource = u" ".join((request.method, request.url_rule.rule))
520+
span._set_str_tag(FLASK_URL_RULE, request.url_rule.rule)
521+
522+
if not span.get_tag(FLASK_VIEW_ARGS) and request.view_args and config.flask.get("collect_view_args"):
523+
for k, v in request.view_args.items():
524+
# DEV: Do not use `_set_str_tag` here since view args can be string/int/float/path/uuid/etc
525+
# https://flask.palletsprojects.com/en/1.1.x/api/#url-route-registrations
526+
span.set_tag(u".".join((FLASK_VIEW_ARGS, k)), v)
527+
except Exception:
528+
log.debug('failed to set tags for "flask.request" span', exc_info=True)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
fixes:
3+
- |
4+
flask: fix resource naming of request span when errors occur in middleware.

tests/contrib/flask/test_request.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,19 @@ def test_http_request_header_tracing(self):
887887
assert span.get_tag("http.request.headers.my-header") == "my_value"
888888
assert span.get_tag("http.request.headers.host") == "localhost"
889889

890+
def test_correct_resource_when_middleware_error(self):
891+
@self.app.route("/helloworld")
892+
@self.app.before_first_request
893+
def error():
894+
raise Exception()
895+
896+
self.client.get("/helloworld")
897+
898+
spans = self.get_spans()
899+
req_span = spans[0]
900+
assert req_span.resource == "GET /helloworld"
901+
assert req_span.get_tag("http.status_code") == "500"
902+
890903
def test_http_response_header_tracing(self):
891904
@self.app.route("/response_headers")
892905
def response_headers():

0 commit comments

Comments
 (0)