Output, Progress and Exit Codes
What GoArchive writes to stdout, stderr and the log, the progress display, the closing report, and the exit codes.
GoArchive writes a command’s result on stdout, diagnostics on stderr, and every log entry to the log, as logging configures it. Nothing reaches stdout that you did not ask for, and an error always reaches stderr.
Streams
| Stream | Carries |
|---|---|
| stdout | The validate, dry-run, plan and list-jobs reports, version, --version, completion and the help. For a run, only with --progress: the start line, the progress lines and the closing block. The log, when logging.output is stdout (or empty) |
| stderr | Every error; the WARNING: lines; with --progress and a log file, the log’s warnings and errors (as level keeps them) and live events. The log, when logging.output is stderr |
| log | Every entry, in its format, at its level. A log file is the run’s record |
Three logging setups
A log file (
output: <path>), the setup for scheduled runs. Without--progress, a run is silent: it prints nothing when it completes or stops, and on a failure prints a summary and the error on stderr:Job archive_old_orders (archive): failed in 61.240s. Log: /var/log/goarchive/orders.log Error: engine: β¦A failure before startup completes (connecting, preflight, locks, registration) says
failed before the first batch.instead of a duration. With--progress, the start line, the progress lines and the closing block go to stdout, and the log’s warnings and errors go to stderr as text lines, with live events whatever the level: a replication hold, the replica recovering, a stop ending a hold, a pause and its end, recovery.file_only: truekeeps every log entry off the console; warnings and errors still reach stderr.The log on the console as text (
output: stdoutorstderr,format: text): the log stream is plain text, with no colour codes.--progressadds its lines and the closing block on stdout.The log on the console as JSON (
output: stdoutorstderr,format: json), the default and the setup for containers: every line of the log stream is one JSON object.--progresswritesRun starting,progressand the closing entry there instead of printing lines, and the closing entry carries the counts. On a failure withoutput: stdout, one plainError:line goes to stderr; withoutput: stderr, the error is the closing entry itself. An error found before the log exists (a flag, the configuration file, an unknown job) is always a plainError:line.
validate and dry-run print their reports as text on stdout in every setup. In a container, set logging.output: stderr for them, so stdout carries only the report and stderr only the log.
Progress display
A bare --progress reports every 30 seconds. --progress=10s or --progress=1m30s sets the interval, and a bare integer is seconds (minimum one second). The value must be attached with =: --progress 10s is refused with that hint.
Job archive_old_orders (archive): starting. Log: /var/log/goarchive/orders.log
progress: roots 4000/~12000 ( 33.3%) remaining=8000 copied_rows=21640 deleted_rows=21640 elapsed=42s eta=1m18s
progress: roots 8000/~12000 ( 66.7%) remaining=4000 copied_rows=43310 deleted_rows=43310 elapsed=1m12s eta=36s
progress: roots 12000/~12000 (100.0%) remaining=0 copied_rows=64920 deleted_rows=64920 elapsed=1m49s eta=0s
- Columns have fixed widths, so successive lines line up. With the log as JSON on the console, each line is instead a
progresslog entry with the fieldsroots_done,roots_total,percent,remaining,copied_rows,deleted_rows,elapsed_secondsandeta, and, while paused,paused. - The total is an estimate.
roots, the percentage,remainingand the ETA count root rows. The total, marked with~, is the optimizer’s estimate of thewhererange, read once after recovery; nothing is counted, so--progressadds no pass over the source. It is close when an index serves thewhere, and can be far off in either direction when thewherefilters each row with a subquery or a function. - Limits: the percentage caps at 100 and
remainingat zero. The ETA showscalculatinguntil a root is done andunknownpast the estimate, and a run that finishes shows its done count as the total.dry-runcounts the range exactly. - If the estimate cannot be read, the run fails before its first batch (
engine: --progress estimate on <table>: β¦). Run without--progressto proceed. - The final line: once the first batch has started, one final line is printed on every exit, and a run that ends naturally shows
remaining=0. A run that stops or fails during startup or recovery prints no progress line.
The closing block
With --progress, a run ends with a closing block on stdout:
Job archive_old_orders (archive): completed in 109.412s
roots: 12000 in 12 batches
table copied deleted verified (sha256)
orders 12000 12000 12000
order_items 40920 40920 40920
order_payments 12480 12480 12480
The status is completed, stopped before the end of the where range: run the job again to continue, or failed, with the error on stderr. Purge shows deleted, copy-only copied and verified; under verification: none there is no verified column. Recovered roots, skipped roots and accepted conversions are listed under roots.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Done: the run exhausted the where range, or validate, dry-run, plan, list-jobs or version printed its result |
| 1 | Failed: a check refused, a stopped job’s unfinished work holds this run’s tables, or the run failed part way. Read stderr and the log |
| 2 | Usage or configuration error, found before anything connected: a flag, the configuration file, an unknown job |
| 3 | Stopped before the end of the where range, without error (a graceful stop): the next run continues |
| 4 | Not started: another live run holds the job, a source table, or work on the same data, or is still creating a new tracking schema. Nothing was done |
A stop that meets an error exits 1. In a scheduled script:
goarchive archive -c archiver.yaml --job archive_old_orders
case $? in
0|3) ;; # done, or stopped: the next run continues
4) exit 0 ;; # another run holds the work: try later
*) exit 1 ;; # failed or misused: read stderr and the log
esac
Containers
Keep the default logging, JSON to stdout, and the container’s log stream carries the run with no file or mount. A foreground docker run returns GoArchive’s exit code. For a detached container, the code is the number docker wait <name> prints. docker stop sends SIGTERM, a graceful stop: the batch in flight finishes and the run exits 3, if it gets there before the stop deadline (10 seconds by default; then the process is killed, and the next run recovers what the log holds). Set docker stop --time, or stop_grace_period in Compose, above one batch’s duration. See Installation
for the image’s user and mounts.
