Link automation.action.* events to automation.triggered event#28
Conversation
When debugging automation failures at high volumes, it's difficult to trace from an `automation.action.failed` event back to the `automation.triggered` event that spawned it. This adds an `automation_triggered_event_id` field to `TriggeredAction` and includes it as a related resource with role `automation-triggered-event` on all action events (`.triggered`, `.executed`, and `.failed`). Port of https://github.com/PrefectHQ/nebula/pull/10911 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The triggering-event related resource should appear on all three action event types (.triggered, .executed, .failed) to enable full traceability. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Now that automation.action.executed and automation.action.failed events include a triggering-event related resource, update the tests to expect it in their assertions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Build related_resources once at the start of fail() and succeed() methods and reuse it for both the .triggered and .failed/.executed events, rather than building separate lists with identical logic. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a brief section to the automations docs explaining the events emitted during automation execution and the related resources (triggering-event and automation-triggered-event) available for tracing action failures back to their source. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
WalkthroughThis change introduces event tracing for automation actions by adding related resource links to action events. It adds a new Changes
Sequence Diagram(s)sequenceDiagram
participant Event as External Event
participant Automation as Automation Trigger
participant ActionSvc as Action Service
participant EventEmitter as Event Emitter
Event->>Automation: Event received (triggering_event)
Automation->>Automation: Select primary state change event<br/>(triggered or resolved)
Automation->>ActionSvc: Create TriggeredAction with<br/>automation_triggered_event_id
ActionSvc->>ActionSvc: Build related resources:<br/>- triggering-event<br/>- automation-triggered-event
ActionSvc->>EventEmitter: Emit action.triggered event<br/>with related resources
EventEmitter->>EventEmitter: Emit prefect.automation.action.triggered
ActionSvc->>ActionSvc: Execute action logic
ActionSvc->>EventEmitter: Emit action.executed/failed<br/>with related resources
EventEmitter->>EventEmitter: Emit prefect.automation.action.executed<br/>or prefect.automation.action.failed
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (16)
🧰 Additional context used🧬 Code graph analysis (2)src/prefect/server/events/actions.py (2)
src/prefect/server/events/triggers.py (2)
🪛 GitHub Actions: Static analysissrc/prefect/server/events/schemas/automations.py[error] 774-774: Type annotation for parameter "v" is missing; Type annotation for parameter "info" is missing; Return type annotation is missing src/prefect/server/events/actions.py[error] 812-812: Type of parameter "triggered_action" is partially unknown. Parameter type is "TriggeredAction" [error] 926-926: Type of parameter "triggered_action" is partially unknown. Parameter type is "TriggeredAction" [error] 342-342: Type of parameter "triggered_action" is partially unknown. Parameter type is "TriggeredAction" [error] 351-351: Type of parameter "triggered_action" is partially unknown. Parameter type is "TriggeredAction" 🪛 Ruff (0.14.14)src/prefect/server/events/schemas/automations.py777-779: Avoid specifying long messages outside the exception class (TRY003) ⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (37)
🔇 Additional comments (27)
✏️ Tip: You can disable this entire section by setting Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/prefect/server/events/actions.py (1)
197-207: Bug:prefect.automation.action.triggeredevent infail()is missing the related resources.In the
fail()method,related_resourcesis constructed with theautomation-triggered-eventandtriggering-eventresources (lines 177-196), but theprefect.automation.action.triggeredevent at line 202 usesself._resulting_related_resourcesinstead of the constructedrelated_resources.This is inconsistent with the
succeed()method (line 291) which correctly passesrelated_resourcesto the triggered event. As a result, the triggered event emitted during failure will be missing both theautomation-triggered-eventandtriggering-eventrelated resources.🐛 Proposed fix
await events.emit( Event( occurred=triggered_action.triggered, event="prefect.automation.action.triggered", resource=resource, - related=self._resulting_related_resources, + related=related_resources, payload=action_details, id=triggered_event_id, follows=follows_id, ) )
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (16)
docs/v3/concepts/automations.mdxsrc/prefect/server/events/actions.pysrc/prefect/server/events/schemas/automations.pysrc/prefect/server/events/triggers.pytests/events/server/actions/test_actions_service.pytests/events/server/actions/test_calling_webhook.pytests/events/server/actions/test_cancelling_flow_run.pytests/events/server/actions/test_changing_flow_run_state.pytests/events/server/actions/test_pausing_resuming_deployment.pytests/events/server/actions/test_pausing_resuming_work_pool.pytests/events/server/actions/test_pausing_resuming_work_queue.pytests/events/server/actions/test_resuming_flow_run.pytests/events/server/actions/test_running_deployment.pytests/events/server/actions/test_sending_notification.pytests/events/server/actions/test_suspending_flow_run.pytests/events/server/triggers/test_service.py
🧰 Additional context used
🧬 Code graph analysis (2)
src/prefect/server/events/actions.py (2)
src/prefect/server/events/schemas/events.py (1)
RelatedResource(86-102)src/prefect/events/schemas/events.py (1)
RelatedResource(84-100)
src/prefect/server/events/triggers.py (2)
src/prefect/server/events/schemas/events.py (1)
id(68-69)src/prefect/server/events/schemas/automations.py (2)
TriggerState(58-60)automation(77-81)
🪛 GitHub Actions: Static analysis
src/prefect/server/events/schemas/automations.py
[error] 774-774: Type annotation for parameter "v" is missing; Type annotation for parameter "info" is missing; Return type annotation is missing
src/prefect/server/events/actions.py
[error] 812-812: Type of parameter "triggered_action" is partially unknown. Parameter type is "TriggeredAction"
[error] 926-926: Type of parameter "triggered_action" is partially unknown. Parameter type is "TriggeredAction"
[error] 342-342: Type of parameter "triggered_action" is partially unknown. Parameter type is "TriggeredAction"
[error] 351-351: Type of parameter "triggered_action" is partially unknown. Parameter type is "TriggeredAction"
🪛 Ruff (0.14.14)
src/prefect/server/events/schemas/automations.py
777-779: Avoid specifying long messages outside the exception class
(TRY003)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (37)
- GitHub Check: Database and Orchestration Tests - python:3.13, sqlite
- GitHub Check: Database and Orchestration Tests - python:3.12, sqlite
- GitHub Check: Client Tests - python:3.12, postgres:14
- GitHub Check: Runner, Worker, Settings, Input, and CLI Tests - python:3.10, postgres:14
- GitHub Check: Database and Orchestration Tests - python:3.10, postgres:14
- GitHub Check: Test SQLite 3.24.0 Compatibility
- GitHub Check: Client Tests - python:3.10, postgres:14
- GitHub Check: Prefect Client Compatibility Tests
- GitHub Check: Client Tests - python:3.13, postgres:14
- GitHub Check: Integration tests
@main - GitHub Check: Database and Orchestration Tests - python:3.14, sqlite
- GitHub Check: Test SQLite 3.31.1 Compatibility
- GitHub Check: Server Tests - python:3.11, sqlite
- GitHub Check: Database and Orchestration Tests - python:3.10, sqlite
- GitHub Check: Runner, Worker, Settings, Input, and CLI Tests - python:3.14, postgres:14
- GitHub Check: Runner, Worker, Settings, Input, and CLI Tests - python:3.13, postgres:14
- GitHub Check: Runner, Worker, Settings, Input, and CLI Tests - python:3.11, postgres:14
- GitHub Check: Server Tests - python:3.13, sqlite
- GitHub Check: Server Tests - python:3.12, sqlite
- GitHub Check: Database and Orchestration Tests - python:3.12, postgres:14
- GitHub Check: Client Tests - python:3.14, postgres:14
- GitHub Check: Runner, Worker, Settings, Input, and CLI Tests - python:3.12, postgres:14
- GitHub Check: Database and Orchestration Tests - python:3.14, postgres:14
- GitHub Check: Database and Orchestration Tests - python:3.13, postgres:14
- GitHub Check: Database and Orchestration Tests - python:3.11, sqlite
- GitHub Check: Server Tests - python:3.14, postgres:14
- GitHub Check: Server Tests - python:3.14, sqlite
- GitHub Check: Server Tests - python:3.10, sqlite
- GitHub Check: Client Tests - python:3.11, postgres:14
- GitHub Check: Server Tests - python:3.12, postgres:14
- GitHub Check: Database and Orchestration Tests - python:3.11, postgres:14
- GitHub Check: Server Tests - python:3.13, postgres:14
- GitHub Check: Server Tests - python:3.11, postgres:14
- GitHub Check: Server Tests - python:3.10, postgres:14
- GitHub Check: Benchmark
- GitHub Check: Benchmark
- GitHub Check: typesafety
🔇 Additional comments (27)
tests/events/server/actions/test_pausing_resuming_work_pool.py (2)
298-312: Good addition of triggering-event related resource in executed event.This keeps executed_event.related aligned with the new tracing requirements.
545-559: Executed event related resources updated consistently.The added triggering-event link mirrors the pause path and supports traceability.
tests/events/server/actions/test_pausing_resuming_work_queue.py (2)
468-474: Good coverage for executed-event traceability.
The added triggering-event related resource in the executed event aligns expectations with the new linkage behavior.
525-531: Consistent executed-event linkage assertion.
The new triggering-event related resource assertion mirrors the expected tracing behavior for resume actions.tests/events/server/actions/test_changing_flow_run_state.py (1)
316-329: Good coverage for executed-event lineage.Adding the triggering-event related resource keeps the executed event consistent with the triggered event and the new traceability model.
tests/events/server/actions/test_running_deployment.py (1)
507-528: Executed-event related resources now align with triggering context.This matches the triggered-event linkage and improves traceability.
tests/events/server/actions/test_sending_notification.py (2)
264-285: Executed-event includes triggering-event linkage as expected.This keeps executed notifications traceable back to the original event.
342-363: Failed-event now preserves triggering-event lineage.Good consistency with triggered/executed assertions.
tests/events/server/actions/test_pausing_resuming_deployment.py (2)
485-499: Pause executed-event now links back to triggering event.Keeps action lineage consistent with triggered event.
542-556: Resume executed-event lineage is now complete.This matches the updated related-resource model.
tests/events/server/actions/test_resuming_flow_run.py (1)
157-171: Executed-event now mirrors triggering-event linkage.Consistent with the updated traceability expectations.
tests/events/server/actions/test_calling_webhook.py (1)
415-436: Webhook executed-event now includes triggering-event reference.Good alignment with the new action event lineage.
tests/events/server/actions/test_cancelling_flow_run.py (1)
250-257: LGTM!The test correctly verifies that the
executed_eventnow includes thetriggering-eventrelated resource, aligning with the PR objective to surface triggering event links on all action events (triggered, executed, failed).tests/events/server/actions/test_suspending_flow_run.py (1)
246-253: LGTM!The test correctly mirrors the pattern from
test_cancelling_flow_run.py, verifying thatexecuted_eventincludes thetriggering-eventrelated resource for suspend actions.tests/events/server/triggers/test_service.py (2)
60-61: LGTM!The test correctly includes the new
automation_triggered_event_idfield in the expectedTriggeredAction, usingparsed.automation_triggered_event_idto handle the dynamically generated UUID.
94-95: LGTM!Consistent with the reactive event test above, this proactive trigger test correctly includes the
automation_triggered_event_idfield.docs/v3/concepts/automations.mdx (1)
88-104: LGTM!The documentation clearly explains the new tracing capability with:
- List of emitted events at each stage of automation firing
- Table describing the related resource roles for tracing
- Concise explanation of how these links enable debugging
This aligns well with the implementation changes in the PR.
tests/events/server/actions/test_actions_service.py (6)
6-6: LGTM!Import of
uuid7from internal module is correct for generating time-ordered UUIDs for the automation-triggered event IDs.
139-145: LGTM!Correctly verifies that
executed_eventincludes thetriggering-eventrelated resource, consistent with the PR objectives.
205-211: LGTM!Correctly verifies that
action.failedevents also include thetriggering-eventrelated resource.
311-410: LGTM!Comprehensive test that verifies:
automation-triggered-eventrelated resource appears on bothaction.triggeredandaction.executedeventstriggering-eventrelated resource is still present alongside the new resource- Uses appropriate pattern with
next()to find specific related resources by role
413-502: LGTM!Good coverage of the failure path - verifies that
automation-triggered-eventandtriggering-eventrelated resources appear on bothaction.triggeredandaction.failedevents when the action fails.
505-553: LGTM!Important negative test case that verifies when
automation_triggered_event_idisNone:
- Only
triggering-eventrelated resource is present- No
automation-triggered-eventrelated resource is added- Ensures backward compatibility with existing behavior
src/prefect/server/events/schemas/automations.py (2)
763-770: LGTM!The new
automation_triggered_event_idfield is well-defined with a clear description explaining its purpose for linking action events back to the automation state change event.
772-780: Add missing type annotations to fix pipeline failure.The validator is missing type annotations for parameters and return type, which is causing the static analysis pipeline to fail.
🔧 Proposed fix to add type annotations
+from pydantic import ( + Field, + PrivateAttr, + ValidationInfo, + field_validator, + model_validator, +) + `@field_validator`("automation_triggered_event_id") `@classmethod` - def validate_automation_triggered_event_id(cls, v, info): + def validate_automation_triggered_event_id( + cls, v: UUID | None, info: ValidationInfo + ) -> UUID | None: """Ensure automation_triggered_event_id is only set when triggering_event exists.""" if v is not None and info.data.get("triggering_event") is None: raise ValueError( "automation_triggered_event_id can only be set when triggering_event is provided" ) return vNote:
ValidationInfoneeds to be added to the import frompydanticat line 23.Likely an incorrect or invalid review comment.
src/prefect/server/events/actions.py (1)
266-310: LGTM!The
succeed()method correctly constructsrelated_resourceswith both theautomation-triggered-event(when present) andtriggering-eventresources, and consistently uses it for both theprefect.automation.action.triggeredandprefect.automation.action.executedevents.src/prefect/server/events/triggers.py (1)
439-489: LGTM!The implementation correctly:
- Determines
primary_state_change_event_idby preferringTriggerState.TriggeredoverTriggerState.Resolved- Extends
source_actionstuples to carry the event ID as a third element- Consistently propagates
automation_triggered_event_idto allTriggeredActioninstancesThis enables proper tracing from action events back to the originating automation state change event.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
Benchmark PR from agentic-review-benchmarks#2
Summary by CodeRabbit
Release Notes
Documentation
New Features
✏️ Tip: You can customize this high-level summary in your review settings.