// Package logger provides structured logging using stdlib log/slog. // // JSON output always, one format for every environment, TTY or not. A // log line is a record to be queried, not prose to be read. package logger import ( "fmt" "io" "log/slog" "path/filepath" ) // New returns a JSON logger writing to out, at debug level when debug is // set and at info level otherwise. func New(out io.Writer, debug bool) *slog.Logger { level := slog.LevelInfo if debug { level = slog.LevelDebug } // replaceAttr simplifies the source attribute to "file.go:line". replaceAttr := func(_ []string, a slog.Attr) slog.Attr { if a.Key == slog.SourceKey { if src, ok := a.Value.Any().(*slog.Source); ok { a.Value = slog.StringValue( fmt.Sprintf("%s:%d", filepath.Base(src.File), src.Line), ) } } return a } return slog.New(slog.NewJSONHandler(out, &slog.HandlerOptions{ Level: level, AddSource: true, ReplaceAttr: replaceAttr, })) }