logging

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2025 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package logging provides structured logging capabilities using Go's standard log/slog package.

This package offers a comprehensive logging solution with support for multiple output formats, component-aware logging, context integration, and dynamic configuration changes at runtime.

Basic Usage

Initialize the global logger with default settings:

err := logging.InitWithDefaults()
if err != nil {
	panic(err)
}
defer logging.Shutdown()

logging.Info("service started", "version", "1.0.0")
logging.Warn("configuration missing", "key", "database.url")
logging.Error("connection failed", "error", err)

Custom Configuration

Configure the logger with custom settings:

cfg := logging.Config{
	Level:     "debug",
	Format:    "json",
	Output:    "/var/log/app.log",
	AddSource: true,
}
err := logging.Init(cfg)
if err != nil {
	panic(err)
}
defer logging.Shutdown()

Independent Logger Instance

Create a logger without affecting global state:

logger, closer, err := logging.New(cfg)
if err != nil {
	panic(err)
}
if closer != nil {
	defer closer.Close()
}
logger.Info("custom logger message")

Component-Aware Logging

Create component-specific loggers that automatically include component context:

authLogger := logging.NewComponentLogger("auth", "service")
authLogger.Info("user authenticated", "user_id", "123")
// Output: ... component=auth component_type=service user_id=123

// Or use component functions directly
logging.InfoComponent("database", "connection", "pool created", "size", 10)

Context-Aware Logging

Automatically extract and include context fields in log messages:

ctx := context.WithValue(context.Background(), "request_id", "req-123")
ctx = context.WithValue(ctx, "user_id", "user-456")

logging.InfoContext(ctx, "processing request")
// Output: ... request_id=req-123 user_id=user-456

Dynamic Level Changes

Change log levels at runtime without restarting the application:

logging.SetLevel("debug") // Enable debug logging
logging.Debug("now visible")

logging.SetLevel("warn")  // Only warnings and errors
logging.Info("not visible")

Logger Interface

Use the Logger interface for dependency injection and testing:

logger := logging.GetLogger()
logger.Info("using interface")

// Create independent logger with interface
logger, closer, err := logging.NewLogger(cfg)
if err != nil {
	panic(err)
}
if closer != nil {
	defer closer.Close()
}

Index

Examples

Constants

View Source
const (
	// LevelDebug enables detailed diagnostic information useful for debugging.
	// This is the most verbose level and should be used sparingly in production.
	LevelDebug = "debug"

	// LevelInfo enables general informational messages about application flow.
	// This is the default level and provides operational visibility.
	LevelInfo = "info"

	// LevelWarn enables warning conditions that don't halt execution.
	// Use for potentially harmful situations that should be investigated.
	LevelWarn = "warn"

	// LevelError enables error conditions that may affect functionality.
	// Use for errors that require immediate attention but don't crash the application.
	LevelError = "error"
)

Log level constants define the available logging levels.

View Source
const (
	// FormatLogfmt provides key=value structured logging in logfmt format.
	// This is the default format and is human-readable while remaining structured.
	// Example: time=2023-01-01T12:00:00Z level=INFO msg="hello" key=value
	FormatLogfmt = "logfmt"

	// FormatJSON provides machine-readable structured logging in JSON format.
	// This format is ideal for log aggregation systems and automated processing.
	// Example: {"time":"2023-01-01T12:00:00Z","level":"INFO","msg":"hello","key":"value"}
	FormatJSON = "json"
)

Log format constants define the available output formats.

Variables

This section is empty.

Functions

func Debug

func Debug(msg string, args ...any)

Debug logs a debug message using the global logger.

func DebugComponent

func DebugComponent(component, componentType, msg string, args ...any)

DebugComponent logs a debug message with component identification.

func DebugComponentContext

func DebugComponentContext(ctx context.Context, component, componentType, msg string, args ...any)

DebugComponentContext logs a debug message with context and component identification.

