Repository navigation
feat(local-collector): make doctor's verdict readable by a process supervisor - #84
Merged
Merged
Conversation
The `doctor` command of the local collector's command-line tool already checks four things about the machine it runs on — the local queue of records waiting to upload, records that failed repeatedly and were set aside, whether any queue entries are held by a worker that has gone away, and whether the server is reachable — and rolls them into one of `ok`, `warning`, or `critical`. But it printed that verdict inside a JSON document and always exited 0. A process supervisor such as systemd decides whether a program succeeded by reading its exit status alone, so nothing on the host could act on the collector's own diagnosis without a JSON parser in between. In practice that means a collector can be reporting `critical` on every scheduled run and no one finds out. `doctor --exit-code` exits 1 when the rollup is `critical` and 0 otherwise. The flag is opt-in rather than the new default because the existing contract is "print JSON on stdout, exit 0", and callers that already parse that output would start seeing a failure status for a document they were reading successfully. `compact` in the same file established this idiom when it made a refused reclaim exit non-zero, so the two scriptable commands now behave alike. Only `critical` exits non-zero. The `warning` conditions are ones the next scheduled run clears on its own — an expired queue lease, a missing database, a coverage gap — so treating them as failure would make a supervisor flap on states that are already resolving. That is the same reasoning the existing rollup uses to keep them out of `critical`. The mapping is a separate exported function rather than an inline comparison so a test can pin all three severities without invoking the command-line entry point. The systemd documentation gains a section on pairing this with `OnFailure=`, a directive that runs another unit when one fails, to raise a local desktop notification. It is labelled explicitly as a local-visibility aid and not a liveness answer: `OnFailure=` requires the unit to have run and exited non-zero on a host whose service manager is up and whose desktop session is present. It covers none of the cases — timer stopped, host powered off, person elsewhere — where the collector goes quiet and only a server can notice. Verified with the package's own test runner: 11 of 11 doctor tests pass, including three new ones covering the flag parsing, the severity mapping across all three values, and a real dead-lettered outbox exiting non-zero. The six tests that parse the documented systemd unit still pass, so the new documentation section did not disturb the block they read. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
On a source's detail page, each device source instance carries a link to the device exporters page — where an owner goes to see whether a collector is still running. The link's visible text was the raw `device_id`, a generated identifier with no meaning to a reader. That is worst exactly where the link matters most. A reader who has just seen the heartbeat line above it report a stale check-in has no way to tell that the opaque string underneath is how to go look at the machine. The link now reads "View this device". The device id moves to the link's tooltip and stays in the URL fragment, which is what scrolls the target page to the right row, so nothing about where the link goes changes. Verified by running the file's existing structural tests, which read this component as text and assert on the literals it contains: 41 of 41 pass. None of them pinned the previous link text. Assisted-by: AI Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A local collector — a one-shot program that uploads a machine's data on a timer, started by a process supervisor such as systemd — can be reporting that it is in trouble on every scheduled run without anything on the host noticing.
Its command-line tool already has a
doctorcommand that checks four things about the machine it runs on: the local queue of records waiting to upload, records that failed repeatedly and were set aside for an operator, whether any queue entries are held by a worker that has gone away, and whether the server is reachable. It rolls those into one ofok,warning, orcritical. But it printed that verdict inside a JSON document and always exited 0, and a process supervisor decides whether a program succeeded by reading its exit status alone. So the collector's own diagnosis was unreadable by the only thing watching it, unless a person ran the command by hand and read the output.doctor --exit-codeexits 1 when the rollup iscriticaland 0 otherwise. A supervisor can then act on it — the systemd documentation in this repository gains a section on wiring it toOnFailure=, a directive that runs another unit when one fails, to raise a local desktop notification.Two choices worth explaining. The flag is opt-in rather than the new default because the existing contract is "print JSON on stdout, exit 0", and callers already parsing that output would suddenly see a failure status for a document they were reading successfully. And only
criticalexits non-zero: thewarningconditions are ones the next scheduled run clears on its own — an expired queue lease, a missing database, a coverage gap — so treating them as failure would make a supervisor flap on states that are already resolving. That is the same reasoning the existing rollup uses to keep them out ofcritical.This also renames one piece of console text. On a source's detail page each device carries a link to the device exporters page, and the link's visible text was the raw device identifier — a generated string with no meaning to a reader, which is worst exactly where the link matters most, next to a line saying the collector stopped checking in. It now reads "View this device", with the identifier moved to the tooltip and left in the URL fragment that scrolls the target page to the right row.
What this does not do
It does not detect a collector that has stopped running.
OnFailure=requires the program to have run and exited non-zero, on a host whose service manager is up and whose desktop session is present to show a notification. It covers none of the cases — timer stopped firing, host powered off, person working elsewhere — where a collector goes quiet and only the server can notice. The documentation says so in place, because that limit is easy to mistake for a liveness answer. Server-side silence detection is separate work, in #74.Verifying it
Eleven of eleven
doctortests pass in the local collector package, including three new ones: the flag is parsed and stays off by default, the severity mapping is pinned across all three values, and a real dead-lettered outbox produces a non-zero status. The mapping is a separate exported function rather than an inline comparison so it can be tested without invoking the command-line entry point.Six tests parse the systemd unit documented in this repository and assert on the directives it declares; they still pass, so the new documentation section did not disturb the block they read. The console change is covered by that file's existing structural tests, which read the component as text and assert on its literals: 41 of 41 pass, and none pinned the previous link text.
Assisted-by: AI