Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func New ¶
New builds a slog.Logger whose handler writes to os.Stderr via a SwappableWriter. The default constructor is preserved for callers that don't need the swap surface.
func Recover ¶ added in v0.3.8
Recover is a deferred panic guard for long-lived goroutines. Installed as `defer log.Recover(logger, "component", onPanic)`, it converts a panic — which would otherwise crash the entire process with only a stderr stack trace, leaving operators with a log that simply stops mid-line (issue #492) — into a logged ERROR carrying the recovered value and the goroutine stack.
onPanic is optional. When non-nil it is called with the recovered error so the caller can escalate (e.g. the daemon records a fatal error and cancels its run context for a clean, logged shutdown). When nil the goroutine simply unwinds: its other deferred calls still run (e.g. closing an output channel), so a panicked IQ/stream worker surfaces downstream as a logged, recoverable stream-closed event instead of a silent process death.
Types ¶
type EventLog ¶ added in v0.5.1
type EventLog struct {
// contains filtered or unexported fields
}
EventLog writes every bus event to a newline-delimited JSON (JSONL / NDJSON) file — one self-contained JSON object per line — so an operator can record a full session for offline inspection (and hand it to support / Claude). Unlike the human-readable MessageLog it captures ALL event kinds, not just the trunking subset, in the same envelope the SSE/WS streams emit. The file rotates to "<path>.1" when it exceeds the configured size cap.
func NewEventLog ¶ added in v0.5.1
func NewEventLog(opts EventLogOptions) (*EventLog, error)
NewEventLog opens the log file and subscribes to the bus.
type EventLogOptions ¶ added in v0.5.1
type EventLogOptions struct {
Bus *events.Bus
// Path is the log file path. Required.
Path string
// MaxSizeMB caps the file size before rotation. Default 16.
MaxSizeMB int
// Encode renders one event to a single JSON line's worth of bytes (without
// the trailing newline). Optional: when nil a minimal {kind,timestamp,
// payload} envelope is used. The daemon injects the api package's wire
// encoder so the file matches the live SSE/WS stream byte-for-byte.
Encode func(events.Event) ([]byte, error)
}
EventLogOptions configure an EventLog.
type MessageLog ¶ added in v0.1.9
type MessageLog struct {
// contains filtered or unexported fields
}
MessageLog writes a human-readable, per-event decoded-message log — the GopherTrunk analogue of SDRtrunk's per-channel decoded message log. It subscribes to the events bus and appends one timestamped line per trunking event (grants, control-channel lock/loss, affiliations, registrations, patches, talker aliases, locations, tone alerts, decode errors). The file rotates to "<path>.1" when it exceeds the configured size cap.
func NewMessageLog ¶ added in v0.1.9
func NewMessageLog(opts MessageLogOptions) (*MessageLog, error)
NewMessageLog opens the log file and subscribes to the bus.
func (*MessageLog) Close ¶ added in v0.1.9
func (m *MessageLog) Close() error
Close releases the bus subscription, waits for Run to drain, and closes the file.
type MessageLogOptions ¶ added in v0.1.9
type MessageLogOptions struct {
Bus *events.Bus
// Path is the log file path. Required.
Path string
// MaxSizeMB caps the file size before rotation. Default 16.
MaxSizeMB int
// Loc is the timezone displayed timestamps are rendered in. Nil means
// time.Local — the operator's wall-clock time (the daemon passes
// cfg.Display.Location()).
Loc *time.Location
}
MessageLogOptions configure a MessageLog.
type PowerLog ¶ added in v0.5.0
type PowerLog struct {
// contains filtered or unexported fields
}
PowerLog writes a per-channel IQ-signal-level log gated on decode activity. It subscribes to the events bus and appends one timestamped line per KindChannelPower event — the wideband engine (internal/scanner/widebandt2) emits one such event per diagnostics window for each channel that decoded at least one frame that window, so idle / off-band channels never appear. By default only low-power windows are written (the "decoding but signal is weak" diagnostic the branch is named for); AllWindows opts into a full per-window power time-series. The file rotates to "<path>.1" when it exceeds the configured size cap, mirroring MessageLog.
func NewPowerLog ¶ added in v0.5.0
func NewPowerLog(opts PowerLogOptions) (*PowerLog, error)
NewPowerLog opens the log file and subscribes to the bus.
type PowerLogOptions ¶ added in v0.5.0
type PowerLogOptions struct {
Bus *events.Bus
// Path is the log file path. Required.
Path string
// MaxSizeMB caps the file size before rotation. Default 16.
MaxSizeMB int
// AllWindows, when true, logs every decode-active window. When false
// (default) only windows whose IQ power is below the low-power
// threshold are written.
AllWindows bool
// Loc is the timezone displayed timestamps are rendered in. Nil means
// time.Local (the daemon passes cfg.Display.Location()).
Loc *time.Location
}
PowerLogOptions configure a PowerLog.
type SwappableWriter ¶ added in v0.1.5
type SwappableWriter struct {
// contains filtered or unexported fields
}
SwappableWriter is an io.Writer that can be redirected to a different target at runtime without re-wiring the slog handler. The daemon installs one as the slog sink at startup; the launcher redirects it to a tempfile while the in-process TUI owns the terminal, then restores it on exit so headless mode keeps stderr.
func NewSwappableWriter ¶ added in v0.1.5
func NewSwappableWriter(w io.Writer) *SwappableWriter
NewSwappableWriter returns a SwappableWriter pointed at w.
func NewWithSwap ¶ added in v0.1.5
func NewWithSwap(level, format string) (*slog.Logger, *SwappableWriter)
NewWithSwap is the variant used by main: it returns both the slog Logger and the SwappableWriter behind its handler, so the launcher can redirect stderr while the TUI runs.
func (*SwappableWriter) Redirect ¶ added in v0.1.5
func (s *SwappableWriter) Redirect(w io.Writer)
Redirect replaces the active target. The previous target is remembered so Restore can reinstate it.
func (*SwappableWriter) Restore ¶ added in v0.1.5
func (s *SwappableWriter) Restore()
Restore reverts to the writer that was active before the most recent Redirect. No-op when nothing was saved.