Repository navigation
Add DatadogMonitorSensorAsync waiting on a monitor's overall state - #71625
raghavan-arvind wants to merge 1 commit into
Conversation
|
Verified all these sensors return the correct result: |
ec1ba66 to
0ccc8f8
Compare
|
The soft_fail tests are reliant on some fix like: Would like to discuss that PR first before this one |
| def resume_execution(self, next_method: str, next_kwargs: dict[str, Any] | None, context: Context): | ||
| """ | ||
| Resume from deferral, applying ``soft_fail`` only to timeouts. | ||
|
|
||
| ``BaseSensorOperator.resume_execution`` converts any deferral-path failure into a skip when | ||
| ``soft_fail`` is set, including trigger crashes (e.g. a bad monitor id or auth failure), | ||
| which silently skips the downstream branch. This sensor instead keeps parity with poke and | ||
| reschedule modes, where only timeouts are skippable and other errors fail the task. | ||
| """ | ||
| try: | ||
| return super(BaseSensorOperator, self).resume_execution(next_method, next_kwargs, context) | ||
| except TaskDeferralError as e: | ||
| timed_out = isinstance(e, TaskDeferralTimeout) or str(e) == "Trigger/execution timeout" | ||
| if timed_out and self.soft_fail: | ||
| raise AirflowSkipException(str(e)) from e | ||
| if getattr(self, "never_fail", False): | ||
| raise AirflowSkipException(str(e)) from e | ||
| if timed_out: | ||
| raise AirflowSensorTimeout(*e.args) from e | ||
| raise |
There was a problem hiding this comment.
Ideally we can remove this and merge some variant of #71256 first.
|
Would like to only support I know edit: updated |
0ccc8f8 to
91f9a8a
Compare
91f9a8a to
41bc29c
Compare
|
Is there a reason this needs a separate |
Why
The existing
DatadogSensorqueries the event stream for transition events in a time window. That shape cannot answer "is this monitor healthy right now": a monitor that entered Alert before the window (or recovered before it) emits no event inside it, so gating a pipeline on monitor health requires reconstructing state from transitions.This adds
DatadogMonitorSensorAsync, which checks a monitor's currentoverall_state— an already-alerting or already-recovered monitor is observed regardless of when it last changed state.What
DatadogMonitorSensorAsync: waits for a monitor to reach one oftarget_states(default("OK",)). Deferrable-only, and named*Asyncto make that explicit: it waits in the triggerer via a newDatadogMonitorTriggerand never occupies a worker slot while waiting; there is deliberately no poke-mode fallback.DatadogMonitorTrigger: polls the monitor state off the event loop (asyncio.to_thread, since the datadog client is sync) and fires when a target state is reached.soft_failon the deferral path applies only to timeouts, matching poke/reschedule semantics elsewhere: a trigger crash (bad monitor id, auth failure) fails the task loudly instead of being converted into a skip that silently skips the downstream branch. Works on both Airflow 3.x (TaskDeferralTimeout) and 2.11 (timeout arrives asTaskDeferralError("Trigger/execution timeout")).AirflowException(e.g.Datadog monitor 999999999: ['Monitor not found']).triggerssection; unit tests for the sensor (defer, completion, soft_fail semantics) and trigger (serialize round-trip, poll-until-target, API error).Testing
uv run --project providers/datadog pytest providers/datadog/tests/unit/datadog: 18 passed. Also validated end to end in a production-like Airflow 3.3 deployment with canary tasks covering pass / timeout / timeout-with-soft_fail / missing-monitor / missing-with-soft_fail.🤖 Generated with Claude Code