Skip to content

feat(integrations): Add http.route attribute to server spans - #7183

Draft
mjq wants to merge 1 commit into
masterfrom
mjq/http-route-server-spans
Draft

feat(integrations): Add http.route attribute to server spans#7183
mjq wants to merge 1 commit into
masterfrom
mjq/http-route-server-spans

Conversation

@mjq

@mjq mjq commented Aug 12, 2026

Copy link
Copy Markdown
Member

Description

Currently the HTTP path template is only available in the span name. Make it available as a semantic attribute as well (http.route - definition in conventions).

This will also let us use this in e.g. HTTP server span description generation, which will be necessary to maintain consistent descriptions between transactions and span streaming.

Issues

@linear-code

linear-code Bot commented Aug 12, 2026

Copy link
Copy Markdown

PY-2732

Comment thread sentry_sdk/scope.py Outdated
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Codecov Results 📊

118315 passed | ⏭️ 6732 skipped | Total: 125047 | Pass Rate: 94.62% | Execution Time: 413m 24s

📊 Comparison with Base Branch

Metric Change
Total Tests 📈 +20
Passed Tests 📈 +21
Failed Tests 📉 -1
Skipped Tests

➖ Removed Tests (1)

View removed tests
  • test_continuous_profiler_auto_start_and_stop_sampled[non-experiment-gevent]
    • File: tests.profiler.test_continuous_profiler

All tests are passing successfully.

✅ Patch coverage is 98.08%. Project has 2485 uncovered lines.
✅ Project coverage is 90.26%. Comparing base (base) to head (head).

Files with missing lines (1)
File Patch % Lines
sentry_sdk/integrations/asgi.py 80.00% ⚠️ 1 Missing and 1 partials
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    90.24%    90.26%    +0.02%
==========================================
  Files          193       193         —
  Lines        25474     25519       +45
  Branches      9378      9402       +24
==========================================
+ Hits         22988     23034       +46
- Misses        2486      2485        -1
- Partials      1431      1431         —

Generated by Codecov Action

Comment thread sentry_sdk/integrations/asgi.py
@mjq
mjq force-pushed the mjq/http-route-server-spans branch from dddf367 to b1363a5 Compare August 13, 2026 20:16
Comment thread sentry_sdk/integrations/starlette.py
mjq added a commit that referenced this pull request Aug 24, 2026
…#7201)

The sync request/response handler passed the _isolation_ scope to
`_set_transaction_name_and_source`, but the transaction/segment span
lives on the _current_ scope. As a result the route-resolved name never
reached the span for sync endpoints, which were instead named by the raw
URL from the ASGI middleware (`transaction_info.source` of `url` rather
than `route`). Async handlers already used the current scope and were
unaffected.

Pass the current scope (already computed above) so sync and async
handlers behave identically:
- streaming: the segment name / `sentry.segment.name.source` are
route-based
- static: the transaction event name / source are route-based

For parametrized routes this also removes high-cardinality URL
transaction names for sync endpoints.

Found while working on
#7183.
sentrivana pushed a commit that referenced this pull request Aug 25, 2026
…#7201)

The sync request/response handler passed the _isolation_ scope to
`_set_transaction_name_and_source`, but the transaction/segment span
lives on the _current_ scope. As a result the route-resolved name never
reached the span for sync endpoints, which were instead named by the raw
URL from the ASGI middleware (`transaction_info.source` of `url` rather
than `route`). Async handlers already used the current scope and were
unaffected.

Pass the current scope (already computed above) so sync and async
handlers behave identically:
- streaming: the segment name / `sentry.segment.name.source` are
route-based
- static: the transaction event name / source are route-based

For parametrized routes this also removes high-cardinality URL
transaction names for sync endpoints.

Found while working on
#7183.
@mjq
mjq force-pushed the mjq/http-route-server-spans branch from b1363a5 to 1d15a6d Compare August 26, 2026 20:10
@mjq mjq changed the title fix(spans): Add http.route attribute to HTTP server spans feat(integrations): Add http.route attribute to server spans Aug 26, 2026
@mjq

mjq commented Aug 26, 2026

Copy link
Copy Markdown
Member Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1d15a6d. Configure here.

name = _DEFAULT_TRANSACTION_NAME
source = TransactionSource.ROUTE
elif source == TransactionSource.ROUTE:
scope.set_segment_attribute(SPANDATA.HTTP_ROUTE, name)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Host routes set raw request path

Low Severity

For Starlette Host routes, _transaction_name_from_router falls back to the raw request path. That value is then stored as http.route, which is supposed to be a path template. High-cardinality paths can leak into span attributes and descriptions.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1d15a6d. Configure here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was an existing bug. PR up to fix in #7266.

Comment thread sentry_sdk/scope.py
for attribute, value in attributes.items():
self.set_attribute(attribute, value)

def set_segment_attribute(self, key: str, value: "AttributeValue") -> None:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seemed like a useful helper function to have (and avoids duplicating this code in every HTTP integration), but I would also understand if we don't want to expand the API surface with this: it makes the "segment" name a public thing which AIUI we are trying to avoid?

Comment thread sentry_sdk/integrations/starlette.py
name = _DEFAULT_TRANSACTION_NAME
source = TransactionSource.ROUTE
elif source == TransactionSource.ROUTE:
scope.set_segment_attribute(SPANDATA.HTTP_ROUTE, name)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was an existing bug. PR up to fix in #7266.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

http.route missing from HTTP server spans

1 participant