Show last run timestamp on ops automation status
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 5s
Build and Publish Container Image / build-and-push (push) Successful in 1m9s

Expose last_run_at / last_run on the status contract and display Last run
and Tasks columns on the /ops/ui status page for the selected window.
This commit is contained in:
tegwick 2026-07-22 00:16:25 +02:00
parent a304ad7397
commit 6c34e2c1f1
3 changed files with 75 additions and 4 deletions

View file

@ -402,11 +402,27 @@ async def ui_status(since: str = Query(default="sunday")) -> HTMLResponse:
"status-bad" if st in {"missed", "validation_failed", "sink_failed"} else "status-warn"
)
aid = html.escape(str(a.get("id") or ""))
last_run = a.get("last_run") or {}
last_at = (
a.get("last_run_at")
or last_run.get("fired_at")
or a.get("temporal_last_fired_at")
or ""
)
last_tasks = last_run.get("tasks_spawned")
last_tasks_s = "" if last_tasks is None else str(last_tasks)
run_count = a.get("observed_run_count", a.get("run_count", a.get("runs_count", "")))
expected_n = a.get("expected_fire_count")
if expected_n is None:
expected_n = len(a.get("expected_fires") or a.get("expected") or [])
rows.append(
f"<tr><td><a href='/ops/ui/automations/{aid}'>{html.escape(str(a.get('name')))}</a></td>"
f"<td class='{cls}'>{html.escape(st)}</td>"
f"<td>{html.escape(str(a.get('run_count', a.get('runs_count', ''))))}</td>"
f"<td>{html.escape(str(len(a.get('expected_fires') or a.get('expected') or [])))}</td>"
f"<td title='latest fire in selected window (or Temporal last action)'>"
f"<code>{html.escape(str(last_at))}</code></td>"
f"<td>{html.escape(last_tasks_s)}</td>"
f"<td>{html.escape(str(run_count))}</td>"
f"<td>{html.escape(str(expected_n))}</td>"
f"<td>{html.escape(str(a.get('enabled')))}</td></tr>"
)
window = html.escape(json.dumps(report.get("window") or {}, indent=2))
@ -418,11 +434,16 @@ async def ui_status(since: str = Query(default="sunday")) -> HTMLResponse:
<label>since <input type="text" name="since" value="{html.escape(since)}"/></label>
<button type="submit">Refresh</button>
</form>
<p class="muted">Last run = newest <code>fired_at</code> in the selected window
(falls back to Temporal schedule last action when no DB run is in-window).</p>
<pre>window: {window}</pre>
<pre>summary: {summary}</pre>
<table>
<thead><tr><th>Name</th><th>Status</th><th>Runs</th><th>Expected</th><th>Enabled</th></tr></thead>
<tbody>{''.join(rows) or '<tr><td colspan="5">No activities</td></tr>'}</tbody>
<thead><tr>
<th>Name</th><th>Status</th><th>Last run</th><th>Tasks</th>
<th>Runs</th><th>Expected</th><th>Enabled</th>
</tr></thead>
<tbody>{''.join(rows) or '<tr><td colspan="7">No activities</td></tr>'}</tbody>
</table>
"""
return _page("Status", body)