Skip to content

Add 'fileglancer debug' TUI for watching the job system - #407

Merged
krokicki merged 6 commits into
mainfrom
debugger
Jul 8, 2026
Merged

krokicki merged 6 commits into
mainfrom
debugger

Conversation

@krokicki

@krokicki krokicki commented Jul 8, 2026 •

Copy link
Copy Markdown
Member

What this adds

A read-only curses dashboard for debugging the job system, runnable as fileglancer debug (works via uvx fileglancer debug once released) or pixi run debug-launch. Single file (fileglancer/debug.py), stdlib-only — no new dependencies in the wheel.

Panes

  • Jobs (all users): statuses, cluster IDs, age, time-in-state; a toggles active-only vs all. Enter opens a detail overlay (DB fields, work-dir file probe, stderr tail) pinned to the job it was opened on.
  • Processes (this host): server processes and per-user worker subprocesses (owner, age, CPU, RSS, current activity), with the poll-lock holder marked ● POLLER.
  • Scheduler activity (this host): live bsub/bjobs/bkill commands as they spawn under workers, caught by /proc sampling.
  • Events: status transitions from DB diffing, worker spawn/exit, poll-lock changes, observed scheduler commands. --log FILE appends the feed to a file for post-mortem analysis.
  • Log viewer (o/e/s): full-screen live tail of a job's stdout/stderr/script with follow mode, scrolling, and panning. Tails the last 256 KB so multi-GB HPC logs are safe.

How it observes

Each data source is sampled by its own background thread so a slow source (NFS stat, bjobs) never blocks the UI: the DB (jobs table snapshots, diffed into events), /proc (processes + the flock holder of the poll lock file, whose mtime doubles as a poll heartbeat), job work directories (phase/service_url/job.pid/log sizes), and optionally the scheduler itself — the b key enables a bjobs cross-check that flags rows where LSF disagrees with the DB.

The cross-check found a real production bug on its first day: the DB stuck at PENDING while bjobs said RUN for other users' jobs, diagnosed as the name-filtered polling visibility issue fixed in JaneliaSciComp/py-cluster-api#3.

Behavior notes

  • Process/lock/heartbeat data is host-local: when watching a remote server's database, those panes describe the local machine, and the header shows POLLER/heartbeat as n/a instead of raising false "NO POLL ACTIVITY" alarms. Work-dir probes and the log viewer work cross-host over shared mounts; the bjobs cross-check queries the cluster so it is valid from anywhere.
  • DB credentials are redacted (postgresql://***@host/db) in the header, event feed, and --log output.
  • Strictly read-only: never modifies the DB, never signals processes; the only scheduler command it runs itself is the opt-in bjobs cross-check.

Testing

Driven end-to-end in a pty with a seeded database: dashboard rendering, poll-lock holder detection (flock held by a child process, matched via /proc/locks), live status-transition events, detail-overlay pinning while the table re-sorts, log viewer follow mode picking up live appends, file switching, credential redaction (screen + log file), and remote-DB mode simulated in an unprivileged PID namespace (unshare --mount-proc) to verify the n/a header path.

@StephanPreibisch @JaneliaSciComp/fileglancer

krokicki and others added 6 commits July 8, 2026 10:00
A read-only curses dashboard for debugging job polling: shows all users'
jobs and status transitions, per-user worker subprocesses, which server
process holds the poll lock (with mtime heartbeat), live scheduler
commands (bsub/bjobs/bkill) as they spawn, an event feed, an optional
bjobs cross-check that flags DB/scheduler mismatches, and a live-follow
log viewer (stdout/stderr/script) per job.

Runs via 'fileglancer debug' or 'pixi run debug-launch'; stdlib-only so
the published wheel needs no new dependencies.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The overlay was bound to a table position, so when the jobs table
re-sorted (new job arrived, status changed) a different job slid into
the selected row and the overlay silently switched to it. Pin the
overlay to the job id at open time: its own fields still refresh live,
but it never changes jobs. Closing re-anchors the table selection to
the viewed job, and o/e/s from the overlay open logs for the pinned
job rather than the drifted selection. The work-dir prober now targets
whatever is being viewed (log job, then detail job, then selection).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The poll lock and its mtime heartbeat are host-local, so when the
watched database belongs to a server on another machine they described
the wrong host — a stale leftover lock file plus active jobs raised a
permanent false "NO POLL ACTIVITY" alarm. When no fileglancer server
process is found on this host, show POLLER/heartbeat as n/a instead,
and label the process and scheduler panes "(this host)".

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The header and the "watching db" event (which also lands in the --log
file) showed the full db_url, leaking user:password for postgres URLs.
Strip credentials to scheme://***@host/db for display so it is still
clear where the tool connects; only the connection itself uses the raw
URL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pixi.lock is now format version 7 (from local pixi 0.70.2), but CI
was pinned to v0.65.0 which doesn't support that lock-file version,
failing every build/integration job before it reached any real work.
@krokicki
krokicki merged commit 630d651 into main Jul 8, 2026
5 checks passed
@krokicki
krokicki deleted the debugger branch July 8, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant