Add API endpoint and UI for deadline callback log visibility#66610
Add API endpoint and UI for deadline callback log visibility#66610seanghaeli wants to merge 14 commits into
Conversation
2b1e618 to
9102967
Compare
e303ead to
f6103b3
Compare
7f042b1 to
b300616
Compare
|
I like the interface but I would like to have @bbovenzi opinion on this one |
|
@vincbeck Screenshots in the PR description are up to date now |
jason810496
left a comment
There was a problem hiding this comment.
Nice feature! LGTM overall.
|
Thanks for the review @jason810496 Fixed what I think is mission critical / low-risk, left off some others for follow on PRs. Let me know if you disagree with any of the points I've chosen to defer |
d0fd5c3 to
131fe8a
Compare
ferruzzi
left a comment
There was a problem hiding this comment.
It looks like main may be down, but other than that I think this has run its course and can be approved/merged?
432e0c4 to
f7cefa0
Compare
pierrejeambrun
left a comment
There was a problem hiding this comment.
From a UI perspective this looks unpolished.
- Competing card title with TI / Run state (not specific to this PR can be a follow up)
- Callback button style is off compared to other buttons in the header. (borderless, icons, position dropped mid card)
- Deadline section in the header (not spefific to this PR can be a follow up)
| const parseCallbackLogs = ( | ||
| data: TaskInstancesLogResponse["content"], | ||
| translate: TFunction, | ||
| ): Array<ParsedLogEntry> => { | ||
| let lineNumber = 0; | ||
| const lineNumbers = data.map((datum) => { | ||
| const text = typeof datum === "string" ? datum : datum.event; | ||
|
|
||
| if (text.includes("::group::") || text.includes("::endgroup::")) { | ||
| return undefined; | ||
| } | ||
| const current = lineNumber; | ||
|
|
There was a problem hiding this comment.
Looks duplicated from the current parseLog function we can probably re-use some pieces instead.
| // Single deadline — show inline with Expected / Actual times. | ||
| const [dl] = deadlines; | ||
|
|
There was a problem hiding this comment.
can't an entity have multiple missed dealines?
I don't think the way we display this information should have 3 branches based on items count. It's making things confusing.
But that's not related to this PR, can be a follow up.
Can you add screenshot for the log button when there are multiple callbacks/deadlines to show.
Add a callback-logs API endpoint and UI viewer so users can see the logs produced during async (triggerer) and executor deadline callback execution, matching the task-log UX. Includes the callback log reader, the CallbackLogViewer component, and triggerer-side callback log capture/upload.
…anceState Address review feedback on the deadline callback-log viewer: - Replace the hand-rolled stateColorMap + Badge with the shared StateBadge component (maps state to colorPalette and adds the state icon), matching the usage in Run/Details. - Type the callbackState prop as TaskInstanceState instead of a bare string; cast dl.callback_state at the two call sites since the generated API schema types it as string.
…ructuredLog) The prettier import-sort is case-sensitive (uppercase before lowercase), so StateBadge must precede renderStructuredLog. Fixes the ts-compile-lint-ui static check.
…e as CallbackState - read_callback_log is a generator, so path-validation ValueError fires during iteration; move list() inside the try so the 400 is actually raised (was dead code). - Annotate DeadlineResponse.callback_state as CallbackState instead of bare str. (Skipped the StreamingLogResponse alias suggestion — that alias isn't present on this branch's base; the explicit tuple type is correct here.)
Address review: annotate _read_callback_remote_logs and _read_callback_local_logs with the existing StreamingLogResponse alias (= tuple[LogSourceInfo, list[RawLogStream]]) from airflow._shared.logging.remote, instead of the inlined tuple type. Imported under TYPE_CHECKING (annotation-only, no runtime cost).
… spec - _create_workload: read trigger.callback via getattr (it's a Trigger-model attr, not on BaseEventTrigger) so asset-only triggers / spec'd test mocks don't AttributeError. - Regenerate _private_ui.yaml for the callback_state CallbackState enum change.
The callback_state field on DeadlineResponse is now typed as the
CallbackState enum (str enum) rather than a bare string. Regenerate the
UI OpenAPI client so schemas.gen.ts/types.gen.ts include the CallbackState
schema + type and reference it from DeadlineResponse, matching what
'pnpm codegen' produces. Fixes the ts-compile-lint-ui static check
('files were modified by this hook').
datamodel-codegen emits the CalendarTimeRangeResponse 'state' enum alias immediately after the response type, then CallbackState. Match that order in types.gen.ts so ts-compile-lint-ui's codegen step produces no diff.
…anges apache#66608 (now in main) added skip-on-missing-DagRun logic to _create_workload that returns None before the callback logging setup ran, so logger_cache was never populated. Move the TriggerLoggingFactory setup ahead of the context fetch + skip check, so callback logs are captured even when context fetch fails. Update the test to stub _fetch_callback_dag_run_data (via mocker.patch.object, since the supervisor is attrs-slotted) so a workload is built. Verified locally: 1 passed.
Rebase conflict resolution kept the completionRule(alert) usage from apache#66608 but dropped the DeadlineAlertResponse type import, so eslint flagged .interval/.reference_type as unsafe member access on an unresolved type (20 errors in ts-compile-lint-ui). Add the missing import to both DeadlineStatus.tsx and DeadlineStatusModal.tsx.
e5e6615 to
a8409ba
Compare
Summary
Make deadline callback logs visible in the Airflow UI. When a deadline is missed and a callback fires, users can now view the callback's execution logs directly from the web interface.
Changes
Backend:
CallbackLogReaderutility (airflow-core/src/airflow/utils/log/callback_log_reader.py) — reads callback logs from remote or local storage using the sameRemoteLogIOinfrastructure as task logsGET /ui/dags/{dag_id}/dagRuns/{dag_run_id}/callbacks/{callback_id}/logson the deadlines UI routerDeadlineResponsedatamodel — addedcallback_idandcallback_statefieldsFrontend:
CallbackLogViewer.tsxcomponent — fetches and displays callback execution logs in a modal dialogMotivation
Kaxil requested this: "Some way to know if a deadline didn't fire and it failed: something on UI would be great, like Task log. If deadlines are visible, it would be even better experience than previous SLAs."
Dependencies
executor_callbacks/{dag_id}/{run_id}/{callback_id}Was generative AI tooling used to co-author this PR?
Generated-by: Claude Code (Opus 4.6) following the guidelines
End-to-End Verification
Verified in breeze with full Airflow stack (scheduler + dag-processor + triggerer + API server + LocalExecutor). A test DAG with a
SyncCallbackdeadline was parsed, unpaused, scheduled, and the deadline missed naturally. The callback executed throughsupervise_callback()and produced real structured logs.Dag Run Page — Deadline Status with Callback
Callback Logs Modal
Verified:
os.path.commonpathcontainment check