Skip to content

Commit 98f8825

Browse files
authored
fix(trace): Error with overlapping span ids (#94565)
- Because this was a dict with single errors the trace would lose errors if there were multiple errors for a given span id
1 parent df699cc commit 98f8825

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

src/sentry/api/endpoints/organization_trace.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,9 @@ def query_trace_data(self, snuba_params: SnubaParams, trace_id: str) -> list[Ser
286286

287287
result = []
288288
id_to_span = {event["id"]: event for event in spans_data}
289-
id_to_error = {event["trace.span"]: event for event in errors_data}
289+
id_to_error: dict[str, Any] = {}
290+
for event in errors_data:
291+
id_to_error.setdefault(event["trace.span"], []).append(event)
290292
id_to_occurrence = defaultdict(list)
291293
with sentry_sdk.start_span(op="process.occurrence_data") as sdk_span:
292294
for event in occurrence_data:
@@ -302,8 +304,8 @@ def query_trace_data(self, snuba_params: SnubaParams, trace_id: str) -> list[Ser
302304
else:
303305
result.append(span)
304306
if span["id"] in id_to_error:
305-
error = id_to_error.pop(span["id"])
306-
span["errors"].append(error)
307+
errors = id_to_error.pop(span["id"])
308+
span["errors"].extend(errors)
307309
if span["id"] in id_to_occurrence:
308310
span["occurrences"].extend(
309311
[
@@ -315,8 +317,8 @@ def query_trace_data(self, snuba_params: SnubaParams, trace_id: str) -> list[Ser
315317
for occurrence in id_to_occurrence[span["id"]]
316318
]
317319
)
318-
for error in id_to_error.values():
319-
result.append(error)
320+
for errors in id_to_error.values():
321+
result.extend(errors)
320322
return [self.serialize_rpc_event(root) for root in result]
321323

322324
def has_feature(self, organization: Organization, request: Request) -> bool:

tests/snuba/api/endpoints/test_organization_trace.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,37 @@ def test_with_errors_data(self):
159159
assert error_event["issue_id"] == error.group_id
160160
assert error_event["start_timestamp"] == error_data["timestamp"]
161161

162+
def test_with_errors_data_with_overlapping_span_id(self):
163+
self.load_trace(is_eap=True)
164+
_, start = self.get_start_end_from_day_ago(123)
165+
error_data = load_data(
166+
"javascript",
167+
timestamp=start,
168+
)
169+
error_data["contexts"]["trace"] = {
170+
"type": "trace",
171+
"trace_id": self.trace_id,
172+
"span_id": self.root_event.data["contexts"]["trace"]["span_id"],
173+
}
174+
error_data["tags"] = [["transaction", "/transaction/gen1-0"]]
175+
error = self.store_event(error_data, project_id=self.gen1_project.id)
176+
error_2 = self.store_event(error_data, project_id=self.gen1_project.id)
177+
178+
with self.feature(self.FEATURES):
179+
response = self.client_get(
180+
data={"timestamp": self.day_ago},
181+
)
182+
assert response.status_code == 200, response.content
183+
data = response.data
184+
assert len(data) == 1
185+
self.assert_trace_data(data[0])
186+
assert len(data[0]["errors"]) == 2
187+
error_event_1 = data[0]["errors"][0]
188+
error_event_2 = data[0]["errors"][1]
189+
assert error_event_1["event_id"] in [error.event_id, error_2.event_id]
190+
assert error_event_2["event_id"] in [error.event_id, error_2.event_id]
191+
assert error_event_1["event_id"] != error_event_2["event_id"]
192+
162193
def test_with_performance_issues(self):
163194
self.load_trace(is_eap=True)
164195
with self.feature(self.FEATURES):

0 commit comments

Comments
 (0)