func DebugContext

func DebugContext(ctx context.Context, msg string, args ...any)

DebugContext logs a debug message with context using the global logger. It automatically includes context fields like request_id, alert_id, etc.

func Error

func Error(msg string, args ...any)

Error logs an error message using the global logger.

func ErrorComponent

func ErrorComponent(component, componentType, msg string, args ...any)

ErrorComponent logs an error message with component identification.

func ErrorComponentContext

func ErrorComponentContext(ctx context.Context, component, componentType, msg string, args ...any)

ErrorComponentContext logs an error message with context and component identification.

func ErrorContext

func ErrorContext(ctx context.Context, msg string, args ...any)

ErrorContext logs an error message with context using the global logger. It automatically includes context fields like request_id, alert_id, etc.

func Get

func Get() *slog.Logger

Get returns the global logger instance, initializing it with defaults if necessary.

func Info

func Info(msg string, args ...any)

Info logs an informational message using the global logger.

func InfoComponent

func InfoComponent(component, componentType, msg string, args ...any)

InfoComponent logs an info message with component identification.

func InfoComponentContext

func InfoComponentContext(ctx context.Context, component, componentType, msg string, args ...any)

InfoComponentContext logs an info message with context and component identification.

func InfoContext

func InfoContext(ctx context.Context, msg string, args ...any)

InfoContext logs an informational message with context using the global logger. It automatically includes context fields like request_id, alert_id, etc.

Example
_ = InitWithDefaults()
defer Shutdown()

// Create context with values that will be automatically extracted
ctx := context.Background()
ctx = context.WithValue(ctx, "request_id", "req-456")
ctx = context.WithValue(ctx, "user_id", "user-789")

// Context fields are automatically included in log output
InfoContext(ctx, "user action performed", "action", "login")

func Init

func Init(config Config) error

Init initializes the global logger with the provided configuration.

This function configures the global logger that is used by all package-level logging functions (Debug, Info, Warn, Error, etc.). It must be called before using any global logging functions, or they will use a default logger.

The function validates the configuration and returns an error if any settings are invalid. If initialization succeeds, the global logger is replaced and becomes available for use.

Important: If the previous global logger was writing to a file, that file handle will be closed automatically. Always call Shutdown() when your application terminates to ensure proper cleanup.

Example:

cfg := logging.Config{
	Level:  "info",
	Format: "json",
	Output: "/var/log/app.log",
}
if err := logging.Init(cfg); err != nil {
	log.Fatal("Failed to initialize logger:", err)
}
defer logging.Shutdown()
Example
// Initialize with default configuration
config := DefaultConfig()
err := Init(config)
if err != nil {
	panic(err)
}
defer Shutdown()

// Use global logging functions
Info("application started", "version", "1.0.0")
Debug("debug information", "key", "value")

func InitWithDefaults

func InitWithDefaults() error

InitWithDefaults initializes the global logger with recommended default settings.

This is a convenience function that calls Init(DefaultConfig()). It configures the logger with info-level logging, logfmt format, and stdout output.

This function is ideal for applications that need basic logging without custom configuration. For more control over logging behavior, use Init() with a custom Config.

Example:

if err := logging.InitWithDefaults(); err != nil {
	log.Fatal("Failed to initialize logger:", err)
}
defer logging.Shutdown()

logging.Info("application started")

func New

func New(config Config) (*slog.Logger, io.Closer, error)

New creates a new logger instance with the provided configuration.

This function creates an independent logger that does not affect the global logger state. It's useful when you need multiple loggers with different configurations or when you want to avoid global state in your application.

The function returns:

  • *slog.Logger: The configured logger instance
  • io.Closer: A closer for cleanup (non-nil only when output is a file)
  • error: Any configuration or initialization error

The closer must be called when the logger is no longer needed to properly close file handles and prevent resource leaks. It's safe to call Close() on a nil closer.

Example:

