Skip to content

Commit 5bf5ffd

Browse files
authored
🔧 chore(aci): pass evidence data to activity model for notifications (#95475)
1 parent e9e09e1 commit 5bf5ffd

File tree

7 files changed

+76
-14
lines changed

7 files changed

+76
-14
lines changed

src/sentry/issues/status_change_consumer.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def update_status(group: Group, status_change: StatusChangeMessageData) -> None:
6767
status=new_status,
6868
substatus=new_substatus,
6969
activity_type=activity_type,
70+
activity_data=status_change.get("activity_data"),
7071
)
7172
remove_group_from_inbox(group, action=GroupInboxRemoveAction.RESOLVED)
7273
kick_off_status_syncs.apply_async(
@@ -90,6 +91,7 @@ def update_status(group: Group, status_change: StatusChangeMessageData) -> None:
9091
status=new_status,
9192
substatus=new_substatus,
9293
activity_type=activity_type,
94+
activity_data=status_change.get("activity_data"),
9395
)
9496
remove_group_from_inbox(group, action=GroupInboxRemoveAction.IGNORED)
9597
kick_off_status_syncs.apply_async(
@@ -127,6 +129,7 @@ def update_status(group: Group, status_change: StatusChangeMessageData) -> None:
127129
substatus=new_substatus,
128130
activity_type=activity_type,
129131
from_substatus=group.substatus,
132+
activity_data=status_change.get("activity_data"),
130133
)
131134
add_group_to_inbox(group, group_inbox_reason)
132135
kick_off_status_syncs.apply_async(
@@ -164,7 +167,7 @@ def get_group_from_fingerprint(project_id: int, fingerprint: Sequence[str]) -> G
164167

165168

166169
def bulk_get_groups_from_fingerprints(
167-
project_fingerprint_pairs: Iterable[tuple[int, Sequence[str]]]
170+
project_fingerprint_pairs: Iterable[tuple[int, Sequence[str]]],
168171
) -> dict[tuple[int, tuple[str, ...]], Group]:
169172
"""
170173
Returns a map of (project, fingerprint) to the group.

src/sentry/issues/status_change_message.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from collections.abc import Sequence
44
from dataclasses import dataclass, field
5-
from typing import TypedDict
5+
from typing import Any, TypedDict
66
from uuid import uuid4
77

88

@@ -13,6 +13,7 @@ class StatusChangeMessageData(TypedDict):
1313
new_substatus: int | None
1414
id: str
1515
detector_id: int | None
16+
activity_data: dict[str, Any] | None
1617

1718

1819
@dataclass(frozen=True)
@@ -22,6 +23,7 @@ class StatusChangeMessage:
2223
new_status: int
2324
new_substatus: int | None
2425
detector_id: int | None = None
26+
activity_data: dict[str, Any] | None = None
2527
id: str = field(default_factory=lambda: uuid4().hex)
2628

2729
def to_dict(
@@ -33,5 +35,6 @@ def to_dict(
3335
"new_status": self.new_status,
3436
"new_substatus": self.new_substatus,
3537
"detector_id": self.detector_id,
38+
"activity_data": self.activity_data,
3639
"id": self.id,
3740
}

src/sentry/workflow_engine/handlers/detector/stateful.py

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import dataclasses
33
import logging
44
from datetime import UTC, datetime, timedelta
5-
from typing import Generic, cast
5+
from typing import Any, Generic, cast
66
from uuid import uuid4
77

88
from django.conf import settings
@@ -380,18 +380,31 @@ def evaluate(
380380
self.state_manager.commit_state_updates()
381381
return results
382382

383-
def _create_resolve_message(self, group_key: DetectorGroupKey = None) -> StatusChangeMessage:
383+
def _create_resolve_message(
384+
self,
385+
condition_results: ProcessedDataConditionGroup,
386+
data_packet: DataPacket[DataPacketType],
387+
group_key: DetectorGroupKey = None,
388+
) -> StatusChangeMessage:
384389
fingerprint = [
385390
*self.build_issue_fingerprint(),
386391
self.state_manager.build_key(group_key),
387392
]
388393

394+
evidence_data = self._build_evidence_data(
395+
detector_occurrence=None,
396+
evaluation_result=condition_results,
397+
new_priority=DetectorPriorityLevel.OK,
398+
data_packet=data_packet,
399+
)
400+
389401
return StatusChangeMessage(
390402
fingerprint=fingerprint,
391403
project_id=self.detector.project_id,
392404
new_status=GroupStatus.RESOLVED,
393405
new_substatus=None,
394406
detector_id=self.detector.id,
407+
activity_data=evidence_data,
395408
)
396409

397410
def _extract_value_from_packet(
@@ -430,7 +443,11 @@ def _build_detector_evaluation_result(
430443

431444
if new_priority == DetectorPriorityLevel.OK:
432445
# Call the `create_resolve_message` method to create the status change.
433-
detector_result = self._create_resolve_message(group_key)
446+
detector_result = self._create_resolve_message(
447+
condition_results,
448+
data_packet,
449+
group_key,
450+
)
434451
else:
435452
# Call the `create_occurrence` method to create the detector occurrence.
436453
detector_occurrence, event_data = self.create_occurrence(
@@ -484,6 +501,33 @@ def _get_configured_detector_levels(self) -> list[DetectorPriorityLevel]:
484501

485502
return list(DetectorPriorityLevel(level) for level in condition_result_levels)
486503

504+
def _build_evidence_data(
505+
self,
506+
detector_occurrence: DetectorOccurrence | None,
507+
evaluation_result: ProcessedDataConditionGroup,
508+
new_priority: DetectorPriorityLevel,
509+
data_packet: DataPacket[DataPacketType],
510+
) -> dict[str, Any]:
511+
512+
evidence_data: dict[str, Any] = {}
513+
514+
if detector_occurrence:
515+
evidence_data.update(detector_occurrence.evidence_data)
516+
517+
evidence_data.update(
518+
{
519+
"detector_id": self.detector.id,
520+
"value": new_priority,
521+
"data_packet_source_id": str(data_packet.source_id),
522+
"conditions": [
523+
result.condition.get_snapshot()
524+
for result in evaluation_result.condition_results
525+
],
526+
}
527+
)
528+
529+
return evidence_data
530+
487531
def _create_decorated_issue_occurrence(
488532
self,
489533
data_packet: DataPacket[DataPacketType],
@@ -495,15 +539,9 @@ def _create_decorated_issue_occurrence(
495539
"""
496540
Decorate the issue occurrence with the data from the detector's evaluation result.
497541
"""
498-
evidence_data = {
499-
**detector_occurrence.evidence_data,
500-
"detector_id": self.detector.id,
501-
"value": new_priority,
502-
"data_packet_source_id": str(data_packet.source_id),
503-
"conditions": [
504-
result.condition.get_snapshot() for result in evaluation_result.condition_results
505-
],
506-
}
542+
evidence_data = self._build_evidence_data(
543+
detector_occurrence, evaluation_result, new_priority, data_packet
544+
)
507545

508546
fingerprint = [
509547
*self.build_issue_fingerprint(group_key),

tests/sentry/issues/test_status_change_consumer.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def get_test_message_status_change(
3030
"new_substatus": new_substatus,
3131
"payload_type": "status_change",
3232
"detector_id": detector_id,
33+
"activity_data": {"test": "test"},
3334
}
3435

3536
return payload
@@ -373,6 +374,7 @@ def setUp(self) -> None:
373374
new_status=status_change["new_status"],
374375
new_substatus=status_change.get("new_substatus"),
375376
detector_id=status_change.get("detector_id"),
377+
activity_data=status_change.get("activity_data"),
376378
)
377379

378380
def get_latest_activity(self, activity_type: ActivityType) -> Activity:
@@ -399,6 +401,8 @@ def test_handler_is_called__resolved(self) -> None:
399401
update_status(self.group, self.message)
400402
latest_activity = self.get_latest_activity(ActivityType.SET_RESOLVED)
401403

404+
assert latest_activity.data == {"test": "test"}
405+
402406
mock_handler.assert_called_once_with(self.group, self.message, latest_activity)
403407

404408
def test_handler_is_not_called__unresolved_escalating(self) -> None:
@@ -431,6 +435,9 @@ def test_handler_is_called_unresolved_ongoing(self) -> None:
431435

432436
update_status(self.group, self.message)
433437
latest_activity = self.get_latest_activity(ActivityType.AUTO_SET_ONGOING)
438+
439+
assert latest_activity.data == {"test": "test"}
440+
434441
mock_handler.assert_called_once_with(self.group, self.message, latest_activity)
435442

436443
def test_handler_is_called__unresolved_regressed(self) -> None:
@@ -447,6 +454,9 @@ def test_handler_is_called__unresolved_regressed(self) -> None:
447454

448455
update_status(self.group, self.message)
449456
latest_activity = self.get_latest_activity(ActivityType.SET_REGRESSION)
457+
458+
assert latest_activity.data == {"test": "test"}
459+
450460
mock_handler.assert_called_once_with(self.group, self.message, latest_activity)
451461

452462
def test_handler_is_called__ignored(self) -> None:
@@ -463,4 +473,7 @@ def test_handler_is_called__ignored(self) -> None:
463473

464474
update_status(self.group, self.message)
465475
latest_activity = self.get_latest_activity(ActivityType.SET_IGNORED)
476+
477+
assert latest_activity.data == {"test": "test"}
478+
466479
mock_handler.assert_called_once_with(self.group, self.message, latest_activity)

tests/sentry/issues/test_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ def build_statuschange_data(self, **overrides: Any) -> StatusChangeMessageData:
9595
"new_status": 1,
9696
"new_substatus": 1,
9797
"detector_id": None,
98+
"activity_data": {"test": "test"},
9899
}
99100
kwargs.update(overrides) # type: ignore[typeddict-item]
100101

tests/sentry/workflow_engine/test_task.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def test__no_detector_id(self):
5858
new_substatus=None,
5959
fingerprint=["test_fingerprint"],
6060
detector_id=None, # No detector_id provided
61+
activity_data=None,
6162
)
6263

6364
with mock.patch("sentry.workflow_engine.tasks.workflows.metrics.incr") as mock_incr:
@@ -80,6 +81,7 @@ def test__feature_flag(self):
8081
new_substatus=None,
8182
fingerprint=["test_fingerprint"],
8283
detector_id=detector.id,
84+
activity_data={"test": "test"},
8385
)
8486

8587
with mock.patch(
@@ -105,6 +107,7 @@ def test(self):
105107
new_substatus=None,
106108
fingerprint=["test_fingerprint"],
107109
detector_id=detector.id,
110+
activity_data={"test": "test"},
108111
)
109112

110113
with mock.patch(

tests/sentry/workflow_engine/test_task_integration.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def test_handler_invoked__when_resolved(self):
6262
new_substatus=None,
6363
fingerprint=[self.fingerprint],
6464
detector_id=self.detector.id,
65+
activity_data={"test": "test"},
6566
)
6667

6768
with mock.patch("sentry.workflow_engine.tasks.workflows.metrics.incr") as mock_incr:

0 commit comments

Comments
 (0)