Documentation
¶
Overview ¶
Package logger provides a thin wrapper around log/slog that:
- injects a trace_id into every record (via a pluggable TraceIDFn),
- tags records with the service name,
- exposes context-aware Debug/Info/Warn/Error methods,
- supports fanning records out to multiple sinks by level (see FanoutHandler), e.g. everything to stdout and ERROR+ to Sentry.
The same *Logger is meant to be used everywhere: HTTP/gRPC handlers, business code, and background workers.
Index ¶
- Constants
- type Config
- type FanoutHandler
- type Level
- type Logger
- func (l *Logger) Debug(ctx context.Context, msg string, args ...any)
- func (l *Logger) Error(ctx context.Context, msg string, args ...any)
- func (l *Logger) Handler() slog.Handler
- func (l *Logger) Info(ctx context.Context, msg string, args ...any)
- func (l *Logger) Named(name string) *Logger
- func (l *Logger) Slog() *slog.Logger
- func (l *Logger) Warn(ctx context.Context, msg string, args ...any)
- func (l *Logger) With(args ...any) *Logger
- type TraceIDFn
Constants ¶
const ( LevelDebug = slog.LevelDebug LevelInfo = slog.LevelInfo LevelWarn = slog.LevelWarn LevelError = slog.LevelError )
Log levels, re-exported from slog for convenience.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// Service tags every record with this name (attribute "service").
Service string
// Level is the minimum level handled.
Level Level
// AddSource attaches a "source" attribute (file:line) to records.
AddSource bool
// TraceIDFn injects "trace_id"; may be nil.
TraceIDFn TraceIDFn
}
Config configures a Logger.
type FanoutHandler ¶
type FanoutHandler struct {
// contains filtered or unexported fields
}
FanoutHandler dispatches each record to every wrapped handler whose own Enabled check passes. This lets you, for example, send all records to a stdout JSON handler while also forwarding ERROR+ records to a Sentry handler.
stdout := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: LevelInfo})
h := logger.NewFanout(stdout, sentryHandler) // sentryHandler.Enabled gates ERROR+
log := logger.NewWithHandler(h, logger.Config{Service: "svc", TraceIDFn: otel.GetTraceID})
func NewFanout ¶
func NewFanout(handlers ...slog.Handler) *FanoutHandler
NewFanout builds a FanoutHandler over the given handlers (nil handlers are skipped). Per-sink level filtering is the responsibility of each handler.
func (*FanoutHandler) Enabled ¶
Enabled reports whether any wrapped handler is enabled for the level.
func (*FanoutHandler) Handle ¶
Handle forwards the record to every wrapped handler that is enabled for it.
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger is the application logger.
func New ¶
New builds a Logger writing JSON to w. For multi-sink behavior, build the Logger with NewWithHandler and a FanoutHandler instead.
func NewWithHandler ¶
NewWithHandler builds a Logger from a custom slog.Handler (e.g. a FanoutHandler). The service attribute and TraceIDFn from cfg are applied.
Trace-id injection is installed as a handler wrapper (not in the Logger's write path), so it also applies to any *slog.Logger derived via Slog() and to third-party middleware that logs through the same handler (e.g. httplog).
func (*Logger) Handler ¶
Handler returns the underlying slog.Handler, so callers can build a stdlib *slog.Logger that shares the same sink and formatting.
func (*Logger) Named ¶
Named returns a child Logger tagged with logger=name. Use it to derive purpose-specific instances (e.g. an access logger, a worker logger) that share the same underlying handler — so output, level, and any multi-sink fan-out (stdout + Sentry, ...) stay unified — while remaining distinguishable in the logs. This is the intended way to have several logger instances without proliferating handlers/config.