Documentation
¶
Overview ¶
Package logbuffer persists graywolf's slog records to a bounded circular buffer in a standalone SQLite database (graywolf-logs.db).
It is wired in cmd/graywolf/main.go as a slog.Handler that wraps the existing console TextHandler: every record continues to print to the console at the operator's selected level (INFO, or DEBUG with -debug), and is also persisted at DEBUG level so a later "graywolf flare" submission can attach recent history regardless of how the operator configured the console.
The DB lives in a separate file from the main configstore to avoid write contention on the main app DB; on Raspberry Pi / SD-card-rooted systems the file is placed on tmpfs to avoid SD-card wear.
Design: .context/2026-04-25-graywolf-flare-system-design.md
§ "Subsystem 1 — Circular Log Persistence".
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BackingDeviceFor ¶
BackingDeviceFor exposes backingDeviceForPath under an exported name.
func IsRamdiskPath ¶
IsRamdiskPath reports whether p was placed under one of the tmpfs candidates ResolvePath tries (i.e. /run/graywolf or /dev/shm/graywolf). Used by cmd/graywolf to detect a "wanted ramdisk but fell back to disk" outcome and surface the spec-required WARN. Kept here so the candidate list stays the single source of truth.
func IsRaspberryPiHost ¶
func IsRaspberryPiHost() bool
IsRaspberryPiHost is the production-default wrapper around isRaspberryPi that reads /sys/firmware/devicetree/base/model. Exposed so cmd/graywolf can drive the path picker without re-implementing the detection.
func IsSDCardDevice ¶
IsSDCardDevice exposes isSDCardDevice under an exported name.
func ResolvePath ¶
func ResolvePath(opts ResolveOptions) (string, error)
ResolvePath returns the absolute path where graywolf-logs.db should live. The returned directory is NOT guaranteed to exist — Open() creates it.
Types ¶
type Config ¶
Config tunes the Handler.
RingSize is the maximum number of rows retained. <=0 disables persistence entirely (Handler still forwards to the inner handler).
MaintenanceEvery controls how often eviction runs (every Nth Handle call). 0 means "never trigger from Handle" (used by tests that drive eviction manually). Wired to 200 in production by cmd/graywolf/main.go.
type DB ¶
type DB struct {
Path string
// contains filtered or unexported fields
}
DB is the standalone graywolf-logs.db handle. It deliberately exposes no application-level methods beyond Close — the handler reaches into gorm directly so we don't carry a duplicate insert API.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler is a slog.Handler that forwards every record to an inner handler (typically the console TextHandler) and tees it to a logbuffer DB. Capture is always at DEBUG regardless of the inner handler's threshold so a future flare submission has full detail.
func (*Handler) Enabled ¶
Enabled returns true for every level >= Debug. The inner handler is asked separately inside Handle so the console keeps its configured threshold.
func (*Handler) Handle ¶
Handle forwards the record to the inner handler (subject to the inner handler's own Enabled check) and persists it to the DB at DEBUG-and-above.
type ResolveOptions ¶
type ResolveOptions struct {
// ConfigDBPath is the path the operator gave for graywolf.db. Used as
// the disk-backed fallback location (logs land in the same directory
// under graywolf-logs.db).
ConfigDBPath string
// PreferRamdisk forces ramdisk preference even on non-SD systems.
// Wired from --logbuffer-ramdisk.
PreferRamdisk bool
// IsRaspberryPi mirrors isRaspberryPi() — kept as a separate field so
// callers can override for tests and so the structured form documents
// the inputs explicitly.
IsRaspberryPi bool
// BackingIsSDCard is true when the directory holding the config DB is
// backed by an mmcblk/mtdblock device.
BackingIsSDCard bool
// WritableProbe is invoked for each candidate ramdisk directory. The
// first directory the probe accepts wins. In production this is
// defaultWritableProbe (creates and removes a temp file).
WritableProbe func(dir string) error
}
ResolveOptions are the inputs to the path picker. All fields are either CLI-flag-derived or detector outputs so the picker itself stays pure and testable.