Run history
Every fire of every job leaves a record. The Runs page and the Run detail drawer are how operators inspect that record — what fired, when, with what parameters, which step succeeded, which failed, what the log says.
This page covers both surfaces and the actions you can take from them.
Where the runs live
You can reach a run from several places:
| From | What you click |
|---|---|
| The Jobs catalogue card. | The coloured state badge after the job id (e.g. SUCCEEDED) — opens the run that produced it. |
| The Schedule view. | A chip in the calendar — only works for fires that have already happened. |
| Direct URL. | /nomaflow/runs/<run-id> if you have the id (from a notification, a colleague, a log line). |
The catalogue's last-run badge always points to the most recent run. To browse further back, follow the link from the Run detail page or use the URL pattern above with the older id.
The Run detail page
The page is split into three regions: header, step timeline, log stream.
The header
| Piece | Meaning |
|---|---|
| Job id · run id | Top-left. Click the job id to open the catalogue card; click the run id to copy it. |
| State badge | QUEUED / RUNNING / SUCCEEDED / FAILED / CANCELED. Live for in-flight runs. |
| Triggered by | cron, user:<name>, api, cli. The audit trail. |
| Started / Finished | Timestamps in the local browser timezone (hover for UTC). For in-flight runs, only Started is shown. |
| Log level | INFO or DEBUG for this run. Useful when troubleshooting — a DEBUG run reads differently than an INFO one. |
| Parameters snapshot | Expandable JSON showing the merged params + op_kwargs as the run actually saw them. The audit answer to "what did this run get". |
The header carries two actions: ✕ Cancel (visible only while the run is RUNNING) and ↻ Replay (visible only on a terminal run).
The step timeline
The left column lists every step in order. Each row shows:
| Element | Meaning |
|---|---|
| Status dot (●) | Green = SUCCEEDED, blue (pulsing) = RUNNING, red = FAILED, grey = pending or CANCELED. |
| Name | Monospace step name. |
| Type | Hover the row to see the type (sql_query, python, …). |
| Duration | Seconds or milliseconds, populated when the step finishes. |
Click a step row to filter the log to only that step's emissions — useful in long runs where the global log is noisy.
The dot transitions live as the runner progresses through the steps. There's no manual refresh — the page subscribes to the run's Socket.IO room.
Step states
| State | When |
|---|---|
pending | The runner hasn't reached this step yet. |
RUNNING | The runner is inside this step. |
SUCCEEDED | The step returned without raising. |
FAILED | The step raised (after retries, if any). |
CANCELED | The operator clicked ✕ Cancel, or the step was disabled (reason skipped: disabled), or an upstream failure stopped the run before this step. |
Clicking a FAILED step expands the row to show the exception message and traceback.
The live log
The right column is the run's log stream. Each line carries:
| Element | Format |
|---|---|
| Timestamp | HH:MM:SS.mmm in the local browser timezone. |
| Level | INFO / WARNING / ERROR. Colour-coded. |
| Message | The text passed to ctx.log.info(…) or emitted by the framework. |
Step boundaries are emitted as INFO lines:
02:30:01.295 INFO step F0004 · SUCCEEDED · 1.2 s
02:30:01.298 INFO step F0005 · type=sql_copy · mode=overwrite
This makes the log self-explanatory — you can read it top-to-bottom and follow the run's narrative without consulting the timeline.
Live streaming
While the run is in flight:
- A green pulse next to "LIVE LOG · streaming" tells you the WebSocket is connected.
- Lines append in real time as they're emitted.
- The view auto-scrolls to the bottom — scroll up and auto-scroll pauses until you scroll back down.
After the run finishes
The log is persisted in the run history and re-rendered from the database on a page reload. Live streaming stops; the same content is still readable. Retention is 90 days by default (configurable in Administration).
Filtering and search
| Action | How |
|---|---|
| Filter to one step | Click the step row in the left column. |
| Show only WARNING / ERROR | Toggle the level chip above the log. |
| Find a specific phrase | Ctrl/Cmd+F in the browser (the log is plain text). |
| Switch to DEBUG | Re-run the job with log_level = DEBUG in the Run-with-parameters modal. |
✕ Cancel
Visible while the run is RUNNING. Clicking sends a cancellation signal:
| Step type | Behaviour on cancel |
|---|---|
sql_query / sql_copy | Database connection closed; transaction rolls back. |
python | Asyncio task cancelled; in-flight await calls raise CancelledError. A step that doesn't yield won't stop until its next checkpoint. |
http | Network request aborted. |
ldap_sync | LDAP connection closed. |
The remaining steps do not run. The run state moves to CANCELED. The log captures run cancelled by user:<name> as the last line.
Cancellation is best-effort for Python steps that loop without yielding to the event loop — see Troubleshoot for the cooperative pattern.
↻ Replay
Visible on terminal runs. Clicking opens a Replay modal pre-filled with the original run's parameters snapshot — same shape as the Run-with-parameters modal:
| Field | Pre-filled with |
|---|---|
log_level | The original run's level. |
| Shared params | The original run's merged params. |
Per-step op_kwargs | The original run's per-step kwargs. |
Per-step enabled | The original run's enable state. |
The operator can adjust anything (typical: change target_connector from production to a sandbox, or disable steps 1-5 to re-run only the tail). Submitting fires a new run — the original is untouched.
Use cases:
| Pattern | Replay tweak |
|---|---|
| "Run the same job again with the same params" | Submit without changes. |
| "Re-run only the failing step" | Disable steps before it; keep it on. |
| "Test against staging" | Change target_connector. |
| "Investigate with full SQL" | Switch log level to DEBUG. |
Filtering runs (the Runs catalogue view)
A "list every run" page is reached from the Jobs catalogue by clicking a job's name — it opens the job's runs list, sorted newest-first. Each row shows:
| Column | What |
|---|---|
| Run id | Click to open the Run detail. |
| State | Coloured badge. |
| Triggered by | cron, user:…, api. |
| Started / Duration | Local timestamp + how long the run took. |
| Step summary | "7 / 7 ✓" or "4 / 7 — failed at F9202". |
Use it to:
- Compare run-to-run durations (a creeping slowdown in an ETL).
- Find the last successful run before a regression.
- Audit who triggered manual runs over the last week.
The Runs catalogue is per job — there's no global "every run across every job" view today; the per-job grouping is what operators actually use.
What's next
- Troubleshoot — when a run fails or hangs, how to find out why.
- Notifications — get pinged on failure instead of refreshing the page.
- Administration — retention, scheduler lock, restart behaviour.