feat(spans): Equalize name and description for manual spans#6070
feat(spans): Equalize name and description for manual spans#6070loewenheim wants to merge 7 commits into
Conversation
| == Some("manual") | ||
| { | ||
| return name.value().cloned(); | ||
| } |
There was a problem hiding this comment.
Manual origin skips query backfill
Medium Severity
derive_description_for_v2_span returns the span name whenever sentry.origin is "manual" before considering db.query.text or HTTP attributes. Child spans that inherit a manual trace origin but lack their own origin can keep a convention-derived name, so description backfill copies that label instead of the DB query or HTTP URL that used to be written via write_legacy_attributes.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 61a998e. Configure here.
There was a problem hiding this comment.
I legitimately don't understand what this is trying to say.
There was a problem hiding this comment.
I think it is trying to say "A child span might have name derived based on convention rules. Do we really want to use this derived name, instead of looking at DB__QUERY__TEXT etc., when the child span wasn't really manually instrumented (it just inherited manual)?"
| continue; | ||
| }; | ||
|
|
||
| attributes.insert(legacy_attribute, attr.value.clone()); |
There was a problem hiding this comment.
Legacy action prefers DB over HTTP
Low Severity
In write_legacy_attributes, skipping when a legacy key already exists means sentry.action is filled from the first mapped conventional attribute and later mappings are ignored. When both db.operation.name and http.request.method are present, sentry.action stays on the DB value instead of being overwritten by the HTTP method as before.
Reviewed by Cursor Bugbot for commit 03de602. Configure here.
There was a problem hiding this comment.
The behavior for spans which have both db and http attributes (which should not happen in practice) was already arbitrary before, now it's arbitrary in the other direction.
| .is_some_and(|attrs| attrs.contains_key(SENTRY__DESCRIPTION)) | ||
| { | ||
| return; | ||
| } |
There was a problem hiding this comment.
Empty description blocks manual backfill
Medium Severity
normalize_sentry_description returns immediately when sentry.description is present, without treating an empty value as missing. For manual-origin spans with a non-empty name but an empty sentry.description attribute, description is never copied from name, so name and description can stay out of sync after processing.
Reviewed by Cursor Bugbot for commit 03de602. Configure here.
There was a problem hiding this comment.
It's intended that if someone manually sets a description it doesn't get clobbered by the name. This includes the case of an empty description.
|
|
||
| if new_span.origin.value().is_none() { | ||
| new_span.origin = origin.clone(); | ||
| } |
There was a problem hiding this comment.
Trace origin applied to child spans
Medium Severity
When extracting transaction child spans, missing span origin is filled from the trace context before V1→V2 conversion. If the trace origin is manual, children without their own origin inherit it and later use manual name/description rules instead of convention-based naming.
Reviewed by Cursor Bugbot for commit 03de602. Configure here.
| if new_span.origin.value().is_none() { | ||
| new_span.origin = origin.clone(); | ||
| } | ||
|
|
There was a problem hiding this comment.
Transaction spans skip description backfill
Medium Severity
normalize_sentry_description runs only in the standalone span pipeline after PII scrubbing. Transaction-extracted spans are converted with span_v1_to_span_v2 and never get that step, so manual spans (including children that inherit trace manual origin) can keep a convention-inferred name while sentry.description stays unset.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 18d7a6f. Configure here.
There was a problem hiding this comment.
Backfilling the description from the name is not a concern for transaction-extracted spans, they need to worry about the converse.
| eap::normalize_sentry_description(&mut span.attributes, &span.name); | ||
| } | ||
| }); | ||
| } |
There was a problem hiding this comment.
Manual spans desync after scrub
Medium Severity
For manual-origin spans, backfill_description skips when sentry.description already exists, but PII scrubbing runs immediately before it and can change that attribute. Top-level span.name is not updated to match, so name and description can diverge after the step meant to equalize them.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit e7c7306. Configure here.
| Some(name_for_op_and_attributes(op, &AttributeGetter(attributes))) | ||
| } | ||
|
|
||
| fn name_for_origin_and_description( |
There was a problem hiding this comment.
| fn name_for_origin_and_description( | |
| fn name_from_origin_and_description( |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 7 total unresolved issues (including 6 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7dbff4a. Configure here.
| == Some("manual") | ||
| { | ||
| return name.value().cloned(); | ||
| } |
There was a problem hiding this comment.
Manual backfill skips PII scrub
Medium Severity
For "manual" origin, backfill_description runs after PII scrub and sets sentry.description from the top-level span.name. That value is not taken from already-scrubbed attributes, and the new attribute is never run through scrub again—unlike DB/HTTP backfill paths that read scrubbed attribute data.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 7dbff4a. Configure here.
| }; | ||
|
|
||
| process::scrub(&mut spans, ctx); | ||
| process::backfill_description(&mut spans); |
There was a problem hiding this comment.
Maybe process::normalize_derived or something similar?
| .value() | ||
| .is_some_and(|attrs| attrs.contains_key(SENTRY__DESCRIPTION)) |
There was a problem hiding this comment.
This might need a check which doesn't just use value() but also considers meta, Empty trait might be able to do that for you.
| if attributes | ||
| .get_value(SENTRY__ORIGIN) | ||
| .and_then(|o| o.as_str()) | ||
| == Some("manual") |


This ensures that for spans (V1 or V2) with an origin of
"manual", name and description coincide. For V1 spans, this means copying the description to the name, and the reverse for V2 spans. Other spans behave as before.sentry-conventions.backfill_descriptionthat runs right after PII scrubbing. Unfortunately it can't simply be integrated intonormalize_spanbecause it's not safe to backfill the description before PII scrubbing—the description could end up containing a URL with PII, for example. Also, in the course of this, we move the (limited) functionality that existed for backfilling the description based on attributes out ofwrite_legacy_attributes(where it was somewhat misplaced anyway) and centralize it innormalize_sentry_description.Future work:
sentry-conventionsCloses INGEST-955.