logger, closer, err := logging.New(logging.Config{
	Level:  "debug",
	Format: "json",
	Output: "/var/log/app.log",
})
if err != nil {
	return err
}
if closer != nil {
	defer closer.Close()
}
logger.Info("application started")
Example
// Create a logger without affecting global state
config := Config{
	Level:  "info",
	Format: "json",
	Output: "stdout",
}

logger, closer, err := New(config)
if err != nil {
	panic(err)
}
if closer != nil {
	defer closer.Close()
}

logger.Info("custom logger message", "service", "example")

func SetLevel

func SetLevel(level string) error

SetLevel dynamically changes the log level of the global logger at runtime.

This function allows you to change the minimum log level without restarting the application. Messages below the specified level will be filtered out.

Valid levels are: "debug", "info", "warn", "error" The level comparison is case-insensitive.

This is particularly useful for:

  • Enabling debug logging to troubleshoot issues
  • Reducing log verbosity in production
  • Implementing runtime log level controls via APIs or signals

Example:

// Enable debug logging for troubleshooting
if err := logging.SetLevel("debug"); err != nil {
	logging.Error("failed to set log level", "error", err)
}

// Later, reduce verbosity
logging.SetLevel("warn")

Returns an error if the level string is invalid.

Example
// Initialize logging
_ = InitWithDefaults()
defer Shutdown()

Info("this will be logged")

// Change level to error only
err := SetLevel("error")
if err != nil {
	return // handle error in real code
}

Info("this will NOT be logged")
Error("this will be logged")

func Shutdown

func Shutdown() error

Shutdown gracefully closes any open file handles used by the global logger.

This function should be called when your application terminates to ensure proper cleanup of resources. It's safe to call multiple times - subsequent calls will be no-ops.

If the global logger is writing to a file, this function closes the file handle. If the logger is writing to stdout/stderr, this function does nothing.

It's recommended to defer this call immediately after successful initialization:

if err := logging.Init(cfg); err != nil {
	return err
}
defer logging.Shutdown()

Returns an error only if closing the file handle fails.

func ValidateFormat

func ValidateFormat(format string) bool

ValidateFormat reports whether format is a valid log format string.

func ValidateLevel

func ValidateLevel(level string) bool

ValidateLevel reports whether level is a valid log level string.

func Warn

func Warn(msg string, args ...any)

Warn logs a warning message using the global logger.

func WarnComponent

func WarnComponent(component, componentType, msg string, args ...any)

WarnComponent logs a warning message with component identification.

func WarnComponentContext

func WarnComponentContext(ctx context.Context, component, componentType, msg string, args ...any)

WarnComponentContext logs a warning message with context and component identification.

func WarnContext

func WarnContext(ctx context.Context, msg string, args ...any)

WarnContext logs a warning message with context using the global logger. It automatically includes context fields like request_id, alert_id, etc.

func With

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

With returns a logger with the given attributes pre-configured.

func WithGroup

func WithGroup(name string) *slog.Logger

WithGroup returns a logger with the given group name.

Types

type ComponentLogger

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

ComponentLogger represents a logger with pre-configured component context.

This logger automatically includes component name and type in all log messages, making it easy to identify which part of your application generated each log entry. This is particularly useful in microservices, modular applications, or any system where you want to track log messages by their source component.

Component loggers are created with NewComponentLogger() and maintain their component context throughout their lifetime. All logging methods automatically include "component" and "component_type" fields.

Example:

authLogger := logging.NewComponentLogger("auth", "service")
authLogger.Info("user authenticated", "user_id", "123")
// Output: ... component=auth component_type=service user_id=123

func ForComponent

func ForComponent(componentName, componentType string) *ComponentLogger

ForComponent creates a component logger for the given component name and type.

func ForComponentInterface

func ForComponentInterface(component interface{}) *ComponentLogger

ForComponentInterface creates a component logger from a component interface.

func NewComponentLogger

