Monitoring & reporting
Watch a live run with nb status, review history with nb report, and push failures to a human with pluggable alerts.
Watching a live run
A long nb dump (run detached, e.g. from cron) reports progress to a status file
in the catalog workdir. From any other shell, nb status reads it and prints an
at-a-glance report:
Run run-2026-06-21.020000 [running]
started: 2026-06-21 02:00:03 (elapsed 4m12s)
workers: 2 configured, 2 active
dles: 1 done, 2 active, 1 pending
DLE LEVEL STATE DUMP FLUSH EST DUMPED LANDED
app01:/etc L1 done [##########] 100% direct 120.00 kB 120.00 kB 41.00 kB
app01:/home L0 dumping [####......] 42% - 20.00 GB 8.40 GB 2.90 GB
db01:/pg L0 dumping [##........] 18% - 20.00 GB 3.60 GB 1.20 GB
app01:/var L1 pending - - 80.00 kB 0 B 0 B
Dump: 12.12 GB of ~62.12 GB (20%) 48.10 MB/s
Volume: 4.11 GB written
ETA: 17m18s
The DUMP bar meters each DLE’s source→volume progress — uncompressed bytes
against the planner estimate — with EST the estimate, DUMPED the uncompressed
source read so far, and LANDED what has landed authoritatively. The run streams
source → compressor → volume in one pass, so there is a single dumping state per
DLE — no separate dumper/taper queues — and FLUSH reads direct for that
one-pass path. With a holding disk FLUSH becomes a second bar
metering the drain from the holding disk to the landing, and the bottom gains a
Flush: line for the aggregate backlog. A run landing on a removable medium
(tape) adds a VOLUME column naming the volume(s) — the tape label(s) — each
DLE’s data reached; a disk or cloud landing is its own sole volume, so the column
is dropped.
A run opens in an estimating phase while it sizes every DLE (a pass that can
take a while on a large source), so nb status shows the dump is underway rather
than nothing at all:
Run estimate [estimating]
started: 2026-06-21 02:00:01 (elapsed 0m38s)
sizing: 2 of 4 DLEs measured
estimate: ~22.1 GB so far
It then switches to the dumping view above.
nb status # the running (or most recent) run
nb status --watch 2s # refresh until the run finishes
nb status --watch 2s refreshes until the run finishes; afterwards nb status
shows the last run’s final result. Reading the status file needs no engine, so
it’s cheap to poll.
Reviewing history with nb report
nb status shows one live run; a hands-off install also wants the history and a
way to be told when something breaks. Every mutating command (dump, sync,
prune, verify, drill) records a machine-readable summary to the catalog
workdir — appended to run-log.jsonl and mirrored as run-summary.json (scrape
it from a monitoring system) — and exits non-zero on failure.
nb report summarizes the recent history — what ran, what failed, bytes moved —
plus a recovery-health audit that flags any DLE whose drills are failing,
degrading (passed before, failing now), stale, or never run:
NBackup report — 3 run(s) from 2026-06-23 02:00 to 2026-06-23 02:25
1 run(s) FAILED, 10.74 GB moved
WHEN COMMAND OUTCOME DETAIL
2026-06-23 02:25 drill FAILED 1 failure(s), 1 overdue
2026-06-23 02:13 sync OK 1 run(s) copied, 5.37 GB
2026-06-23 02:00 dump OK run-2026-06-23, 3 archive(s), 5.37 GB
FAILURES
2026-06-23 02:25 drill [drill-failures]: 1 drill failure(s) — recovery is at risk
DRILL COVERAGE
FAILING DLE CLASS LAST DRILL REMEDY
app01:/home pipeline 2026-06-23 02:25 the archive would not decrypt/decompress/untar — …
stale (overdue past 30d): app01:/etc (84d ago)
nb report --last 30 widens the window; nb report --json emits the raw records.
For the classic dump report, nb report --dump prints the latest dump in
detail: a one-line headline, an overall statistics grid (Total / Full / Incr), and
the per-DLE table — each DLE’s level, original/output size, compression %, files,
dump time, and rate:
DUMP REPORT run-2026-06-24.020000 (run 2026-06-24 02:00)
2 DLE(s) dumped OK · 21.47 GB -> 5.37 GB (25%) · 12m00s elapsed
STATISTICS Total Full Incr
DLEs dumped 2 1 1
Original size 21.47 GB 21.47 GB 122.88 kB
Output size 5.37 GB 5.37 GB 40.96 kB
Avg compression 25% 25% 33%
Files 1249 1240 9
Dump time (sum) 12m05s 12m04s 1s
Avg dump rate 29.62 MB/s 29.66 MB/s 122.88 kB/s
Run time (wall) 12m00s
DLE LVL ORIG OUT COMP% FILES TIME RATE
app01:/home 0 21.47 GB 5.37 GB 25% 1240 12m04s 29.66 MB/s
app01:/etc 1 122.88 kB 40.96 kB 33% 9 1s 122.88 kB/s
Dump time is the sum of per-DLE dump times (it exceeds the wall-clock run time when workers run in parallel); run time is the single wall-clock span.
nb report --dump --run run-2026-06-21.020000 reports a specific dump.
Alerting (notify)
To push failures to a human, add a notify: block. Backends are pluggable —
built-in email (SMTP) and a generic webhook (Slack/Discord/PagerDuty-compatible):
notify:
on_failure: [email, slack] # omit to alert every backend
# on_success: [email] # see below — dump already notifies on success
digest: [email] # for `nb report --notify`
backends:
email:
type: smtp
host: smtp.example.com
from: nbackup@example.com
to: [ops@example.com]
password_env: SMTP_PASS # env var name — never the secret itself
slack:
type: webhook
url_env: SLACK_WEBHOOK_URL
What notifies, when:
- Any command alerts on failure by default (every backend, unless
on_failurenarrows it). - A successful
nb dumpalso notifies by default — the nightly “backups happened” signal, so a silent inbox means cron didn’t run, not that all is well. The dump notification carries the full per-DLE dump report (thenb report --dumptable), so the nightly email is the report. - Other commands’ success is opt-in: list backends in
on_successforsync/verify/drill/prune(that list then applies to dump too).
A literal password:/token: key is rejected (neither is a config field), so
an SMTP password is given by the name of an environment variable (password_env)
and resolved at send time — credentials never sit in the config. A webhook URL may be
a literal url: or, when the URL is itself a secret (Slack/Discord bear the
credential in the URL), the name of an environment variable (url_env, preferred). A
notification failure (unreachable mail server, missing secret, hung endpoint) is
only ever a stderr warning: it never fails or blocks the backup.
A hands-off cron line
nb dump && nb sync && nb prune && nb drill --unattended; nb report --notify
This dumps, replicates offsite, trims each medium to its cycle/capacity budget,
rehearses a recovery, and mails the nightly digest — every step recording its run
summary and alerting on failure. nb prune with no medium named prunes every
configured medium against its own retention, and runs after nb sync so nothing
is reclaimed before it is replicated.
See also Verification & drills for what a drill proves, Planning for what each run decides, and the Full 3-2-1-1-0 scenario for the whole unattended pipeline end to end.