From 73c1193bfb93fab44d1683f0ae6a30229c56b22e Mon Sep 17 00:00:00 2001 From: Joris Bayer Date: Fri, 14 Nov 2025 09:05:33 +0100 Subject: [PATCH 1/5] fix(spans): Shim more fields for issue detectors --- src/sentry/spans/consumers/process_segments/shim.py | 9 ++++++++- src/sentry/spans/consumers/process_segments/types.py | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/sentry/spans/consumers/process_segments/shim.py b/src/sentry/spans/consumers/process_segments/shim.py index 42b76d3b5dffc2..f024efdb17b761 100644 --- a/src/sentry/spans/consumers/process_segments/shim.py +++ b/src/sentry/spans/consumers/process_segments/shim.py @@ -99,8 +99,15 @@ def build_shim_event_data( # topological sorting on the span tree. for span in spans: event_span = cast(dict[str, Any], deepcopy(span)) - event_span["start_timestamp"] = span["start_timestamp"] event_span["timestamp"] = span["end_timestamp"] + event_span["data"] = { + key: value + for (key, attribute) in (span.get("attributes") or {}).items() + if (value := (attribute or {}).get("value")) is not None + } + if description := attribute_value(span, "sentry.description"): + event_span["description"] = description + event["spans"].append(event_span) return event diff --git a/src/sentry/spans/consumers/process_segments/types.py b/src/sentry/spans/consumers/process_segments/types.py index 4e277fe64a6929..117125dd3b4fe7 100644 --- a/src/sentry/spans/consumers/process_segments/types.py +++ b/src/sentry/spans/consumers/process_segments/types.py @@ -28,9 +28,12 @@ class CompatibleSpan(SpanEvent, total=True): This type will be removed eventually.""" + data: dict[str, Any] + description: str exclusive_time: float op: str sentry_tags: dict[str, str] + timestamp: float # Added by `SpanGroupingResults.write_to_spans` in `_enrich_spans` hash: NotRequired[str] From ca6a0bd68daa19bc1ab33cf6c785043a06eeea49 Mon Sep 17 00:00:00 2001 From: Joris Bayer Date: Fri, 14 Nov 2025 09:07:43 +0100 Subject: [PATCH 2/5] remove typing again --- src/sentry/spans/consumers/process_segments/types.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/sentry/spans/consumers/process_segments/types.py b/src/sentry/spans/consumers/process_segments/types.py index 117125dd3b4fe7..4e277fe64a6929 100644 --- a/src/sentry/spans/consumers/process_segments/types.py +++ b/src/sentry/spans/consumers/process_segments/types.py @@ -28,12 +28,9 @@ class CompatibleSpan(SpanEvent, total=True): This type will be removed eventually.""" - data: dict[str, Any] - description: str exclusive_time: float op: str sentry_tags: dict[str, str] - timestamp: float # Added by `SpanGroupingResults.write_to_spans` in `_enrich_spans` hash: NotRequired[str] From 1dfc6ffaf97adcb3d854c859510416ea41db2d40 Mon Sep 17 00:00:00 2001 From: Joris Bayer Date: Fri, 14 Nov 2025 11:11:10 +0100 Subject: [PATCH 3/5] fix --- src/sentry/spans/consumers/process_segments/shim.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/sentry/spans/consumers/process_segments/shim.py b/src/sentry/spans/consumers/process_segments/shim.py index f024efdb17b761..28992bbbc5a5b1 100644 --- a/src/sentry/spans/consumers/process_segments/shim.py +++ b/src/sentry/spans/consumers/process_segments/shim.py @@ -100,11 +100,14 @@ def build_shim_event_data( for span in spans: event_span = cast(dict[str, Any], deepcopy(span)) event_span["timestamp"] = span["end_timestamp"] - event_span["data"] = { - key: value - for (key, attribute) in (span.get("attributes") or {}).items() - if (value := (attribute or {}).get("value")) is not None - } + event_span["data"] = {} + for key, value in (span.get("attributes") or {}).items(): + if (value := attribute_value(event_span, key)) is not None: + if key == "sentry.description": + event_span["description"] = value + else: + event_span["data"][key] = value + if description := attribute_value(span, "sentry.description"): event_span["description"] = description From c758a881fdf0334b0ea5cad64f01a08f34c3950f Mon Sep 17 00:00:00 2001 From: Joris Bayer Date: Fri, 14 Nov 2025 12:40:11 +0100 Subject: [PATCH 4/5] Apply suggestion from @jjbayer --- src/sentry/spans/consumers/process_segments/shim.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/sentry/spans/consumers/process_segments/shim.py b/src/sentry/spans/consumers/process_segments/shim.py index 28992bbbc5a5b1..a52cb36cf57e95 100644 --- a/src/sentry/spans/consumers/process_segments/shim.py +++ b/src/sentry/spans/consumers/process_segments/shim.py @@ -108,9 +108,6 @@ def build_shim_event_data( else: event_span["data"][key] = value - if description := attribute_value(span, "sentry.description"): - event_span["description"] = description - event["spans"].append(event_span) return event From 52cf1e0cc83d3fdee308eed48d87adb5c611898f Mon Sep 17 00:00:00 2001 From: Joris Bayer Date: Mon, 17 Nov 2025 08:50:36 +0100 Subject: [PATCH 5/5] Add note --- src/sentry/spans/consumers/process_segments/shim.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sentry/spans/consumers/process_segments/shim.py b/src/sentry/spans/consumers/process_segments/shim.py index a52cb36cf57e95..4961a1025c6a51 100644 --- a/src/sentry/spans/consumers/process_segments/shim.py +++ b/src/sentry/spans/consumers/process_segments/shim.py @@ -97,6 +97,9 @@ def build_shim_event_data( # Add legacy span attributes required only by issue detectors. As opposed to # real event payloads, this also adds the segment span so detectors can run # topological sorting on the span tree. + # + # TODO: Remove this code once `organizations:performance-issues-spans` has graduated + # and performance issue detection runs 100% on spans. for span in spans: event_span = cast(dict[str, Any], deepcopy(span)) event_span["timestamp"] = span["end_timestamp"]