slogsafe

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 14 Imported by: 0

README

slogsafe

CI Go Reference

Enterprise-grade structured logging for Go, built on log/slog. Evolves slogx with OpenTelemetry correlation, stack traces on errors, and high-performance object dumping via saferefl.

Features

  • Runtime configuration — change level, format (JSON/Text), masking, and removal without restart
  • OpenTelemetry — automatic trace_id, span_id, and trace_sampled from context.Context
  • Stack traces — optional stack attachment on Error and Fatal records
  • Data redaction — email, phone, card, secret masking and key removal
  • Typed context keys — collision-safe ContextKey for request/user/tenant IDs
  • Fast dumping — struct serialization via saferefl (depth limits, cycles, field caps)
  • Payload helpers — sanitized HTTP and gRPC request/response snapshots

Install

go get github.com/glaciforge/slogsafe

Quick start

package main

import (
    "context"
    "log/slog"

    "github.com/glaciforge/slogsafe"
)

func main() {
    log := slogsafe.New(
        slogsafe.WithFormat(slogsafe.FormatJSON),
        slogsafe.WithTraceContext(true),
        slogsafe.WithStackOnError(true),
        slogsafe.WithContextKeys(slogsafe.KeyRequestID),
        slogsafe.WithMaskRules(
            slogsafe.NewMaskRules().Add("email", slogsafe.MaskEmail),
        ),
    )
    slog.SetDefault(log.Logger)

    ctx := slogsafe.WithValue(context.Background(), slogsafe.KeyRequestID, "req-1")
    log.InfoContext(ctx, "started", slog.String("email", "user@example.com"))
}

Presets

log := slogsafe.Default() // JSON, Info, OTel, stack on error, source lines
log := slogsafe.Dev()     // Text, Debug, OTel, stack on error

Examples

Runnable examples live under examples/:

Example What it shows
examples/basic/ levels, formats, Err, NewNop
examples/masking/ email/phone/card/secret masking + removal
examples/context/ typed context keys, ToContext / FromContext
examples/tracing/ OpenTelemetry trace_id / span_id injection
examples/stack/ AddSource, stack on Error/Fatal, WithExitFunc
examples/dump/ Dump / DumpGroup via saferefl
examples/http_payload/ sanitized HTTP request/response dumps
examples/grpc_payload/ sanitized gRPC call/response/stream dumps
examples/runtime_config/ UpdateConfig / SetLevel hot reload
examples/presets/ Default, Dev, MustDefault
go run ./examples/basic/
go run ./examples/tracing/
go run ./examples/dump/
make examples

Dumping

log.Info("payload",
    slogsafe.DumpWith(log, "user", user),
)

HTTP / gRPC payloads

log.Info("http", slogsafe.HTTPRequestWith(log, "request", req))
log.Info("grpc", slogsafe.GRPCCallWith(log, "call", "/svc.Method", body, md))

Sensitive headers (Authorization, Cookie, …) are redacted automatically. HTTPRequestWith restores http.Request.Body for downstream handlers.

Runtime config

log.UpdateConfig(func(c *slogsafe.Config) {
    c.Level = slog.LevelDebug
    c.Format = slogsafe.FormatJSON
})

Development

make test
make coverage
make lint
make pre-release        # full local gate (mirrors CI)
make pre-release-quick  # skip coverage + lint

See CONTRIBUTING.md and CHANGELOG.md.

License

MIT — see LICENSE.

Documentation

Index

Constants

View Source
const (
	// LevelTrace is below slog.LevelDebug for verbose diagnostics.
	LevelTrace = slog.Level(-8)
	// LevelFatal is above slog.LevelError for unrecoverable failures.
	LevelFatal = slog.Level(12)
)

Variables

View Source
var (
	KeyRequestID = ContextKey("request_id")
	KeyUserID    = ContextKey("user_id")
	KeyTenantID  = ContextKey("tenant_id")
)

Standard context keys for enterprise services.

Functions

func Dump

func Dump(key string, v any, opts ...DumpOption) slog.Attr

Dump serializes v into a slog attribute using saferefl with cycle detection.

func DumpGroup

func DumpGroup(key string, v any, opts ...DumpOption) slog.Attr

DumpGroup wraps a serialized value as a slog group attribute.

func DumpGroupWith

func DumpGroupWith(l *Logger, key string, v any, opts ...DumpOption) slog.Attr

DumpGroupWith serializes v as a group using configuration from l when available.

func DumpWith

func DumpWith(l *Logger, key string, v any, opts ...DumpOption) slog.Attr

DumpWith serializes v using configuration from l when available.

func Err

func Err(err error) slog.Attr

Err creates a structured error attribute.

func GRPCCall

func GRPCCall(name, method string, req any, md Metadata, opts ...DumpOption) slog.Attr

GRPCCall logs a sanitized gRPC request snapshot.

func GRPCCallWith

func GRPCCallWith(l *Logger, name, method string, req any, md Metadata, opts ...DumpOption) slog.Attr

GRPCCallWith logs a sanitized gRPC request using logger dump settings.

func GRPCResponse

func GRPCResponse(name string, resp any, opts ...DumpOption) slog.Attr

GRPCResponse logs a sanitized gRPC response snapshot.

func GRPCResponseWith

func GRPCResponseWith(l *Logger, name string, resp any, opts ...DumpOption) slog.Attr

GRPCResponseWith logs a sanitized gRPC response using logger dump settings.

func GRPCStreamEvent

func GRPCStreamEvent(name, method, event string, msg any, md Metadata, opts ...DumpOption) slog.Attr

GRPCStreamEvent logs a streaming gRPC event with optional metadata.

func GRPCStreamEventWith

func GRPCStreamEventWith(l *Logger, name, method, event string, msg any, md Metadata, opts ...DumpOption) slog.Attr

GRPCStreamEventWith logs a streaming gRPC event using logger dump settings.

func HTTPRequest

func HTTPRequest(name string, r *http.Request, opts ...DumpOption) slog.Attr

HTTPRequest logs a sanitized HTTP request snapshot.

func HTTPRequestWith

func HTTPRequestWith(l *Logger, name string, r *http.Request, opts ...DumpOption) slog.Attr

HTTPRequestWith logs a sanitized HTTP request using logger dump settings.

func HTTPResponse

func HTTPResponse(name string, r *http.Response, opts ...DumpOption) slog.Attr

HTTPResponse logs a sanitized HTTP response snapshot.

func HTTPResponseWith

func HTTPResponseWith(l *Logger, name string, r *http.Response, opts ...DumpOption) slog.Attr

HTTPResponseWith logs a sanitized HTTP response using logger dump settings.

func RestoreBody

func RestoreBody(r *http.Request, body string)

RestoreBody replaces r.Body after logging so downstream handlers can still read it.

func Serialize

func Serialize(cfg Config, v any, opts ...DumpOption) any

Serialize converts v to a log-safe representation using saferefl.

func SerializeDefault

func SerializeDefault(v any, opts ...DumpOption) any

SerializeDefault uses Default dump limits and masking rules.

func SetGlobalDumpConfig

func SetGlobalDumpConfig(cfg *Config)

SetGlobalDumpConfig sets defaults used by Dump when no Logger is available.

func ToContext

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

ToContext injects a Logger into context.

func Value

func Value(ctx context.Context, key ContextKey) any

Value reads a context value by typed key.

func WithValue

func WithValue(ctx context.Context, key ContextKey, val any) context.Context

WithValue stores a log attribute source in context under a typed key.

Types

type Config

type Config struct {
	Level       slog.Level
	Format      Format
	Output      io.Writer
	MaskKeys    MaskMap
	RemoveKeys  RemoveMap
	LevelNames  LevelNames
	Masker      Masker
	ContextKeys []ContextKey

	AddSource      bool
	StackOnError   bool
	StackDepth     int
	TraceContext   bool
	TraceIDKey     string
	SpanIDKey      string
	TraceSampleKey string

	DumpMaxDepth  int
	DumpMaxFields int
}

Config holds the atomic logger configuration state.

func (*Config) Clone

func (c *Config) Clone() *Config

Clone creates a deep copy of Config for copy-on-write updates.

type ContextKey

type ContextKey string

ContextKey is a typed key for values stored in context.Context.

func (ContextKey) String

func (k ContextKey) String() string

String returns the key name used in log attributes.

type DefaultMasker

type DefaultMasker struct{}

DefaultMasker provides built-in redaction for common sensitive data types.

func (*DefaultMasker) Mask

func (m *DefaultMasker) Mask(value any, mType MaskType) any

Mask processes the input value based on the specified MaskType.

type DumpOption

type DumpOption func(*dumpOptions)

DumpOption configures Dump and payload helpers.

func WithDumpDepth

func WithDumpDepth(depth int) DumpOption

