AIP-97 POC: tag failure metrics with failure_kind (both emission sites) - #20
Draft
1fanwang wants to merge 3 commits into
Draft
AIP-97 POC: tag failure metrics with failure_kind (both emission sites)#201fanwang wants to merge 3 commits into
1fanwang wants to merge 3 commits into
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
1fanwang
force-pushed
the
aip97-poc-celery
branch
from
July 27, 2026 18:11
2c39e41 to
8c2aa32
Compare
1fanwang
force-pushed
the
aip97-poc-metrics-kind
branch
from
July 27, 2026 18:11
ca9f851 to
41a2a5e
Compare
An infra disruption still increments ti_failures / operator_failures identically to a real bug, so failure dashboards can't separate infra churn from application failures, the same problem the AIP solves for the retry budget. Tag both metrics with failure_kind when the failure is classified; the tag is omitted (metric shape unchanged) when nothing classified it. Signed-off-by: 1fanwang <1fannnw@gmail.com>
ti_failures / operator_failures are emitted from two sites: the scheduler (taskinstance.py, for an externally-killed task) and the worker task runner (task_runner.py, for a failure the worker catches). The first commit tagged only the scheduler side, so an application or timeout failure still emitted an untagged metric and a dashboard grouped by failure_kind would miss half its data. Derive the kind from the caught exception (AirflowTaskTimeout -> timeout, else application) and tag the worker-side emission to match. Found by a live statsd capture: an infra kill tagged failure_kind=infra, but an application failure emitted nothing tagged from the worker until this. Signed-off-by: 1fanwang <1fannnw@gmail.com>
…e tests Assert the wire tag as TaskFailureKind.INFRA.value / APPLICATION.value instead of bare 'infra'/'application' string literals, so the expected value tracks the enum. Signed-off-by: 1fanwang <1fannnw@gmail.com>
1fanwang
force-pushed
the
aip97-poc-celery
branch
from
July 27, 2026 20:01
8c2aa32 to
03035d0
Compare
1fanwang
force-pushed
the
aip97-poc-metrics-kind
branch
from
July 27, 2026 20:01
41a2a5e to
3a7556b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
POC for AIP-97, stacked on the Celery classifier (#15). This carries the classified cause into failure metrics, not only listeners and callbacks.
Why
ti_failuresandoperator_failureswere emitted withoutfailure_kindfrom two paths: the scheduler for an externally killed task, and the worker task runner for a failure caught by the worker. An evicted task and aValueErrortherefore looked identical on the failure dashboards. AIP-97 keeps infra churn off the retry budget, but it also needs to keep it visible in metrics.What
Tag both metrics with
failure_kindat both emission sites. The scheduler side tags an externally killed task with the executor's kind, such asinfrawhen classified. The worker side derives the kind from the caught exception:AirflowTaskTimeoutbecomestimeout; other caught exceptions becomeapplication. The tag is omitted when nothing classified the failure, so the unclassified metric shape is unchanged.Testing
Live: statsd capture on a real Celery stack
Ran the Docker Celery stack (postgres, redis, api-server, scheduler, Dag processor, and
celery worker) with statsd on andstatsd_influxdb_enabled=Trueso tags render on the wire. A UDP sink captured two runs.failure_kind=infraValueErrorfailure_kind=applicationRaw statsd packets
Infra, emitted scheduler-side:
Application, emitted worker-side:
That capture also caught the gap fixed by the second commit. The first commit tagged only the scheduler emission, so scenario 2 emitted an untagged metric until the worker path was tagged too.
Live: OTel to Prometheus to Grafana backend, plus cardinality
The statsd capture proves the tag leaves both emission sites. This run carries it into a real backend and checks cardinality. Full writeup and reproduce steps: evidence branch.
Pipeline with no mocks in the path: Airflow OTel Stats client to OpenTelemetry Collector 0.116.1 to Prometheus v3.1.0 to Grafana 11.4.0. The collector's Prometheus exporter renames
ti_failurestoairflow_ti_failures_totaland keeps the labels.Cardinality:
failure_kindis a bounded 4-value label on a metric that only fires on failure and is already keyed bydag_idandtask_id, so it multiplies the series count by at most 4, usually less. A realistic matrix (5 Dags by 3 tasks, each failing a subset of kinds) produced 47 series from a base of 15, below the 60 worst case:A 4-value enum is a normal metrics label. High cardinality would come from an unbounded label such as a run id or a free-text error string.
Prometheus, all 47 tagged series:
Series per kind (15 + 15 + 8 + 9 = 47):
Grafana, failures grouped by
failure_kindwith the series count. The bars separate infra churn (68 events) from application bugs (50), timeouts (21), and manual stops (8):Airflow mocks
Statsunder pytest, so these backend numbers come from the real OTel Stats client driven with the POC's tag shape outside pytest. Thehandle_failuretostats.incrwiring is covered by the unit tests below.Unit
Scheduler side: an
infrafailure tags both metrics; the unclassified path is unchanged. Worker side: an application failure tags both metrics in the legacy and influx forms, and successes stay untagged. All green.