Skip to content

Commit 732ca5b

Browse files
shayna-chsentry-junior[bot]cursoragent
authored
feat(np): migrate legacy issue alerts to np (#127289)
migrates legacy issue alerts to np for teams, slack, and discord. - Shared send logic: metric and issue alerts now share the code that builds the send target, decides whether to thread, and sends with failure logging. - Threading: follow-up alerts for the same issue reply in the original Slack thread and are also posted to the channel, matching legacy. Uptime and metric issues get a new thread for each open period. - Activity updates: resolve, assign, archive and similar updates are now also posted in Slack threads created by the platform. For uptime issues they go only to the current open period's thread. - Seer autofix: Slack threads from platform alerts are registered for Seer autofix updates, always using the thread's root message. --------- Co-authored-by: sentry-junior[bot] <264270552+sentry-junior[bot]@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent e913f14 commit 732ca5b

15 files changed

Lines changed: 652 additions & 46 deletions

File tree

‎src/sentry/integrations/discord/integration.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def send_notification(
9797
except ApiError as e:
9898
translate_discord_api_error(e)
9999

100-
def send_notification_with_threading(
100+
def send_notification_with_response(
101101
self,
102102
target: IntegrationNotificationTarget,
103103
payload: DiscordRenderable,

‎src/sentry/integrations/msteams/integration.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def send_notification(
103103
client = self.get_client()
104104
client.send_card(conversation_id=target.resource_id, card=payload)
105105

106-
def send_notification_with_threading(
106+
def send_notification_with_response(
107107
self,
108108
target: IntegrationNotificationTarget,
109109
payload: AdaptiveCard,

‎src/sentry/integrations/slack/integration.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def send_notification(
122122
translate_slack_api_error(e)
123123
return {}
124124

125-
def send_notification_with_threading(
125+
def send_notification_with_response(
126126
self,
127127
target: IntegrationNotificationTarget,
128128
payload: SlackRenderable,

‎src/sentry/integrations/slack/service.py‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
from sentry.models.group import Group
3838
from sentry.models.options.organization_option import OrganizationOption
3939
from sentry.notifications.additional_attachment_manager import get_additional_attachment
40+
from sentry.notifications.models.notificationthread import (
41+
NotificationThread,
42+
NotificationThreadObjectType,
43+
)
4044
from sentry.notifications.notifications.activity.archive import ArchiveActivityNotification
4145
from sentry.notifications.notifications.activity.assigned import AssignedActivityNotification
4246
from sentry.notifications.notifications.activity.base import GroupActivityNotification
@@ -58,6 +62,8 @@
5862
from sentry.notifications.notifications.activity.unassigned import UnassignedActivityNotification
5963
from sentry.notifications.notifications.activity.unresolved import UnresolvedActivityNotification
6064
from sentry.notifications.notifications.base import BaseNotification
65+
from sentry.notifications.platform.rollout import NotificationRolloutService
66+
from sentry.notifications.platform.types import SLACK_PROVIDERS, NotificationSource
6167
from sentry.notifications.utils.open_period import open_period_start_for_group
6268
from sentry.silo.base import SiloMode
6369
from sentry.types.activity import ActivityType
@@ -249,6 +255,25 @@ def _notify_all_threads_for_activity(
249255
group_ids=[group.id],
250256
)
251257

258+
# Also query platform threads for issue alerts sent via notification platform. Only orgs in
259+
# a platform rollout tier have them, so skip the query for everyone else. This checks the
260+
# tier, not the per-send random rollout rate, so replies reach every existing thread.
261+
platform_threads = NotificationThread.objects.none()
262+
if NotificationRolloutService(organization=group.organization).has_feature_flag_access():
263+
platform_threads = NotificationThread.objects.filter(
264+
object_type=NotificationThreadObjectType.GROUP,
265+
object_id=group.id,
266+
key_type=NotificationSource.ISSUE.value,
267+
provider_key__in=SLACK_PROVIDERS,
268+
)
269+
if use_open_period_start:
270+
# The platform thread key stores the open period start as an ISO string
271+
platform_threads = platform_threads.filter(
272+
key_data__open_period_start=(
273+
open_period_start.isoformat() if open_period_start else None
274+
)
275+
)
276+
252277
# We don't wrap this in a lifecycle because _handle_parent_notification is already wrapped in a lifecycle
253278
parent_notification_count = 0
254279
for parent_notification in parent_notifications:
@@ -307,6 +332,34 @@ def _notify_all_threads_for_activity(
307332
},
308333
)
309334

335+
# Send to platform threads
336+
for platform_thread in platform_threads:
337+
with MessagingInteractionEvent(
338+
interaction_type=MessagingInteractionType.SEND_ACTIVITY_NOTIFICATION,
339+
spec=SlackMessagingSpec(),
340+
).capture() as lifecycle:
341+
lifecycle.add_extras(
342+
{
343+
"activity_id": activity.id,
344+
"platform_thread_id": platform_thread.id,
345+
"integration_id": client.integration_id,
346+
"group_id": group.id,
347+
"project_id": activity.project.id,
348+
}
349+
)
350+
try:
351+
self._send_notification_to_slack_channel(
352+
channel_id=platform_thread.target_id,
353+
message_identifier=platform_thread.thread_identifier,
354+
notification_to_send=notification_to_send,
355+
client=client,
356+
)
357+
except Exception as err:
358+
if isinstance(err, SlackApiError):
359+
record_lifecycle_termination_level(lifecycle, err)
360+
else:
361+
lifecycle.record_failure(err)
362+
310363
def _get_channel_id_from_parent_notification_notification_action(
311364
self,
312365
parent_notification: NotificationActionNotificationMessage,

0 commit comments

Comments
 (0)