Logging: structured slog messages throughout, and WithLogger options so callers choose the logger

Log messages are lower-case event names with their details as key/value
attributes ("error" for errors), in place of formatted strings.

Loggable package take a WithLogger option as part of their "New*" call,
defaulting to slog.Default(). Each tags its lines with its `component`.

Some debug loggers print directly rather than using slog when in
terminal logging mode.
This commit is contained in:
bwilliams committed 2026-10-15 16:10:52 +01:00
1 parent 0b5fde9563
commit 043e307663
49 files changed
+598 -248

No files matched your search

+9 -2
View File
@@ -36,6 +36,9 @@ type Worker struct {
ShutdownTimeout time.Duration
// Task is the work to perform on each tick.
Task Task
// Logger is what the worker logs to; nil means slog.Default(), looked up
// when Run starts.
Logger *slog.Logger
}
// Run executes Task immediately, then once per Interval, until ctx is
@@ -55,7 +58,11 @@ func (w Worker) Run(ctx context.Context, since time.Time) error {
timeout = DefaultWorkerShutdownTimeout
}
logger := slog.With("source", w.Name)
logger := w.Logger
if logger == nil {
logger = slog.Default()
}
logger = logger.With("source", w.Name)
logger.Info("starting worker", "since", since, "interval", w.Interval)
// workCtx is NOT cancelled immediately when ctx is. It gives an in-flight
@@ -123,7 +130,7 @@ func (w Worker) execute(
logger.Warn("task cancelled", "elapsed", elapsed)
return since
default:
logger.Error("task failed", "err", err, "elapsed", elapsed)
logger.Error("task failed", "error", err, "elapsed", elapsed)
return since
}
}