|
12 | 12 | from sentry.api import client |
13 | 13 | from sentry.api.endpoints.organization_events_timeseries import TOP_EVENTS_DATASETS |
14 | 14 | from sentry.api.serializers.base import serialize |
| 15 | +from sentry.api.serializers.models.activity import ActivitySerializer |
15 | 16 | from sentry.api.serializers.models.event import EventSerializer |
16 | 17 | from sentry.api.serializers.models.group import GroupSerializer |
17 | 18 | from sentry.api.utils import default_start_end_dates |
18 | 19 | from sentry.constants import ALL_ACCESS_PROJECT_ID, ObjectStatus |
19 | 20 | from sentry.issues.grouptype import GroupCategory |
| 21 | +from sentry.models.activity import Activity |
20 | 22 | from sentry.models.apikey import ApiKey |
21 | 23 | from sentry.models.group import EventOrdering, Group |
22 | 24 | from sentry.models.organization import Organization |
|
42 | 44 | from sentry.snuba.trace import query_trace_data |
43 | 45 | from sentry.snuba.trace_metrics import TraceMetrics |
44 | 46 | from sentry.snuba.utils import get_dataset |
| 47 | +from sentry.types.activity import ActivityType |
45 | 48 | from sentry.utils.dates import outside_retention_with_modified_start, parse_stats_period |
46 | 49 | from sentry.utils.snuba_rpc import get_trace_rpc |
47 | 50 |
|
@@ -825,6 +828,18 @@ def _get_recommended_event( |
825 | 828 | return events[0].for_group(group) |
826 | 829 |
|
827 | 830 |
|
| 831 | +# Activity types to include in issue details for Seer Explorer (manual actions only) |
| 832 | +_SEER_EXPLORER_ACTIVITY_TYPES = [ |
| 833 | + ActivityType.NOTE.value, |
| 834 | + ActivityType.SET_RESOLVED.value, |
| 835 | + ActivityType.SET_RESOLVED_IN_RELEASE.value, |
| 836 | + ActivityType.SET_RESOLVED_IN_COMMIT.value, |
| 837 | + ActivityType.SET_RESOLVED_IN_PULL_REQUEST.value, |
| 838 | + ActivityType.SET_UNRESOLVED.value, |
| 839 | + ActivityType.ASSIGNED.value, |
| 840 | +] |
| 841 | + |
| 842 | + |
828 | 843 | def get_issue_and_event_response( |
829 | 844 | event: Event | GroupEvent, group: Group | None, organization: Organization |
830 | 845 | ) -> dict[str, Any]: |
@@ -865,13 +880,30 @@ def get_issue_and_event_response( |
865 | 880 | else: |
866 | 881 | timeseries, timeseries_stats_period, timeseries_interval = None, None, None |
867 | 882 |
|
| 883 | + # Fetch user activity (comments, status changes, etc.) |
| 884 | + try: |
| 885 | + activities = Activity.objects.filter( |
| 886 | + group=group, |
| 887 | + type__in=_SEER_EXPLORER_ACTIVITY_TYPES, |
| 888 | + ).order_by("-datetime")[:50] |
| 889 | + serialized_activities = serialize( |
| 890 | + list(activities), user=None, serializer=ActivitySerializer() |
| 891 | + ) |
| 892 | + except Exception: |
| 893 | + logger.exception( |
| 894 | + "Failed to get user activity for issue", |
| 895 | + extra={"organization_id": organization.id, "issue_id": group.id}, |
| 896 | + ) |
| 897 | + serialized_activities = [] |
| 898 | + |
868 | 899 | result = { |
869 | 900 | **result, |
870 | 901 | "issue": serialized_group, |
871 | 902 | "event_timeseries": timeseries, |
872 | 903 | "timeseries_stats_period": timeseries_stats_period, |
873 | 904 | "timeseries_interval": timeseries_interval, |
874 | 905 | "tags_overview": tags_overview, |
| 906 | + "user_activity": serialized_activities, |
875 | 907 | } |
876 | 908 |
|
877 | 909 | return result |
|
0 commit comments