@@ -179,14 +179,15 @@ def _get_trace_tree_for_event(event: Event | GroupEvent, project: Project) -> di
179
179
180
180
event_node = {
181
181
"event_id" : event .event_id ,
182
- "datetime" : event . datetime ,
182
+ "datetime" : event_data . get ( "start_timestamp" , float ( "inf" )) ,
183
183
"span_id" : event_data .get ("contexts" , {}).get ("trace" , {}).get ("span_id" ),
184
184
"parent_span_id" : event_data .get ("contexts" , {}).get ("trace" , {}).get ("parent_span_id" ),
185
185
"is_transaction" : is_transaction ,
186
186
"is_error" : is_error ,
187
187
"is_current_project" : event .project_id == project .id ,
188
188
"project_slug" : event .project .slug ,
189
189
"project_id" : event .project_id ,
190
+ "platform" : event .platform ,
190
191
"children" : [],
191
192
}
192
193
@@ -223,7 +224,6 @@ def _get_trace_tree_for_event(event: Event | GroupEvent, project: Project) -> di
223
224
event_node .update (
224
225
{
225
226
"title" : f"{ op } - { transaction_title } " if op else transaction_title ,
226
- "platform" : event .platform ,
227
227
"duration" : duration_str ,
228
228
"profile_id" : profile_id ,
229
229
"span_ids" : span_ids , # Store for later use
@@ -249,7 +249,6 @@ def _get_trace_tree_for_event(event: Event | GroupEvent, project: Project) -> di
249
249
event_node .update (
250
250
{
251
251
"title" : error_title ,
252
- "platform" : event .platform ,
253
252
}
254
253
)
255
254
@@ -346,91 +345,58 @@ def sort_tree(node):
346
345
# Sort children at each level
347
346
sorted_tree = [sort_tree (root ) for root in root_events ]
348
347
349
- # Clean up temporary fields before returning
350
- def cleanup_node (node ):
351
- if "span_ids" in node :
352
- del node ["span_ids" ]
353
- for child in node ["children" ]:
354
- cleanup_node (child )
355
- return node
356
-
357
- cleaned_tree = [cleanup_node (root ) for root in sorted_tree ]
358
-
359
348
return {
360
349
"trace_id" : event .trace_id ,
361
350
"org_id" : project .organization_id ,
362
- "events" : cleaned_tree ,
351
+ "events" : sorted_tree ,
363
352
}
364
353
365
354
366
355
def _get_profile_from_trace_tree (
367
356
trace_tree : dict [str , Any ] | None , event : Event | GroupEvent | None , project : Project
368
357
) -> dict [str , Any ] | None :
369
358
"""
370
- Finds the profile for the transaction that is a parent of our error event.
359
+ Finds the profile for the transaction that contains our error event.
371
360
"""
372
361
if not trace_tree or not event :
373
362
return None
374
363
375
364
events = trace_tree .get ("events" , [])
376
- event_id = event .event_id
377
-
378
- # First, find our error event in the tree and track parent transactions
379
- # 1. Find the error event node and also build a map of parent-child relationships
380
- # 2. Walk up from the error event to find a transaction with a profile
381
-
382
- child_to_parent = {}
383
-
384
- def build_parent_map (node , parent = None ):
385
- node_id = node .get ("event_id" )
386
-
387
- if parent :
388
- child_to_parent [node_id ] = parent
389
-
390
- for child in node .get ("children" , []):
391
- build_parent_map (child , node )
365
+ event_span_id = event .data .get ("contexts" , {}).get ("trace" , {}).get ("span_id" )
392
366
393
- # Build the parent-child map for the entire tree
394
- for root_node in events :
395
- build_parent_map (root_node )
367
+ if not event_span_id :
368
+ return None
396
369
397
- # Find our error node in the flattened tree
398
- error_node = None
399
- all_nodes = []
370
+ # Flatten all events in the tree for easier traversal
371
+ all_events = []
400
372
401
- def collect_all_nodes (node ):
402
- all_nodes .append (node )
373
+ def collect_all_events (node ):
374
+ all_events .append (node )
403
375
for child in node .get ("children" , []):
404
- collect_all_nodes (child )
376
+ collect_all_events (child )
405
377
406
378
for root_node in events :
407
- collect_all_nodes (root_node )
379
+ collect_all_events (root_node )
380
+
381
+ # Find the first transaction that contains the event's span ID
382
+ # or has a span_id matching the event's span_id
383
+ matching_transaction = None
384
+ for node in all_events :
385
+ if node .get ("is_transaction" , False ):
386
+ # Check if this transaction's span_id matches the event_span_id
387
+ if node .get ("span_id" ) == event_span_id :
388
+ matching_transaction = node
389
+ break
408
390
409
- for node in all_nodes :
410
- if node .get ("event_id" ) == event_id :
411
- error_node = node
412
- break
391
+ # Check if this transaction contains the event_span_id in its span_ids
392
+ if event_span_id in node .get ("span_ids" , []) :
393
+ matching_transaction = node
394
+ break
413
395
414
- if not error_node :
396
+ if not matching_transaction or not matching_transaction . get ( "profile_id" ) :
415
397
return None
416
398
417
- # Now walk up the tree to find a transaction with a profile
418
- profile_id = None
419
- current_node = error_node
420
- while current_node :
421
- if current_node .get ("profile_id" ):
422
- profile_id = current_node .get ("profile_id" )
423
- break
424
-
425
- # Move up to parent - child_to_parent maps child event IDs to parent node objects
426
- parent_node = child_to_parent .get (current_node .get ("event_id" ))
427
- if not parent_node :
428
- # Reached the root without finding a suitable transaction
429
- return None
430
- current_node = parent_node
431
-
432
- if not profile_id :
433
- return None
399
+ profile_id = matching_transaction .get ("profile_id" )
434
400
435
401
# Fetch the profile data
436
402
response = get_from_profiling_service (
0 commit comments