@@ -648,41 +648,6 @@ def _get_issue_event_timeseries(
648648 return data , stats_period , interval
649649
650650
651- def _get_trace_with_spans (
652- trace_ids : list [str ], organization : Organization , start : datetime , end : datetime
653- ) -> str | None :
654- """
655- Given a list of trace IDs, return a trace ID with at least one span (non-deterministic).
656- """
657- # Allow errors if start is outside retention.
658- _ , start = outside_retention_with_modified_start (start , end , organization )
659-
660- if not trace_ids :
661- return None
662-
663- if len (trace_ids ) == 1 :
664- query = f"trace:{ trace_ids [0 ]} "
665- else :
666- query = f"trace:[{ ',' .join (trace_ids )} ]"
667-
668- # Table query for a single item that has one of the trace IDs.
669- result = execute_table_query (
670- org_id = organization .id ,
671- dataset = "spans" ,
672- per_page = 1 ,
673- fields = ["trace" ],
674- query = query ,
675- sort = "-timestamp" ,
676- start = start .isoformat (),
677- end = end .isoformat (),
678- )
679-
680- if not result or not result .get ("data" ):
681- return None
682-
683- return result ["data" ][0 ]["trace" ]
684-
685-
686651def _get_recommended_event (
687652 group : Group ,
688653 organization : Organization ,
@@ -907,7 +872,7 @@ def get_issue_and_event_details_v2(
907872
908873 if group is None :
909874 logger .warning (
910- "get_issue_and_event_details : Missing group" ,
875+ "get_issue_and_event_details_v2 : Missing group" ,
911876 extra = {
912877 "organization_id" : organization_id ,
913878 "project_slug" : project_slug ,
@@ -919,7 +884,7 @@ def get_issue_and_event_details_v2(
919884
920885 if event is None :
921886 logger .warning (
922- "get_issue_and_event_details : Missing event" ,
887+ "get_issue_and_event_details_v2 : Missing event" ,
923888 extra = {
924889 "organization_id" : organization_id ,
925890 "project_slug" : project_slug ,
@@ -937,230 +902,6 @@ def get_issue_and_event_details_v2(
937902 return get_issue_and_event_response (event , None , organization )
938903
939904
940- def get_issue_and_event_details (
941- * ,
942- organization_id : int ,
943- issue_id : str | None ,
944- selected_event : str ,
945- ) -> dict [str , Any ] | None :
946- """
947- Tool to get details for a Sentry issue and one of its associated events. null issue_id can be passed so the
948- is issue is looked up from the event. We assume the event is always associated with an issue, otherwise None is returned.
949-
950- Args:
951- organization_id: The ID of the organization to query.
952- issue_id: The issue/group ID (numeric) or short ID (string) to look up. If None, we fill this in with the event's `group` property.
953- selected_event:
954- If issue_id is provided, this is the event to return and must exist in the issue - the options are "oldest", "latest", "recommended", or a UUID.
955- If issue_id is not provided, this must be a UUID.
956-
957- Returns:
958- A dict containing:
959- Issue fields: aside from `issue` these are nullable if an error occurred.
960- `issue`: Serialized issue details.
961- `tags_overview`: A summary of all tags in the issue.
962- `event_timeseries`: Event counts over time for the issue.
963- `timeseries_stats_period`: The stats period used for the event timeseries.
964- `timeseries_interval`: The interval used for the event timeseries.
965-
966- Event fields:
967- `event`: Serialized event details.
968- `event_id`: The event ID of the selected event.
969- `event_trace_id`: The trace ID of the selected event. Nullable.
970- `project_id`: The event and issue's project ID.
971- `project_slug`: The event and issue's project slug.
972-
973- Returns None when the requested event or issue is not found, or an error occurred.
974- """
975- try :
976- organization = Organization .objects .get (id = organization_id )
977- except Organization .DoesNotExist :
978- logger .warning (
979- "Organization does not exist" ,
980- extra = {"organization_id" : organization_id , "issue_id" : issue_id },
981- )
982- return None
983-
984- org_project_ids = list (
985- Project .objects .filter (organization = organization , status = ObjectStatus .ACTIVE ).values_list (
986- "id" , flat = True
987- )
988- )
989- if not org_project_ids :
990- return None
991-
992- event : Event | GroupEvent | None = None
993- group : Group
994-
995- # Fetch the group object.
996- if issue_id is None :
997- # If issue_id is not provided, first find the event. Then use this to fetch the group.
998- uuid .UUID (selected_event ) # Raises ValueError if not valid UUID
999- # We can't use get_event_by_id since we don't know the exact project yet.
1000- events_result = eventstore .backend .get_events (
1001- filter = eventstore .Filter (
1002- event_ids = [selected_event ],
1003- organization_id = organization_id ,
1004- project_ids = org_project_ids ,
1005- ),
1006- limit = 1 ,
1007- tenant_ids = {"organization_id" : organization_id },
1008- )
1009- if not events_result :
1010- logger .warning (
1011- "Could not find the requested event ID" ,
1012- extra = {
1013- "organization_id" : organization_id ,
1014- "issue_id" : issue_id ,
1015- "selected_event" : selected_event ,
1016- },
1017- )
1018- return None
1019-
1020- event = events_result [0 ]
1021- assert event is not None
1022- if event .group is None :
1023- logger .warning (
1024- "Event is not associated with a group" ,
1025- extra = {"organization_id" : organization_id , "event_id" : event .event_id },
1026- )
1027- return None
1028-
1029- group = event .group
1030-
1031- else :
1032- # Fetch the group from issue_id.
1033- try :
1034- if issue_id .isdigit ():
1035- group = Group .objects .get (project_id__in = org_project_ids , id = int (issue_id ))
1036- else :
1037- group = Group .objects .by_qualified_short_id (organization_id , issue_id )
1038-
1039- except Group .DoesNotExist :
1040- logger .warning (
1041- "Requested issue does not exist for organization" ,
1042- extra = {"organization_id" : organization_id , "issue_id" : issue_id },
1043- )
1044- return None
1045-
1046- # Get the issue data, tags overview, and event count timeseries.
1047- serialized_group = dict (serialize (group , user = None , serializer = GroupSerializer ()))
1048- # Add issueTypeDescription as it provides better context for LLMs. Note the initial type should be BaseGroupSerializerResponse.
1049- serialized_group ["issueTypeDescription" ] = group .issue_type .description
1050-
1051- try :
1052- tags_overview = get_all_tags_overview (group )
1053- except Exception :
1054- logger .exception (
1055- "Failed to get tags overview for issue" ,
1056- extra = {"organization_id" : organization_id , "issue_id" : issue_id },
1057- )
1058- tags_overview = None
1059-
1060- ts_result = _get_issue_event_timeseries (
1061- organization = organization ,
1062- project_id = group .project_id ,
1063- issue_short_id = group .qualified_short_id ,
1064- first_seen_delta = datetime .now (UTC ) - group .first_seen ,
1065- issue_category = group .issue_category ,
1066- )
1067- if ts_result :
1068- timeseries , timeseries_stats_period , timeseries_interval = ts_result
1069- else :
1070- timeseries , timeseries_stats_period , timeseries_interval = None , None , None
1071-
1072- # Fetch event from group, if not already fetched.
1073- if event is None :
1074- if selected_event == "oldest" :
1075- event = group .get_oldest_event ()
1076- elif selected_event == "latest" :
1077- event = group .get_latest_event ()
1078- elif selected_event == "recommended" :
1079- event = group .get_recommended_event ()
1080- else :
1081- uuid .UUID (selected_event ) # Raises ValueError if not valid UUID
1082- event = eventstore .backend .get_event_by_id (
1083- project_id = group .project_id ,
1084- event_id = selected_event ,
1085- group_id = group .id ,
1086- tenant_ids = {"organization_id" : organization_id },
1087- )
1088-
1089- # If the recommended event (default when agent doesn't specify an event) doesn't have a useful trace, try finding a different event.
1090- try :
1091- if selected_event == "recommended" and (
1092- event is None
1093- or event .trace_id is None
1094- or _get_trace_with_spans (
1095- [event .trace_id ],
1096- organization ,
1097- group .first_seen - timedelta (days = 1 ),
1098- group .last_seen + timedelta (days = 1 ),
1099- )
1100- is None
1101- ):
1102- logger .info (
1103- "No spans found for recommended event, trying a different event." ,
1104- extra = {
1105- "organization_id" : organization_id ,
1106- "issue_id" : group .id ,
1107- "recommended_event_id" : event .event_id if event else None ,
1108- "event_trace_id" : event .trace_id if event else None ,
1109- },
1110- )
1111-
1112- candidate_event = _get_recommended_event (group , organization )
1113- if candidate_event :
1114- event = candidate_event
1115-
1116- logger .info (
1117- "Replaced recommended event with an event with spans." ,
1118- extra = {
1119- "organization_id" : organization_id ,
1120- "issue_id" : group .id ,
1121- "candidate_event_id" : candidate_event .event_id ,
1122- "candidate_event_trace_id" : candidate_event .trace_id ,
1123- },
1124- )
1125-
1126- except Exception :
1127- logger .exception (
1128- "Error getting event with valid trace" ,
1129- extra = {
1130- "organization_id" : organization_id ,
1131- "issue_id" : group .id ,
1132- "selected_event" : selected_event ,
1133- },
1134- )
1135-
1136- if event is None :
1137- logger .warning (
1138- "Could not find the selected event." ,
1139- extra = {
1140- "organization_id" : organization_id ,
1141- "issue_id" : issue_id ,
1142- "selected_event" : selected_event ,
1143- },
1144- )
1145- return None
1146-
1147- # Serialize event.
1148- serialized_event = serialize (event , user = None , serializer = EventSerializer ())
1149-
1150- return {
1151- "issue" : serialized_group ,
1152- "event_timeseries" : timeseries ,
1153- "timeseries_stats_period" : timeseries_stats_period ,
1154- "timeseries_interval" : timeseries_interval ,
1155- "tags_overview" : tags_overview ,
1156- "event" : serialized_event ,
1157- "event_id" : event .event_id ,
1158- "event_trace_id" : event .trace_id ,
1159- "project_id" : event .project_id ,
1160- "project_slug" : event .project .slug ,
1161- }
1162-
1163-
1164905def get_replay_metadata (
1165906 * ,
1166907 replay_id : str ,
0 commit comments