Documentation
¶
Overview ¶
Package logging provides a structured logger built on log/slog with support for OpenTelemetry trace/span injection, runtime level control, and a middleware chain for application-specific attribute injection.
Construction ¶
Create a logger once at application startup using functional options:
logger, err := logging.NewLogger(
logging.WithEnvironment("production"),
logging.WithFormat(logging.FormatJSON),
logging.WithVersion("1.8.0"),
logging.WithRevision("a1b2c3d4"),
logging.WithLevel("info"),
logging.WithMiddleware(logging.OtelMiddleware()),
)
The returned Logger exposes Logger.SetLevel and Logger.GetLevel to change the active log level at runtime without restarting the process:
logger.SetLevel(slog.LevelDebug)
Logging ¶
Every method accepts a context.Context so middlewares can extract request-scoped values (trace IDs, user IDs, etc.) automatically:
logger.Info(ctx, "user authenticated", slog.String("user_id", id))
logger.Error(ctx, "payment failed", slog.Any("error", err))
Middleware ¶
Use WithMiddleware to inject application-specific attributes on every log call. A middleware receives the slog.Handler it wraps and the context on each Handle call, making it ideal for pulling values out of ctx:
func UserIDMiddleware(next slog.Handler) logging.Middleware {
return func(next slog.Handler) slog.Handler {
return &userIDHandler{Handler: next}
}
}
Pass one or more middlewares at construction time:
logging.NewLogger( logging.WithMiddleware( logging.OtelMiddleware(), UserIDMiddleware, ), )
Extending with static attributes ¶
Use Logger.With to derive a child logger pre-populated with extra fields. Call it at the request boundary and pass the enriched logger down:
reqLogger := logger.With(slog.String("request_id", id))
reqLogger.Info(ctx, "request started")
Context propagation ¶
Store and retrieve a logger from a context.Context:
ctx = logging.WithContext(ctx, logger) logging.FromContext(ctx).Info(ctx, "retrieved from context")
FromContext returns a no-op logger when none is stored, so callers never need to nil-check.
Index ¶
- func TraceIDFromContext(ctx context.Context) string
- func WithContext(ctx context.Context, l *Logger) context.Context
- type Format
- 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) GetLevel() slog.Level
- func (l *Logger) Info(ctx context.Context, msg string, args ...any)
- func (l *Logger) LevelVar() *slog.LevelVar
- func (l *Logger) SetAsDefault()
- func (l *Logger) SetLevel(level slog.Level)
- 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 Middleware
- type Option
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func TraceIDFromContext ¶
TraceIDFromContext returns the OTEL trace ID from the active span in ctx. Returns an empty string when no active span is present.
Types ¶
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger is a structured logger backed by log/slog.
func FromContext ¶
FromContext retrieves the Logger stored in ctx. If none is found it returns a no-op Logger so callers never need to nil-check.
func NewLogger ¶
NewLogger constructs a Logger with the provided options. The logger includes an OTel handler that injects trace_id and span_id from the context on every log call.
func NewNoopLogger ¶
func NewNoopLogger() *Logger
NewNoopLogger returns a Logger that discards all output. Useful in tests for components that require a Logger but produce no assertions on logs.
func (*Logger) SetAsDefault ¶
func (l *Logger) SetAsDefault()
SetAsDefault installs this logger as the global slog default. After this call, package-level slog functions (slog.Info, slog.Error, …) and legacy log.Print calls route through this logger's handler. Call this once at the application wiring layer — never in library code.
func (*Logger) Slog ¶
Slog returns the underlying slog.Logger for interoperability.
type Middleware ¶
Middleware wraps an slog.Handler to inject additional attributes. Middlewares receive the context on every log call, making them suitable for extracting request-scoped values (e.g. user_id, tenant_id) from ctx.
func OtelMiddleware ¶
func OtelMiddleware() Middleware
OtelMiddleware returns a Middleware that injects trace_id and span_id from the active OpenTelemetry span into every log record. Add it via WithMiddleware when your application uses OpenTelemetry tracing.
type Option ¶
type Option func(*config)
Option configures a Logger.
func WithEnvironment ¶
WithEnvironment sets the "environment" global attribute (e.g. "production").
func WithLevel ¶
WithLevel sets the initial log level as a string ("debug", "info", "warn", "error").
func WithMiddleware ¶
func WithMiddleware(m ...Middleware) Option
WithMiddleware appends one or more handler middlewares to the chain. Middlewares are applied in order after the built-in OTel handler, so they receive a context on every Handle call and can inject attrs derived from it.
func WithOutput ¶
WithOutput sets the writer for log output. Defaults to os.Stdout.
func WithRevision ¶
WithRevision sets the "revision" global attribute (e.g. a git commit hash).
func WithVersion ¶
WithVersion sets the "version" global attribute.