Documentation
¶
Overview ¶
Package exitrecord persists why systemd last stopped a miren daemon, so the next run can tell the user about it.
The information only exists for an instant. systemd exposes the reason a unit stopped as the unit's Result property, and resets it to "success" as soon as the replacement instance activates — so a process that looks at its own unit during startup always sees a healthy unit, however violently its predecessor died. The one place the reason is readable is an ExecStopPost hook, which runs after the main process is gone and has SERVICE_RESULT in its environment.
So the hook writes a record here, and the next boot reads it. Without this, a server killed for exceeding its memory limit comes back up with no idea that it ever went down, and neither does the operator.
Index ¶
Constants ¶
const ( // FileName holds an exit that has not yet been reported. FileName = "last-exit.json" // ReportedFileName holds one that has. Renaming rather than deleting keeps // the detail available for later diagnosis while making sure the warning is // logged once per occurrence instead of on every boot. ReportedFileName = "last-exit.reported.json" // ResultSuccess is systemd's SERVICE_RESULT for a clean stop. ResultSuccess = "success" // ResultOOMKill is systemd's SERVICE_RESULT when the kernel's out-of-memory // killer took a process in the unit's cgroup. ResultOOMKill = "oom-kill" )
Variables ¶
This section is empty.
Functions ¶
func Clear ¶
Clear removes any stored record. Called after a clean stop, so the file's presence always means the previous run ended badly.
func MarkReported ¶
MarkReported moves the record aside once it has been surfaced to the user.
Types ¶
type Record ¶
type Record struct {
At time.Time `json:"at"`
Unit string `json:"unit"`
// Result is systemd's SERVICE_RESULT, e.g. "oom-kill", "signal",
// "exit-code", "timeout".
Result string `json:"result"`
// ExitCode is systemd's EXIT_CODE: "exited", "killed" or "dumped".
ExitCode string `json:"exit_code,omitempty"`
// ExitStatus is the numeric status or signal that goes with ExitCode.
ExitStatus string `json:"exit_status,omitempty"`
// MemoryPeak is the highest memory the unit's cgroup reached, and MemoryMax
// the limit it was held to. Both are 0 when systemd didn't report them —
// MemoryPeak needs systemd 254 or newer, and MemoryMax reads as "infinity"
// when no limit is set.
MemoryPeak int64 `json:"memory_peak,omitempty"`
MemoryMax int64 `json:"memory_max,omitempty"`
// Restarts is the unit's NRestarts counter at the time of the exit.
Restarts int `json:"restarts,omitempty"`
}
Record is one abnormal exit of a miren daemon.
func Read ¶
Read returns the unreported record in dir. The boolean is false when there isn't one, which is the ordinary case: nothing went wrong last time.
func (Record) LogTo ¶
LogTo writes the record as a single warning.
Warn rather than Error: the platform did its job. The control process was contained and restarted instead of taking the host down with it, and an Error here would page someone about a system that worked as designed.
Individual fields are named rather than logging the struct, per the log-level guidance in CLAUDE.md — "%+v" on a record renders its whole field tree inline.