Skip to content

Commit b641dc1

Browse files
committed
debugging logs for workflow engine
1 parent cc312e7 commit b641dc1

File tree

6 files changed

+114
-1
lines changed

6 files changed

+114
-1
lines changed

src/sentry/features/temporary.py

+2
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,8 @@ def register_temporary_features(manager: FeatureManager):
483483
manager.add("organizations:workflow-engine-issue-alert-dual-write", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
484484
# Enable workflow engine for issue alerts
485485
manager.add("organizations:workflow-engine-process-workflows", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
486+
# Enable logging to debug workflow engine process workflows
487+
manager.add("organizations:workflow-engine-process-workflows-logs", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
486488
# Enable firing actions for workflow engine issue alerts
487489
manager.add("organizations:workflow-engine-trigger-actions", OrganizationFeature, FeatureHandlerStrategy.FLAGPOLE, api_expose=False)
488490
# Enable dual writing for metric alert issues (see: alerts create issues)

src/sentry/rules/processing/delayed_processing.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from celery import Task
1010
from django.db.models import OuterRef, Subquery
1111

12-
from sentry import buffer, nodestore
12+
from sentry import buffer, features, nodestore
1313
from sentry.buffer.base import BufferField
1414
from sentry.db import models
1515
from sentry.eventstore.models import Event, GroupEvent
@@ -465,6 +465,19 @@ def fire_rules(
465465
groupevent = group_to_groupevent[group]
466466
rule_fire_history = history.record(rule, group, groupevent.event_id, notification_uuid)
467467

468+
if features.has(
469+
"organizations:workflow-engine-process-workflows-logs",
470+
project.organization,
471+
):
472+
logger.info(
473+
"post_process.delayed_processing.triggered_rule",
474+
extra={
475+
"rule_id": rule.id,
476+
"group_id": group.id,
477+
"event_id": groupevent.event_id,
478+
},
479+
)
480+
468481
callback_and_futures = activate_downstream_actions(
469482
rule, groupevent, notification_uuid, rule_fire_history, is_post_process=False
470483
).values()

src/sentry/rules/processing/processor.py

+15
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,21 @@ def apply_rule(self, rule: Rule, status: GroupRuleStatus) -> None:
396396
organization_id=rule.project.organization.id,
397397
rule_id=rule.id,
398398
)
399+
400+
if features.has(
401+
"organizations:workflow-engine-process-workflows-logs",
402+
rule.project.organization,
403+
):
404+
logger.info(
405+
"post_process.process_rules.triggered_rule",
406+
extra={
407+
"rule_id": rule.id,
408+
"payload": state,
409+
"group_id": self.group.id,
410+
"event_id": self.event.event_id,
411+
},
412+
)
413+
399414
notification_uuid = str(uuid.uuid4())
400415
rule_fire_history = history.record(rule, self.group, self.event.event_id, notification_uuid)
401416
grouped_futures = activate_downstream_actions(

src/sentry/workflow_engine/processors/delayed_workflow.py

+11
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
from sentry.workflow_engine.processors.workflow import (
4747
WORKFLOW_ENGINE_BUFFER_LIST_KEY,
4848
evaluate_workflows_action_filters,
49+
log_fired_workflows,
4950
)
5051
from sentry.workflow_engine.types import DataConditionHandler, WorkflowJob
5152

@@ -423,6 +424,16 @@ def fire_actions_for_groups(
423424
tags={"event_type": group_event.group.type},
424425
)
425426

427+
if features.has(
428+
"organizations:workflow-engine-process-workflows-logs",
429+
organization,
430+
):
431+
log_fired_workflows(
432+
log_name="workflow_engine.delayed_workflow.fired_workflow",
433+
actions=filtered_actions,
434+
job=job,
435+
)
436+
426437
if features.has(
427438
"organizations:workflow-engine-trigger-actions",
428439
organization,

src/sentry/workflow_engine/processors/workflow.py

+39
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from sentry.utils import json, metrics
1212
from sentry.workflow_engine.models import (
1313
Action,
14+
AlertRuleWorkflow,
1415
DataCondition,
1516
DataConditionGroup,
1617
Detector,
@@ -111,6 +112,34 @@ def evaluate_workflows_action_filters(
111112
return filter_recently_fired_workflow_actions(filtered_action_groups, job["event"].group)
112113

113114

115+
def log_fired_workflows(log_name: str, actions: BaseQuerySet[Action], job: WorkflowJob) -> None:
116+
# go from actions to workflows
117+
action_ids = {action.id for action in actions}
118+
action_conditions = DataConditionGroup.objects.filter(
119+
dataconditiongroupaction__action_id__in=action_ids
120+
).values_list("id", flat=True)
121+
workflows_to_fire = Workflow.objects.filter(
122+
workflowdataconditiongroup__condition_group_id__in=action_conditions
123+
)
124+
workflow_to_rule = dict(
125+
AlertRuleWorkflow.objects.filter(workflow__in=workflows_to_fire).values_list(
126+
"workflow_id", "rule_id"
127+
)
128+
)
129+
130+
for workflow in workflows_to_fire:
131+
logger.info(
132+
log_name,
133+
extra={
134+
"workflow_id": workflow.id,
135+
"rule_id": workflow_to_rule.get(workflow.id),
136+
"payload": job,
137+
"group_id": job["event"].group_id,
138+
"event_id": job["event"].event_id,
139+
},
140+
)
141+
142+
114143
def process_workflows(job: WorkflowJob) -> set[Workflow]:
115144
"""
116145
This method will get the detector based on the event, and then gather the associated workflows.
@@ -171,6 +200,16 @@ def process_workflows(job: WorkflowJob) -> set[Workflow]:
171200
tags={"detector_type": detector.type},
172201
)
173202

203+
if features.has(
204+
"organizations:workflow-engine-process-workflows-logs",
205+
organization,
206+
):
207+
log_fired_workflows(
208+
log_name="workflow_engine.process_workflows.fired_workflow",
209+
actions=actions,
210+
job=job,
211+
)
212+
174213
with sentry_sdk.start_span(op="workflow_engine.process_workflows.trigger_actions"):
175214
if features.has(
176215
"organizations:workflow-engine-trigger-actions",

tests/sentry/workflow_engine/processors/test_workflow.py

+33
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from sentry import buffer
77
from sentry.eventstream.base import GroupState
88
from sentry.grouping.grouptype import ErrorGroupType
9+
from sentry.models.rule import Rule
910
from sentry.testutils.factories import Factories
1011
from sentry.testutils.helpers import with_feature
1112
from sentry.testutils.helpers.datetime import before_now, freeze_time
@@ -14,6 +15,7 @@
1415
from sentry.utils import json
1516
from sentry.workflow_engine.models import (
1617
Action,
18+
AlertRuleWorkflow,
1719
DataConditionGroup,
1820
DataConditionGroupAction,
1921
Workflow,
@@ -84,6 +86,37 @@ def test_error_event(self):
8486
triggered_workflows = process_workflows(self.job)
8587
assert triggered_workflows == {self.error_workflow}
8688

89+
@with_feature("organizations:workflow-engine-process-workflows-logs")
90+
@patch("sentry.workflow_engine.processors.workflow.logger")
91+
def test_error_event__logger(self, mock_logger):
92+
self.action_group, self.action = self.create_workflow_action(workflow=self.error_workflow)
93+
94+
rule = Rule.objects.filter(project=self.project).first()
95+
AlertRuleWorkflow.objects.create(workflow=self.error_workflow, rule=rule)
96+
97+
triggered_workflows = process_workflows(self.job)
98+
assert triggered_workflows == {self.error_workflow}
99+
100+
mock_logger.info.assert_called_with(
101+
"workflow_engine.process_workflows.fired_workflows",
102+
extra={
103+
"workflow_id": self.error_workflow.id,
104+
"rule_id": rule.id,
105+
"payload": {
106+
"event": self.group_event,
107+
"group_state": {
108+
"id": 1,
109+
"is_new": False,
110+
"is_regression": True,
111+
"is_new_group_environment": False,
112+
},
113+
"workflow": self.error_workflow,
114+
},
115+
"group_id": self.group.id,
116+
"event_id": self.event.event_id,
117+
},
118+
)
119+
87120
def test_same_environment_only(self):
88121
# only processes workflows with the same env or no env specified
89122
self.error_workflow.update(environment=None)

0 commit comments

Comments
 (0)