feat(asm): add normalized HTTP route span tag for Tornado#18398
Conversation
|
8928751 to
b86f35d
Compare
BenchmarksBenchmark execution time: 2026-06-04 12:20:39 Comparing candidate commit 6ab0ab1 in PR branch Found 0 performance improvements and 1 performance regressions! Performance is the same for 83 metrics, 0 unstable metrics. scenario:iastaspectsospath-ospathbasename_aspect
|
Codeowners resolved as |
8c999a6 to
cef37b4
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cef37b41c8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
6ae8f9d to
37459ab
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 37459ab39e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
37459ab to
3b721b8
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3b721b8c0c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
emmettbutler
left a comment
There was a problem hiding this comment.
release note approved
Implements RFC-1103 ``_dd.appsec.normalized_route`` for Tornado, following the FastAPI/Starlette and Django implementations already in main. - ``normalize_route_tornado`` in ``_api_security/_normalized_route.py``: handles Tornado's ``%s``-placeholder ``http.route`` strings (produced by ``_regex_to_route``), named-group dict and positional-group list ``path_params``, multi-param segment combining (rule 5 ``+``), and optional-trailing-slash stripping (``/?`` is not "declared with trailing slash" per RFC rule 1). - ``_handlers.py``: registers ``"tornado"`` in ``_NORMALIZED_ROUTE_BY_INTEGRATION``. - ``tornado_app/app.py``: switches ``/asm/`` route to named groups so ``path_params`` arrives as a dict with proper names; adds ``MultiParamHandler`` (``/multi-param/``) and ``FilesHandler`` (``/files/``) for normalized-route integration tests. - ``test_tornado.py``: overrides ``test_normalized_route`` and ``test_normalized_route_disabled_when_api_security_off`` with Tornado-specific expected values; expands ``ENDPOINT_DISCOVERY_EXPECTED_PATHS``. - ``test_normalized_route.py``: adds 27 unit test cases covering all code paths of ``normalize_route_tornado``. - ``utils.py``: documents the reason Tornado is skipped in ``test_normalized_route_survives_request_span_name_override``. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
3b721b8 to
4c95976
Compare
…529c9.yaml Co-authored-by: Emmett Butler <[email protected]>
408222d to
302da8c
Compare
302da8c to
6ab0ab1
Compare
APPSEC-65478
Description
Extends RFC-1103
_dd.appsec.normalized_routeto Tornado, following the FastAPI/Starlette (#17920), Django (#18209), and Flask (#18343) implementations.Tornado's ddtrace integration produces
http.routestrings with%sas a placeholder for every capturing group (via_regex_to_route). The new normalizer maps those placeholders to parameter names sourced frompath_params: a dict for named groups ((?P<name>...)), a list for positional groups, or{}for static routes. Optional trailing-slash patterns (/?) are treated as not declaring a trailing slash per RFC-1103 rule 1, consistent with the Django^asm/?$→/asmconvention.Changes:
_normalized_route.py— adds_normalize_route_tornado_cached(LRU-cached, keyed on route + param-names tuple) andnormalize_route_tornado(public entry point). Handles%splaceholder mapping,/?stripping, multi-param-in-segment combining with+(rule 5), and static-segment URL-encoding (rule 3)._handlers.py— registers"tornado": normalize_route_tornadoin_NORMALIZED_ROUTE_BY_INTEGRATION.tornado_app/app.py— converts the/asm/route from positional to named capturing groups sopath_paramsarrives as a dict with proper parameter names; addsMultiParamHandler(/multi-param/) andFilesHandler(/files/) for integration test coverage.test_tornado.py— overridestest_normalized_routeandtest_normalized_route_disabled_when_api_security_offwith Tornado-specific expected values (no trailing slash for/?routes); expandsENDPOINT_DISCOVERY_EXPECTED_PATHS.test_normalized_route.py— 27 new unit tests fornormalize_route_tornadocovering all code paths.utils.py— documents why Tornado is skipped intest_normalized_route_survives_request_span_name_override(span name is hard-coded viaschematize_url_operation).Testing
tests/appsec/appsec/api_security/test_normalized_route.pycovering named groups, positional groups, multi-param combining (+),/?stripping, explicit trailing-slash preservation, URL-encoding, mismatch detection, andlru_cacheidentity.test_tornado.pyexercise the full request path: named-group params (/asm/{param_int}/{param_str}), multi-param-in-segment (/multi-param/{first+last}), catch-all (/files/{file_path}), root (/), ASM-disabled gate, and API-Security-disabled gate.test_normalized_route_disabled_when_api_security_offverifies the tag is absent when API Security is off while ASM is on.Risks
None — all production code is confined to
ddtrace/appsec/. No changes to integration code or public API. The/asm/route change (positional → named groups) is backward-compatible: Tornado passes named groups as keyword arguments that match the existing handler signature.Additional Notes
Tornado routes using positional groups (no
(?P<name>...)) produce auto-numbered placeholders ({param1},{param2}, …). Users who want named parameters in_dd.appsec.normalized_routeshould use named capturing groups in their route patterns.