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 ¶
- Constants
- func Debug(msg string, args ...any)
- func DebugComponent(component, componentType, msg string, args ...any)
- func DebugComponentContext(ctx context.Context, component, componentType, msg string, args ...any)
- func DebugContext(ctx context.Context, msg string, args ...any)
- func Error(msg string, args ...any)
- func ErrorComponent(component, componentType, msg string, args ...any)
- func ErrorComponentContext(ctx context.Context, component, componentType, msg string, args ...any)
- func ErrorContext(ctx context.Context, msg string, args ...any)
- func Get() *slog.Logger
- func Info(msg string, args ...any)
- func InfoComponent(component, componentType, msg string, args ...any)
- func InfoComponentContext(ctx context.Context, component, componentType, msg string, args ...any)
- func InfoContext(ctx context.Context, msg string, args ...any)
- func Init(config Config) error
- func InitWithDefaults() error
- func New(config Config) (*slog.Logger, io.Closer, error)
- func SetLevel(level string) error
- func Shutdown() error
- func ValidateFormat(format string) bool
- func ValidateLevel(level string) bool
- func Warn(msg string, args ...any)
- func WarnComponent(component, componentType, msg string, args ...any)
- func WarnComponentContext(ctx context.Context, component, componentType, msg string, args ...any)
- func WarnContext(ctx context.Context, msg string, args ...any)
- func With(args ...any) *slog.Logger
- func WithGroup(name string) *slog.Logger
- type ComponentLogger
- func (cl *ComponentLogger) Debug(msg string, args ...any)
- func (cl *ComponentLogger) DebugContext(ctx context.Context, msg string, args ...any)
- func (cl *ComponentLogger) Error(msg string, args ...any)
- func (cl *ComponentLogger) ErrorContext(ctx context.Context, msg string, args ...any)
- func (cl *ComponentLogger) GetComponent() string
- func (cl *ComponentLogger) GetComponentType() string
- func (cl *ComponentLogger) Info(msg string, args ...any)
- func (cl *ComponentLogger) InfoContext(ctx context.Context, msg string, args ...any)
- func (cl *ComponentLogger) Warn(msg string, args ...any)
- func (cl *ComponentLogger) WarnContext(ctx context.Context, msg string, args ...any)
- func (cl *ComponentLogger) With(args ...any) Logger
- type ComponentLoggerFactory
- type Config
- type Logger
Examples ¶
Constants ¶
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.
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 DebugComponent ¶
DebugComponent logs a debug message with component identification.
func DebugComponentContext ¶
DebugComponentContext logs a debug message with context and component identification.
func DebugContext ¶
DebugContext logs a debug message with context using the global logger. It automatically includes context fields like request_id, alert_id, etc.
func ErrorComponent ¶
ErrorComponent logs an error message with component identification.
func ErrorComponentContext ¶
ErrorComponentContext logs an error message with context and component identification.
func ErrorContext ¶
ErrorContext logs an error message with context using the global logger. It automatically includes context fields like request_id, alert_id, etc.
func InfoComponent ¶
InfoComponent logs an info message with component identification.
func InfoComponentContext ¶
InfoComponentContext logs an info message with context and component identification.
func InfoContext ¶
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 ¶
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 ¶
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 ¶
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 ¶
ValidateFormat reports whether format is a valid log format string.
func ValidateLevel ¶
ValidateLevel reports whether level is a valid log level string.
func WarnComponent ¶
WarnComponent logs a warning message with component identification.
func WarnComponentContext ¶
WarnComponentContext logs a warning message with context and component identification.
func WarnContext ¶
WarnContext logs a warning message with context using the global logger. It automatically includes context fields like request_id, alert_id, etc.
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