Handlers, formatters, and helpers for Go's log/slog. The missing batteries
go get github.com/philiprehberger/go-slogutilHandlers, formatters, and helpers for Go's log/slog. The missing batteries
go get github.com/philiprehberger/go-slogutil
import "github.com/philiprehberger/go-slogutil"
logger := slog.New(slogutil.PrettyHandler(os.Stderr, &slogutil.PrettyHandlerOptions{
Level: slog.LevelDebug,
TimeFormat: time.DateTime,
}))
logger.Info("server started", "port", 8080)
// Output: 2026-03-15 10:30:00 INFO server started port=8080
console := slogutil.PrettyHandler(os.Stderr, nil)
file := slog.NewJSONHandler(logFile, nil)
logger := slog.New(slogutil.Multi(console, file))
logger.Info("logged to both console and file")
stdout := slog.NewTextHandler(os.Stdout, nil)
stderr := slog.NewTextHandler(os.Stderr, nil)
logger := slog.New(slogutil.LevelRoute(map[slog.Level]slog.Handler{
slog.LevelInfo: stdout,
slog.LevelError: stderr,
}))
logger.Info("goes to stdout")
logger.Error("goes to stderr")
// Log only 1 in every 100 info messages (errors are always logged).
h := slogutil.Sampling(slog.NewJSONHandler(os.Stdout, nil), 100)
logger := slog.New(h)
logger.Info("request handled",
slogutil.Duration(elapsed),
slogutil.HTTPRequest(r),
slogutil.HTTPStatus(200),
slogutil.TraceID("abc-123"),
)
if err != nil {
logger.Error("failed", slogutil.Error(err))
}
import slogutil "github.com/philiprehberger/go-slogutil"
logger.Info("query complete",
slogutil.Database("users", "localhost", 5432),
slogutil.UserID("user-123"),
slogutil.RequestID("req-abc"),
slogutil.Latency(42 * time.Millisecond),
)
| Function / Type | Description |
|---|---|
PrettyHandler(w, opts) | Colorized console handler for development |
PrettyHandlerOptions | Options: Level, TimeFormat |
Multi(handlers...) | Fan-out to multiple handlers |
LevelRoute(routes) | Route records by level to different handlers |
Sampling(handler, rate) | Log 1 in every N records (errors always pass) |
Duration(d) | Formatted duration attr |
Error(err) | Error attr with "error" key |
HTTPRequest(r) | Group attr with method, path, remote_addr |
HTTPStatus(code) | Status code attr |
TraceID(id) | Trace ID attr |
Stringer(key, v) | Attr from any fmt.Stringer |
Database(name, host, port) | Group attr with database connection details |
UserID(id) | User identifier attr |
RequestID(id) | Request identifier attr |
Latency(d) | Latency in milliseconds attr |
go test ./...
go vet ./...
If you find this project useful: