logging

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 7 Imported by: 0

README

logging

import "github.com/brpaz/lib-go/logging"

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

func TraceIDFromContext(ctx context.Context) string

TraceIDFromContext returns the OTEL trace ID from the active span in ctx. Returns an empty string when no active span is present.

func WithContext

func WithContext(ctx context.Context, l *Logger) context.Context

WithContext returns a copy of ctx carrying l.

type Format

Format controls the log output encoding.

type Format string

const (
    FormatJSON Format = "json"
    FormatText Format = "text"
)

type Logger

Logger is a structured logger backed by log/slog.

type Logger struct {
    // contains filtered or unexported fields
}

func FromContext
func FromContext(ctx context.Context) *Logger

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
func NewLogger(opts ...Option) (*Logger, error)

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) Debug
func (l *Logger) Debug(ctx context.Context, msg string, args ...any)

Debug logs at DEBUG level.

func (*Logger) Error
func (l *Logger) Error(ctx context.Context, msg string, args ...any)

Error logs at ERROR level.

func (*Logger) GetLevel
func (l *Logger) GetLevel() slog.Level

GetLevel returns the current log level.

func (*Logger) Info
func (l *Logger) Info(ctx context.Context, msg string, args ...any)

Info logs at INFO level.

func (*Logger) LevelVar
func (l *Logger) LevelVar() *slog.LevelVar

LevelVar returns the runtime-mutable level variable.

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) SetLevel
func (l *Logger) SetLevel(level slog.Level)

SetLevel changes the active log level at runtime.

func (*Logger) Slog
func (l *Logger) Slog() *slog.Logger

Slog returns the underlying [slog.Logger] for interoperability.

func (*Logger) Warn
func (l *Logger) Warn(ctx context.Context, msg string, args ...any)

Warn logs at WARN level.

func (*Logger) With
func (l *Logger) With(args ...any) *Logger

With returns a new Logger pre-populated with the given attributes. The new logger shares the same [slog.LevelVar] as the parent, so a level change on either propagates to both.

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.

type Middleware func(slog.Handler) slog.Handler

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

Option configures a Logger.

type Option func(*config)

func WithAttrs
func WithAttrs(attrs ...slog.Attr) Option

WithAttrs appends global attributes added to every log record.

func WithEnvironment
func WithEnvironment(v string) Option

WithEnvironment sets the "environment" global attribute (e.g. "production").

func WithFormat
func WithFormat(f Format) Option

WithFormat sets the log output format.

func WithLevel
func WithLevel(l string) Option

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
func WithOutput(w io.Writer) Option

WithOutput sets the writer for log output. Defaults to os.Stdout.

func WithRevision
func WithRevision(v string) Option

WithRevision sets the "revision" global attribute (e.g. a git commit hash).

func WithVersion
func WithVersion(v string) Option

WithVersion sets the "version" global attribute.

Generated by gomarkdoc

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

Constants

This section is empty.

Variables

This section is empty.

Functions

func TraceIDFromContext

func TraceIDFromContext(ctx context.Context) string

TraceIDFromContext returns the OTEL trace ID from the active span in ctx. Returns an empty string when no active span is present.

func WithContext

func WithContext(ctx context.Context, l *Logger) context.Context

WithContext returns a copy of ctx carrying l.

Types

type Format

type Format string

Format controls the log output encoding.

const (
	FormatJSON Format = "json"
	FormatText Format = "text"
)

type Logger

type Logger struct {
	// contains filtered or unexported fields
}

Logger is a structured logger backed by log/slog.

func FromContext

func FromContext(ctx context.Context) *Logger

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

func NewLogger(opts ...Option) (*Logger, error)

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) Debug

func (l *Logger) Debug(ctx context.Context, msg string, args ...any)

Debug logs at DEBUG level.

func (*Logger) Error

func (l *Logger) Error(ctx context.Context, msg string, args ...any)

Error logs at ERROR level.

func (*Logger) GetLevel

func (l *Logger) GetLevel() slog.Level

GetLevel returns the current log level.

func (*Logger) Info

func (l *Logger) Info(ctx context.Context, msg string, args ...any)

Info logs at INFO level.

func (*Logger) LevelVar

func (l *Logger) LevelVar() *slog.LevelVar

LevelVar returns the runtime-mutable level variable.

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) SetLevel

func (l *Logger) SetLevel(level slog.Level)

SetLevel changes the active log level at runtime.

func (*Logger) Slog

func (l *Logger) Slog() *slog.Logger

Slog returns the underlying slog.Logger for interoperability.

func (*Logger) Warn

func (l *Logger) Warn(ctx context.Context, msg string, args ...any)

Warn logs at WARN level.

func (*Logger) With

func (l *Logger) With(args ...any) *Logger

With returns a new Logger pre-populated with the given attributes. The new logger shares the same slog.LevelVar as the parent, so a level change on either propagates to both.

type Middleware

type Middleware func(slog.Handler) slog.Handler

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 WithAttrs

func WithAttrs(attrs ...slog.Attr) Option

WithAttrs appends global attributes added to every log record.

func WithEnvironment

func WithEnvironment(v string) Option

WithEnvironment sets the "environment" global attribute (e.g. "production").

func WithFormat

func WithFormat(f Format) Option

WithFormat sets the log output format.

func WithLevel

func WithLevel(l string) Option

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

func WithOutput(w io.Writer) Option

WithOutput sets the writer for log output. Defaults to os.Stdout.

func WithRevision

func WithRevision(v string) Option

WithRevision sets the "revision" global attribute (e.g. a git commit hash).

func WithVersion

func WithVersion(v string) Option

WithVersion sets the "version" global attribute.

Directories

Path Synopsis
Package logtest provides test helpers for the log package.
Package logtest provides test helpers for the log package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL