Logging Package

API reference for rivaas.dev/logging - Structured logging for Go applications

This is the API reference for the rivaas.dev/logging package. For learning-focused documentation, see the Logging Guide.

Package Information

Package Overview

The logging package provides structured logging for Rivaas applications using Go’s standard log/slog package, with additional features for production environments.

Core Features

  • Multiple output formats (JSON, Text, Console)
  • Context-aware logging with OpenTelemetry trace correlation
  • Automatic sensitive data redaction
  • Log sampling for high-traffic scenarios
  • Dynamic log level changes at runtime
  • Convenience methods for common patterns
  • Comprehensive testing utilities
  • Zero external dependencies (except OpenTelemetry for tracing)

Architecture

The package is organized around key components:

Main Types

Logger - Main logging type with structured logging methods

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

ContextLogger - Context-aware logger with automatic trace correlation

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

Option - Functional option for logger configuration

type Option func(*Logger)

Quick API Index

Logger Creation

logger, err := logging.New(options...)     // With error handling
logger := logging.MustNew(options...)      // Panics on error

Options must not be nil; passing a nil option results in an error (or panic with MustNew).

Logging Methods

logger.Debug(msg string, args ...any)
logger.Info(msg string, args ...any)
logger.Warn(msg string, args ...any)
logger.Error(msg string, args ...any)

Convenience Methods

logger.LogRequest(r *http.Request, extra ...any)
logger.LogError(err error, msg string, extra ...any)
logger.LogDuration(msg string, start time.Time, extra ...any)
logger.ErrorWithStack(msg string, err error, includeStack bool, extra ...any)

Context-Aware Logging

cl := logging.NewContextLogger(ctx context.Context, logger *Logger)
cl.Info(msg string, args ...any)  // Includes trace_id and span_id

Configuration Methods

logger.SetLevel(level Level) error
logger.Level() Level
logger.Shutdown(ctx context.Context) error

Reference Pages

API Reference

Logger and ContextLogger types with all methods.

View →

Options

Configuration options for handlers and output.

View →

Testing Utilities

Test helpers and mocking utilities.

View →

Troubleshooting

Common logging issues and solutions.

View →

User Guide

Step-by-step tutorials and examples.

View →

Type Reference

Logger

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

Main logging type. Thread-safe for concurrent access.

Creation:

logger := logging.MustNew(
    logging.WithJSONHandler(),
    logging.WithLevel(logging.LevelInfo),
)

Key Methods:

  • Debug, Info, Warn, Error - Logging at different levels
  • LogRequest, LogError, LogDuration - Convenience methods
  • SetLevel, Level - Dynamic level management
  • Shutdown - Graceful shutdown

ContextLogger

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

Context-aware logger with automatic trace correlation.

Creation:

cl := logging.NewContextLogger(ctx, logger)

Key Methods:

  • Debug, Info, Warn, Error - Logging with trace correlation
  • TraceID, SpanID - Access trace information
  • Logger - Get underlying slog.Logger

HandlerType

type HandlerType string

const (
    JSONHandler    HandlerType = "json"
    TextHandler    HandlerType = "text"
    ConsoleHandler HandlerType = "console"
)

Output format type.

Level

type Level = slog.Level

const (
    LevelDebug = slog.LevelDebug  // -4
    LevelInfo  = slog.LevelInfo   // 0
    LevelWarn  = slog.LevelWarn   // 4
    LevelError = slog.LevelError  // 8
)

Log level constants.

Log sampling options

Configure log sampling with functional options (no config struct):

  • WithSamplingInitial(initial int) — Log the first initial entries unconditionally. Zero means no initial burst. Must be non-negative.
  • WithSamplingThereafter(thereafter int) — After the initial phase, log 1 in every thereafter entries. Zero means log all. Must be non-negative.
  • WithSamplingTick(tick time.Duration) — Reset the sampling counter every tick. Zero means never reset.

Sampling is enabled when any of these options is applied. Combine them as needed. Errors (level >= ERROR) always bypass sampling.

Error Types

The package defines sentinel errors for better error handling:

var (
    ErrNilLogger         = errors.New("custom logger is nil")
    ErrInvalidHandler    = errors.New("invalid handler type")
    ErrLoggerShutdown    = errors.New("logger is shut down")
    ErrInvalidLevel      = errors.New("invalid log level")
    ErrCannotChangeLevel = errors.New("cannot change level on custom logger")
)

Usage:

if err := logger.SetLevel(level); err != nil {
    if errors.Is(err, logging.ErrCannotChangeLevel) {
        // Handle immutable logger case
    }
}

Common Patterns

Basic Usage

logger := logging.MustNew(
    logging.WithJSONHandler(),
    logging.WithLevel(logging.LevelInfo),
)
defer logger.Shutdown(context.Background())

logger.Info("operation completed", "items", 100)

With Service Metadata

logger := logging.MustNew(
    logging.WithJSONHandler(),
    logging.WithServiceName("payment-api"),
    logging.WithServiceVersion("v2.1.0"),
    logging.WithEnvironment("production"),
)

With Context and Tracing

cl := logging.NewContextLogger(ctx, logger)
cl.Info("processing request", "user_id", userID)
// Automatically includes trace_id and span_id

With Sampling

logger := logging.MustNew(
    logging.WithJSONHandler(),
    logging.WithSamplingInitial(1000),
    logging.WithSamplingThereafter(100),
    logging.WithSamplingTick(time.Minute),
)

Thread Safety

The Logger type is thread-safe for:

  • Concurrent logging operations
  • Concurrent SetLevel calls (serialized internally)
  • Mixed logging and configuration operations

Not thread-safe for:

  • Concurrent modification during initialization (use synchronization)

Performance Notes

  • Logging overhead: ~500ns per log entry
  • Level checks: ~5ns per check
  • Sampling overhead: ~20ns per log entry
  • Zero allocations: Standard log calls with inline fields
  • Stack traces: ~150µs capture cost (only when requested)

Version Compatibility

The logging package follows semantic versioning. The API is stable for the v1 series.

Minimum Go version: 1.25

Next Steps

For learning-focused guides, see the Logging Guide.