func NewComponentLogger(component, componentType string) *ComponentLogger

NewComponentLogger creates a new component-aware logger with the specified component context.

The returned logger automatically includes the component name and type in all log messages, making it easy to identify the source of log entries in complex applications.

Parameters:

  • component: A descriptive name for the component (e.g., "auth", "database", "api")
  • componentType: The type or category of the component (e.g., "service", "handler", "client")

The component and componentType are included as "component" and "component_type" fields in every log message produced by the returned logger.

Example:

dbLogger := logging.NewComponentLogger("database", "connection")
dbLogger.Info("connection established", "host", "localhost", "port", 5432)
// Output: ... component=database component_type=connection host=localhost port=5432

apiLogger := logging.NewComponentLogger("users", "handler")
apiLogger.Warn("rate limit exceeded", "client_ip", "192.168.1.1")
// Output: ... component=users component_type=handler client_ip=192.168.1.1
Example
// Initialize logging first
_ = InitWithDefaults()
defer Shutdown()

// Create a component-aware logger
cl := NewComponentLogger("auth-service", "microservice")
cl.Info("user authenticated", "user_id", "12345", "method", "oauth")
cl.Warn("rate limit approaching", "current", 95, "limit", 100)

func (*ComponentLogger) Debug

func (cl *ComponentLogger) Debug(msg string, args ...any)

Debug logs a debug message with component context.

func (*ComponentLogger) DebugContext

func (cl *ComponentLogger) DebugContext(ctx context.Context, msg string, args ...any)

DebugContext logs a debug message with context and component context.

func (*ComponentLogger) Error

func (cl *ComponentLogger) Error(msg string, args ...any)

Error logs an error message with component context.

func (*ComponentLogger) ErrorContext

func (cl *ComponentLogger) ErrorContext(ctx context.Context, msg string, args ...any)

ErrorContext logs an error message with context and component context.

func (*ComponentLogger) GetComponent

func (cl *ComponentLogger) GetComponent() string

GetComponent returns the component name.

func (*ComponentLogger) GetComponentType

func (cl *ComponentLogger) GetComponentType() string

GetComponentType returns the component type.

func (*ComponentLogger) Info

func (cl *ComponentLogger) Info(msg string, args ...any)

Info logs an info message with component context.

func (*ComponentLogger) InfoContext

func (cl *ComponentLogger) InfoContext(ctx context.Context, msg string, args ...any)

InfoContext logs an info message with context and component context.

func (*ComponentLogger) Warn

func (cl *ComponentLogger) Warn(msg string, args ...any)

Warn logs a warning message with component context.

func (*ComponentLogger) WarnContext

func (cl *ComponentLogger) WarnContext(ctx context.Context, msg string, args ...any)

WarnContext logs a warning message with context and component context.

func (*ComponentLogger) With

func (cl *ComponentLogger) With(args ...any) Logger

With returns a new logger with additional attributes.

Example
_ = InitWithDefaults()
defer Shutdown()

// Create base component logger
cl := NewComponentLogger("api", "handler")

// Create request-scoped logger with additional context
requestLogger := cl.With("request_id", "req-123", "endpoint", "/users")
requestLogger.Info("processing request")
requestLogger.Info("request completed", "duration_ms", 45)

type ComponentLoggerFactory

type ComponentLoggerFactory struct{}

ComponentLoggerFactory provides factory methods for creating component loggers.

func GetComponentLoggerFactory

func GetComponentLoggerFactory() *ComponentLoggerFactory

GetComponentLoggerFactory returns the global component logger factory.

func NewComponentLoggerFactory

func NewComponentLoggerFactory() *ComponentLoggerFactory

NewComponentLoggerFactory creates a new component logger factory.

func (*ComponentLoggerFactory) CreateLogger

func (clf *ComponentLoggerFactory) CreateLogger(componentName, componentType string) *ComponentLogger

CreateLogger creates a component logger for a component with name and type.

