@@ -71,6 +71,7 @@ class SerializedSpan(SerializedEvent):
71
71
start_timestamp : datetime
72
72
is_transaction : bool
73
73
transaction_id : str
74
+ additional_attributes : NotRequired [dict [str , Any ]]
74
75
75
76
76
77
@region_silo_endpoint
@@ -169,12 +170,21 @@ def _qualify_short_id(project: str, short_id: int | None) -> str | None:
169
170
raise Exception (f"Unknown event encountered in trace: { event .get ('event_type' )} " )
170
171
171
172
def serialize_rpc_event (
172
- self , event : dict [str , Any ], group_cache : dict [int , Group ]
173
+ self ,
174
+ event : dict [str , Any ],
175
+ group_cache : dict [int , Group ],
176
+ additional_attributes : list [str ] | None = None ,
173
177
) -> SerializedEvent | SerializedIssue :
174
178
if event .get ("event_type" ) == "span" :
179
+ attribute_dict = {
180
+ attribute : event [attribute ]
181
+ for attribute in additional_attributes or []
182
+ if attribute in event
183
+ }
175
184
return SerializedSpan (
176
185
children = [
177
- self .serialize_rpc_event (child , group_cache ) for child in event ["children" ]
186
+ self .serialize_rpc_event (child , group_cache , additional_attributes )
187
+ for child in event ["children" ]
178
188
],
179
189
errors = [self .serialize_rpc_issue (error , group_cache ) for error in event ["errors" ]],
180
190
occurrences = [
@@ -204,6 +214,7 @@ def serialize_rpc_event(
204
214
op = event ["span.op" ],
205
215
name = event ["span.name" ],
206
216
event_type = "span" ,
217
+ additional_attributes = attribute_dict ,
207
218
)
208
219
else :
209
220
return self .serialize_rpc_issue (event , group_cache )
@@ -306,7 +317,11 @@ def run_perf_issues_query(self, occurrence_query: DiscoverQueryBuilder):
306
317
307
318
@sentry_sdk .tracing .trace
308
319
def query_trace_data (
309
- self , snuba_params : SnubaParams , trace_id : str , error_id : str | None = None
320
+ self ,
321
+ snuba_params : SnubaParams ,
322
+ trace_id : str ,
323
+ error_id : str | None = None ,
324
+ additional_attributes : list [str ] | None = None ,
310
325
) -> list [SerializedEvent ]:
311
326
"""Queries span/error data for a given trace"""
312
327
# This is a hack, long term EAP will store both errors and performance_issues eventually but is not ready
@@ -326,6 +341,7 @@ def query_trace_data(
326
341
snuba_params ,
327
342
Referrer .API_TRACE_VIEW_GET_EVENTS .value ,
328
343
SearchResolverConfig (),
344
+ additional_attributes ,
329
345
)
330
346
errors_future = _query_thread_pool .submit (
331
347
self .run_errors_query ,
@@ -376,7 +392,9 @@ def query_trace_data(
376
392
for errors in id_to_error .values ():
377
393
result .extend (errors )
378
394
group_cache : dict [int , Group ] = {}
379
- return [self .serialize_rpc_event (root , group_cache ) for root in result ]
395
+ return [
396
+ self .serialize_rpc_event (root , group_cache , additional_attributes ) for root in result
397
+ ]
380
398
381
399
def has_feature (self , organization : Organization , request : Request ) -> bool :
382
400
return bool (
@@ -393,6 +411,8 @@ def get(self, request: Request, organization: Organization, trace_id: str) -> Ht
393
411
except NoProjects :
394
412
return Response (status = 404 )
395
413
414
+ additional_attributes = request .GET .getlist ("additional_attributes" , [])
415
+
396
416
update_snuba_params_with_timestamp (request , snuba_params )
397
417
398
418
error_id = request .GET .get ("errorId" )
@@ -402,7 +422,9 @@ def get(self, request: Request, organization: Organization, trace_id: str) -> Ht
402
422
def data_fn (offset : int , limit : int ) -> list [SerializedEvent ]:
403
423
"""offset and limit don't mean anything on this endpoint currently"""
404
424
with handle_query_errors ():
405
- spans = self .query_trace_data (snuba_params , trace_id , error_id )
425
+ spans = self .query_trace_data (
426
+ snuba_params , trace_id , error_id , additional_attributes
427
+ )
406
428
return spans
407
429
408
430
return self .paginate (
0 commit comments