SEZ9 opened a new pull request, #12688:
URL: https://github.com/apache/seatunnel/pull/12688
Closes #12685
### Benchmark
Per our convention of leading with benchmark numbers: this change cannot move
the L1 static smoke preset, and I would rather say so than report a
meaningless delta. `--diagnose` returns before any provider is constructed,
and
this PR adds one module plus one best-effort GET behind that same flag — no
prompt, no tool spec, no planner path is touched, so there is nothing for a
generation benchmark to measure. The run-to-run spread on identical code is
around ±5 tasks, which would swamp any effect even if one existed.
What this rests on instead is 27 new tests (271 total, up from 245 on the
parent branch), including mutation checks on the three assumptions below.
### Why
The rules added in #12631 all compare against zero or a fixed threshold. That
answers "did it break" and "is it stuck", but not the question people
actually
ask about a long-running CDC job — it was fine at first and now it lags.
Such a
job is `RUNNING`, both row counters keep moving and `restoreCount` is 0, so
every rule we have stays silent. Running `--diagnose` against exactly that
shape today produces one line:
```
Job 852 mysql-cdc-to-doris — RUNNING
[info] Running for 72h00m. (state=RUNNING)
```
Which restates what the user already knew.
### What
`GET /jobs/checkpoints/<jobId>` is the one place the engine publishes a
*series* rather than a current value, so the job can be compared against its
own recent past. Six rules read it:
| rule | severity | fires when |
|------|----------|-----------|
| `checkpoint_duration_growing` | warning | recent checkpoints take ≥2× what
earlier ones took |
| `checkpoint_state_growing` | info | recent state is ≥2× earlier state —
usually the cause of the above |
| `checkpoint_bound` | warning | a checkpoint takes ≥80% of the gap between
triggers |
| `checkpoint_never_completed` | warning | checkpoints are triggered but
`completed == 0` |
| `checkpoint_failing` | warning | `failed > 0`, with the engine's own
`failureReason` |
| `checkpoint_stalled` | error | one has been in progress > 120s, naming
unacknowledged subtasks |
Two of these answer different questions on purpose. A *trend* needs a
baseline,
so it only sees degradation still inside the retained window. A *ratio*
(`checkpoint_bound`) needs no baseline at all, which is what makes it work
for
the job that degraded yesterday and has been slow ever since — the common
case
by the time someone asks for help.
The same scenario now gets an actionable answer:
```
Job 852 mysql-cdc-to-doris — RUNNING
[warning] Pipeline 1 has 19 failed checkpoints. ... Last failure:
checkpoint expired before completing (failed=19)
[warning] Pipeline 1 checkpoints are getting slower: recently 48.0s
against 4.0s earlier in the retained
history. ... (median durationMillis 4000 -> 48000 over 16
checkpoints)
[warning] Pipeline 1 now spends almost all its time checkpointing: a
checkpoint takes 48.0s and one is
triggered every 1m00s. Raise checkpoint.interval, or find why
the snapshot is slow ...
(recent median duration 48000ms vs interval 60000ms)
[info] Running for 72h00m. (state=RUNNING)
[info] Pipeline 1 checkpoint state is growing: recently 120.0MiB against
12.0MiB earlier. ...
```
Still read-only, still no LLM call, so it works with no API key and no
provider
configured. The checkpoint read is best-effort on purpose: an engine without
the endpoint, or a cluster with the checkpoint monitor off, still gets the
rest
of the diagnosis rather than a failure.
### Three wire-format details the arithmetic depends on
Each of these fails *silently* — it yields a confident finding that is simply
backwards — so each has a dedicated regression test:
1. **`history` is newest-first.** `PipelineCheckpointOverview.addHistory`
uses
`history.addFirst(...)` and `CheckpointMonitorService.getHistory` sorts by
`triggerTimestamp` descending. Read in array order, every trend conclusion
inverts. Pinned from both directions: a history that is getting *faster*
must not be reported as slower.
2. **Failed checkpoints omit `durationMillis` entirely** (it is a `Long`, and
null fields are not serialized). Counted as zero they would halve the
recent
median and hide a real slowdown.
3. **Their `stateSize` is a primitive `long`**, so it arrives as a plausible
`0` rather than being absent. Counted in, growing state looks like
shrinking
state.
All three are handled by filtering to `status == "COMPLETED"` before any
duration or state arithmetic — but intervals are computed from *every* entry,
because a checkpoint that failed was still triggered on schedule.
### Honest limits
- `maxHistorySize` is 32 per pipeline (`SeaTunnelServer.java:202`), so at a
10s
interval the trend sees roughly five minutes, not three days. This is why
`checkpoint_bound` exists.
- Where the time *goes* (sink vs source) needs `/metrics/realtime`, which is
a
follow-up: `engine.observability.enabled` defaults to `false`, so that rule
has a prerequisite this one does not, and it deserves its own PR.
- The CDC snapshot→incremental transition is not exposed over REST at all
(`AssignerStatus` appears nowhere in `seatunnel-engine/`), so it can only
ever be a hint, never a rule. Not attempted here.
### Also in this PR
Printing findings with `markup=False`. This fixes a real display bug in
#12631: `"error"` is a style name in the CLI theme, so rich was consuming the
`[error]` severity prefix as a style tag. Severity reached the user by colour
alone — invisible in a pipe, in CI, or under `NO_COLOR`. It also stops an
engine failure message containing brackets from corrupting the output, which
is
newly reachable here because `failureReason` is passed through verbatim.
`_as_int` in `jobs.py` is renamed to `as_int` so a sibling module need not
import a private name, and `sort_findings` is extracted so findings from
several rule sets are ordered as one list — sorting each set separately would
put an info line from one above an error from another.
### Stack
This is third in a stack and the diff includes its parents:
- #12629 — one REST module (base)
- #12631 — the `--diagnose` flag (on #12629)
- **this PR** (on #12631)
Review only the last commit, `[Feature][seatunnel-cli] Diagnose a gradual
slowdown from checkpoint history`. I will rebase as the parents land.
### Tests
271 pass (245 on the parent branch). `ruff check .` — the exact command
`cli.yml` runs — passes. Mutation-verified that the ordering assumption is
caught by 5 tests, the `markup=False` fix by 3, and the "unknown `completed`
count is not zero" guard by 1.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]