WithDumpDepth overrides the maximum recursion depth.

func WithDumpMaskKeys

func WithDumpMaskKeys(keys MaskMap) DumpOption

WithDumpMaskKeys applies masking rules during dump serialization.

func WithDumpMaxFields

func WithDumpMaxFields(n int) DumpOption

WithDumpMaxFields overrides the maximum number of fields emitted.

func WithDumpRemoval

func WithDumpRemoval(keys ...string) DumpOption

WithDumpRemoval excludes keys during dump serialization.

type DynamicHandler

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

DynamicHandler is a slog.Handler with runtime reconfiguration, OTel context injection, and stack traces on errors.

func (*DynamicHandler) Enabled

func (h *DynamicHandler) Enabled(_ context.Context, level slog.Level) bool

Enabled reports whether the record should be logged.

func (*DynamicHandler) Handle

func (h *DynamicHandler) Handle(ctx context.Context, r slog.Record) error

Handle processes a log record using a cached static handler chain.

func (*DynamicHandler) WithAttrs

func (h *DynamicHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs returns a new DynamicHandler with additional attributes.

func (*DynamicHandler) WithGroup

func (h *DynamicHandler) WithGroup(name string) slog.Handler

WithGroup returns a new DynamicHandler with an additional group.

type Format

type Format int

Format defines the output format for the logger.

const (
	// FormatText is human-readable key=value output.
	FormatText Format = iota
	// FormatJSON is structured JSON output.
	FormatJSON
)

func ParseFormat

func ParseFormat(s string) Format

ParseFormat converts a string to Format. Defaults to FormatText.

type LevelNames

type LevelNames map[slog.Level]string

LevelNames maps slog.Level values to custom string labels in log output.

type Logger

type Logger struct {
	*slog.Logger
	// contains filtered or unexported fields
}

Logger wraps slog.Logger with atomic runtime configuration updates.

func Default

func Default() *Logger

Default returns a production-ready logger: JSON, Info level, OTel, stack on error.

func Dev

func Dev() *Logger

Dev returns a text logger suitable for local development.

func FromContext

func FromContext(ctx context.Context) *Logger

FromContext extracts a Logger from context or returns a wrapper around slog.Default().

func MustDefault

func MustDefault() *Logger

MustDefault sets Default() as slog.Default() and returns it.

func New

func New(opts ...Option) *Logger

New creates a Logger with the provided options.

func NewNop

func NewNop() *Logger

NewNop creates a logger that discards all output.

func SetupDefault

func SetupDefault(opts ...Option) *Logger

SetupDefault initializes a Logger and sets it as slog.Default().

func (*Logger) Config

func (l *Logger) Config() Config

Config returns a snapshot of the current logger configuration.

func (*Logger) FatalContext

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

FatalContext logs at LevelFatal and exits the process.

func (*Logger) SetLevel

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

SetLevel updates the logging threshold.

func (*Logger) TraceContext

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

TraceContext logs at LevelTrace.

func (*Logger) UpdateConfig

func (l *Logger) UpdateConfig(fn func(*Config))

UpdateConfig atomically updates logger configuration using copy-on-write.

func (*Logger) With

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

With returns a derived Logger sharing the same config pointer.

func (*Logger) WithGroup

func (l *Logger) WithGroup(name string) *Logger

WithGroup returns a grouped Logger sharing the same config pointer.

type MaskMap

type MaskMap map[string]MaskType

MaskMap associates attribute keys with masking strategies.

type MaskRules

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

MaskRules is a fluent builder for masking configuration.

func NewMaskRules

func NewMaskRules() *MaskRules

NewMaskRules creates a new builder.

func (*MaskRules) Add

func (r *MaskRules) Add(key string, mType MaskType) *MaskRules

Add registers a key with a masking strategy.

func (*MaskRules) Keys

func (r *MaskRules) Keys() MaskMap

Keys exposes the underlying map.

type MaskType

type MaskType int

MaskType defines the category of data being masked.

const (
	// MaskDefault replaces the value with [MASKED].
	MaskDefault MaskType = iota
	// MaskEmail redacts email addresses while preserving parts for debugging.
	MaskEmail
	// MaskPhone redacts phone numbers while preserving prefix and suffix.
	MaskPhone
	// MaskCard redacts credit card numbers.
	MaskCard
	// MaskSecret completely hides the value as [SECRET].
	MaskSecret
)

type Masker

type Masker interface {
	Mask(value any, mType MaskType) any
}

Masker applies redaction rules to attribute values.

type Metadata

type Metadata map[string][]string

Metadata is a gRPC-style metadata map (key -> values).

type Option

type Option func(*options)

Option configures logger initialization.

func WithAddSource

func WithAddSource(enabled bool) Option

WithAddSource enables source file and line in log records.

func WithContextKeys

func WithContextKeys(keys ...ContextKey) Option

WithContextKeys registers typed keys extracted from context.Context.

func WithDumpLimits

func WithDumpLimits(maxDepth, maxFields int) Option

WithDumpLimits sets default depth and field limits for Dump and payload helpers.

func WithExitFunc

func WithExitFunc(fn func(int)) Option

WithExitFunc overrides the process exit function used by Fatal.

func WithFormat

func WithFormat(f Format) Option

WithFormat sets the log output format.

func WithLevel

func WithLevel(l slog.Level) Option

WithLevel sets the initial logging threshold.

func WithLevelNames

func WithLevelNames(m LevelNames) Option

WithLevelNames customizes level string labels.

func WithMaskKey

func WithMaskKey(key string, mType MaskType) Option

WithMaskKey associates a single attribute key with a MaskType.

func WithMaskKeys

func WithMaskKeys(keys MaskMap) Option

WithMaskKeys applies a batch of masking rules.

func WithMaskRules

func WithMaskRules(r *MaskRules) Option

WithMaskRules applies masking rules from a MaskRules builder.

func WithMasker

func WithMasker(m Masker) Option

WithMasker replaces the default masking logic.

func WithOutput

func WithOutput(w io.Writer) Option

WithOutput sets the output destination.

func WithRemoval

func WithRemoval(set *RemovalSet) Option

WithRemoval registers keys from a RemovalSet for removal.

func WithStackDepth

func WithStackDepth(depth int) Option

WithStackDepth sets how many stack frames to capture on errors.

func WithStackOnError

func WithStackOnError(enabled bool) Option

WithStackOnError attaches a stack trace to Error and Fatal records.

func WithTraceContext

func WithTraceContext(enabled bool) Option

WithTraceContext enables OpenTelemetry trace_id and span_id extraction.

func WithTraceKeys

func WithTraceKeys(traceID, spanID, traceSampled string) Option

WithTraceKeys customizes OTel field names in log output.

type RemovalSet

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

RemovalSet collects attribute keys that must be stripped from log output.

func NewRemovalSet

func NewRemovalSet(keys ...string) *RemovalSet

NewRemovalSet creates an empty RemovalSet or initializes it with keys.

func (*RemovalSet) Add

func (s *RemovalSet) Add(keys ...string) *RemovalSet

Add appends one or more keys to the removal set.

func (*RemovalSet) Keys

func (s *RemovalSet) Keys() []string

Keys returns the underlying slice of keys.

type RemoveMap

type RemoveMap map[string]struct{}

RemoveMap is a set of attribute keys excluded from logs.

Directories

Path Synopsis
examples
basic command
Package main demonstrates basic slogsafe setup: levels, formats, and helpers.
Package main demonstrates basic slogsafe setup: levels, formats, and helpers.
context command
Package main demonstrates typed context keys and logger injection.
Package main demonstrates typed context keys and logger injection.
dump command
Package main demonstrates Dump / Serialize for nested structs via saferefl.
Package main demonstrates Dump / Serialize for nested structs via saferefl.
grpc_payload command
Package main demonstrates sanitized gRPC call / response / stream logging.
Package main demonstrates sanitized gRPC call / response / stream logging.
http_payload command
Package main demonstrates sanitized HTTP request/response payload logging.
Package main demonstrates sanitized HTTP request/response payload logging.
masking command
Package main demonstrates data masking and field removal.
Package main demonstrates data masking and field removal.
presets command
Package main demonstrates Default / Dev / MustDefault presets.
Package main demonstrates Default / Dev / MustDefault presets.
runtime_config command
Package main demonstrates runtime config updates (level / format) without restart.
Package main demonstrates runtime config updates (level / format) without restart.
stack command
Package main demonstrates stack traces and source location on Error/Fatal.
Package main demonstrates stack traces and source location on Error/Fatal.
tracing command
Package main demonstrates OpenTelemetry trace_id / span_id injection.
Package main demonstrates OpenTelemetry trace_id / span_id injection.

Jump to

Keyboard shortcuts

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