func (*ComponentLoggerFactory) CreateLoggerFromComponent

func (clf *ComponentLoggerFactory) CreateLoggerFromComponent(component interface{}) *ComponentLogger

CreateLoggerFromComponent creates a component logger from a component interface.

type Config

type Config struct {
	// Level sets the minimum log level to output.
	// Valid values: "debug", "info", "warn", "error"
	// Default: "info"
	Level string `json:"level" yaml:"level"`

	// Format sets the output format for log messages.
	// Valid values: "logfmt", "json"
	// Default: "logfmt"
	Format string `json:"format" yaml:"format"`

	// Output sets the destination for log messages.
	// Valid values: "stdout", "stderr", or a file path
	// Default: "stdout"
	// When using a file path, directories will be created automatically.
	Output string `json:"output" yaml:"output"`

	// AddSource includes source file and line information in log messages.
	// This is useful for debugging but adds overhead and should be disabled in production.
	// Default: false
	AddSource bool `json:"add_source" yaml:"add_source"`
}

Config holds the logger configuration settings.

All fields have sensible defaults and can be omitted for basic usage. Use DefaultConfig() to get a pre-configured instance with recommended settings.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a logger configuration with recommended default settings.

The returned configuration uses:

  • Info level logging (debug messages filtered out)
  • Logfmt format (human-readable key=value pairs)
  • Stdout output (console output)
  • Source information disabled (better performance)

This configuration is suitable for most applications and provides a good balance between visibility and performance.

type Logger

type Logger interface {
	// Debug logs a debug-level message with optional key-value pairs.
	// Debug messages are typically filtered out in production.
	Debug(msg string, args ...any)

	// Info logs an info-level message with optional key-value pairs.
	// Info messages provide general operational information.
	Info(msg string, args ...any)

	// Warn logs a warning-level message with optional key-value pairs.
	// Warnings indicate potentially harmful situations.
	Warn(msg string, args ...any)

	// Error logs an error-level message with optional key-value pairs.
	// Errors indicate failure conditions that need attention.
	Error(msg string, args ...any)

	// DebugContext logs a debug message with context and optional key-value pairs.
	// Context fields are automatically extracted and included.
	DebugContext(ctx context.Context, msg string, args ...any)

	// InfoContext logs an info message with context and optional key-value pairs.
	// Context fields are automatically extracted and included.
	InfoContext(ctx context.Context, msg string, args ...any)

	// WarnContext logs a warning message with context and optional key-value pairs.
	// Context fields are automatically extracted and included.
	WarnContext(ctx context.Context, msg string, args ...any)

	// ErrorContext logs an error message with context and optional key-value pairs.
	// Context fields are automatically extracted and included.
	ErrorContext(ctx context.Context, msg string, args ...any)

	// With returns a new Logger with additional key-value pairs pre-configured.
	// The returned logger will include these pairs in all subsequent log messages.
	With(args ...any) Logger
}

Logger defines the interface for structured logging operations.

This interface provides a consistent API for logging across different implementations and is ideal for dependency injection, testing, and creating mockable logging components.

All logging methods accept a message string followed by optional key-value pairs for structured logging. Keys should be strings, and values can be any type that can be serialized by the underlying slog implementation.

Example usage:

logger := logging.GetLogger()
logger.Info("user login", "user_id", "123", "ip", "192.168.1.1")
logger.Error("database error", "error", err, "query", "SELECT * FROM users")

Context-aware methods automatically extract and include context fields:

ctx := context.WithValue(context.Background(), "request_id", "req-456")
logger.InfoContext(ctx, "processing request")
// Output includes: request_id=req-456

func GetLogger

func GetLogger() Logger

GetLogger returns a Logger interface that wraps the global logger.

func NewLogger

func NewLogger(config Config) (Logger, io.Closer, error)

NewLogger creates a Logger interface from the provided configuration.

Jump to

Keyboard shortcuts

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