logger

package module
v0.9.6 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 2026 License: MIT Imports: 7 Imported by: 0

README

Logger

A production-ready structured logging package for Go, built on top of log/slog with file rotation support and flexible output options.

Features

Core Features:

  • 📝 Structured logging with log/slog
  • 🎯 Multiple output types: stdout, file with automatic rotation
  • 📊 Log format options: text (human-readable), json (machine-readable)
  • 📋 Configurable log levels: debug, info, warn, error
  • 🔄 Automatic file rotation using lumberjack
  • 🛡️ Safe resource management with CloseableLogger
  • 🚨 Enhanced error logging with automatic stack traces
  • 🔧 Zero-downtime logger replacement in running applications

Installation

go get github.com/AlexeiDKL/logger

Quick Start

Basic Usage - Stdout
package main

import (
	"log"
	"github.com/AlexeiDKL/logger"
)

func main() {
	cfg := logger.Config{
		LogOutput: "stdout",
		LogType:   "text",
		Level:     "info",
	}

	log, err := logger.InitLogger(cfg)
	if err != nil {
		log.Fatalf("failed to initialize logger: %v", err)
	}
	defer log.Close()

	log.Info("Application started", "version", "1.0.0")
	log.Debug("This won''t be printed with info level")
	log.Warn("Warning message", "code", 42)
	log.Error("Error occurred", "err", "something went wrong")
}
File Output with Rotation
cfg := logger.Config{
	LogOutput:  "file",
	Path:       "/var/log/myapp/app.log", // absolute path required for file output
	LogType:    "json",                    // json or text
	Level:      "debug",
	MaxSize:    100,    // MB before rotation
	MaxBackups: 5,      // max rotated files to keep
	MaxAge:     30,     // days before deletion
	Compress:   true,   // gzip compressed backups
}

appLog, err := logger.InitLogger(cfg)
if err != nil {
	panic(err)
}
defer appLog.Close()

appLog.Info("Request processed", "duration_ms", 145, "status", 200)

Configuration

Config Struct
type Config struct {
	LogType    string // "json" or "text"
	LogOutput  string // "stdout" or "file"
	Level      string // "debug", "info", "warn", "error"
	Path       string // required for file output (absolute path)
	MaxSize    int    // MB (file rotation)
	MaxBackups int    // number of backup files to keep
	MaxAge     int    // days before backup deletion
	Compress   bool   // gzip compress backups
}
Log Levels
  • debug: Detailed diagnostic information (development)
  • info: General informational messages (production)
  • warn: Warning conditions (recoverable issues)
  • error: Error conditions (unrecoverable issues)

API Reference

CloseableLogger Methods

All methods follow log/slog patterns and safely handle nil loggers:

Method Description
Info(msg, keysAndValues...) Log info level message
Debug(msg, keysAndValues...) Log debug level message
Warn(msg, keysAndValues...) Log warn level + auto stack trace if error/err/panic present
WarnStack(msg, keysAndValues...) Log warn level + explicit stack trace
Error(msg, keysAndValues...) Log error level + auto stack trace if error/err/panic present
ErrorStack(msg, keysAndValues...) Log error level + explicit stack trace
Console(msg, keysAndValues...) Output directly to stderr (config warnings)
Close() Flush buffers and release resources (MUST call before shutdown)
Examples
Automatic Stack Traces
log.Warn("validation failed", "err", errors.New("invalid input"))
// Output includes automatic stack trace when "err" key is detected

log.Error("database error", "error", "connection timeout")
// "error" key also triggers stack trace

log.Error("panic recovered", "panic", "nil pointer", "user_id", 123)
// "panic" key also adds stack trace
Explicit Stack Traces
log.ErrorStack("critical failure", "component", "auth_service")
// Always includes full stack trace regardless of keys
Structured Data
log.Info("user login",
	"user_id", 42,
	"ip_address", "192.168.1.1",
	"duration_ms", 234,
	"success", true,
)

Error Handling

File Validation

The logger validates file paths and rotation parameters:

// ❌ Will error: relative path for file output
cfg := logger.Config{
	LogOutput: "file",
	Path:      "logs/app.log", // must be absolute
	LogType:   "text",
	Level:     "info",
}
_, err := logger.InitLogger(cfg) // error: relative path

// ❌ Will error: negative rotation values
cfg := logger.Config{
	LogOutput:  "file",
	Path:       "/var/log/app.log",
	MaxSize:    -1,  // invalid
	MaxBackups: -1,  // invalid
	MaxAge:     -1,  // invalid
}
_, err := logger.InitLogger(cfg) // error: invalid params
Fallback Behavior
// ⚠️ File output without path falls back to ./apps.log
cfg := logger.Config{
	LogOutput: "file",
	Path:      "", // empty path
	LogType:   "text",
	Level:     "info",
}
log, err := logger.InitLogger(cfg)
// Uses ./apps.log and prints warning to stderr:
// "WARNING: log path not specified, using fallback ./apps.log. Please set absolute path in config to avoid issues."

Best Practices

DO:

  • ✓ Always call defer log.Close() to flush buffers and release file handles
  • ✓ Use absolute paths for file output to avoid confusion
  • ✓ Use structured logging with key-value pairs
  • ✓ Include relevant context (user_id, request_id, duration, etc.)
  • ✓ Use appropriate log levels (debug for noise, info for important events, error for issues)

DON''T:

  • ✗ Ignore the Close() method - logs may be lost
  • ✗ Use string concatenation instead of structured keys
  • ✗ Log the same message with different casing (normalizes to lowercase)
  • ✗ Rely on fallback path for production - explicitly set absolute path

Testing

Run the test suite:

go test -v

The package includes tests for:

  • ✓ Stdout output (text format)
  • ✓ File output (absolute and relative paths)
  • ✓ File rotation configuration
  • ✓ Invalid log types and outputs
  • ✓ Invalid rotation parameters
  • ✓ Fallback path handling

Thread Safety

CloseableLogger wraps slog.Logger, which is safe for concurrent use. Multiple goroutines can safely call logging methods simultaneously.

// Safe to use from multiple goroutines
go func() { log.Info("goroutine 1") }()
go func() { log.Info("goroutine 2") }()

Dependencies

  • log/slog (stdlib, Go 1.21+)
  • gopkg.in/natefinch/lumberjack.v2 - File rotation

Requirements

  • Go 1.21 or higher (uses log/slog)

License

MIT License - See LICENSE file for details

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

Author

Alexei DKL

Documentation

Overview

Package logger provides structured logging for Go applications with support for multiple output formats and file rotation.

The package wraps the standard library log/slog with additional features:

  • Multiple output destinations (stdout, file)
  • Multiple formats (text, JSON)
  • Configurable log levels
  • Automatic file rotation using lumberjack
  • Automatic stack trace capture for errors
  • Safe resource management via CloseableLogger

Example:

cfg := logger.Config{
	LogOutput: "file",
	Path:      "/var/log/app.log",
	LogType:   "json",
	Level:     "info",
	MaxSize:   100,     // MB
	MaxBackups: 5,
	MaxAge:    30,      // days
}
log, err := logger.InitLogger(cfg)
if err != nil {
	panic(err)
}
defer log.Close()

log.Info("Application started")
log.Error("Something went wrong", "err", errors.New("connection timeout"))

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CloseableLogger

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

CloseableLogger wraps slog.Logger with resource management capabilities. It handles optional closer (e.g., file-rotation writer) that may hold OS resources.

IMPORTANT: Callers MUST call Close() when the logger is no longer needed:

defer log.Close()

This ensures buffers are flushed and file handles are released. Failure to close may result in lost logs.

All logging methods safely handle nil loggers.

Example (StackTraces)

ExampleCloseableLogger_stackTraces demonstrates automatic stack trace capture.

cfg := Config{
	LogOutput: "stdout",
	LogType:   "text",
	Level:     "warn",
}

log, err := InitLogger(cfg)
if err != nil {
	fmt.Printf("Error: %v\n", err)
	return
}
defer log.Close()

// Auto stack trace when "error" or "err" key is present
log.Warn("validation failed", "err", errors.New("invalid email format"))

// Explicit stack trace regardless of keys
log.ErrorStack("critical operation failed", "operation", "database_migration")
Example (StructuredData)

ExampleCloseableLogger_structuredData demonstrates structured key-value logging.

cfg := Config{
	LogOutput: "stdout",
	LogType:   "text",
	Level:     "info",
}

log, err := InitLogger(cfg)
if err != nil {
	fmt.Printf("Error: %v\n", err)
	return
}
defer log.Close()

// Include relevant context in logs
log.Info("user action",
	"user_id", 42,
	"action", "login",
	"ip_address", "192.168.1.100",
	"success", true,
	"duration_ms", 234,
)

func InitLogger

func InitLogger(logConfig Config) (*CloseableLogger, error)

InitLogger creates and returns a new CloseableLogger based on the provided Config.

Parameters:

  • logConfig: Configuration struct specifying logger output, format, and level

Returns:

  • *CloseableLogger: Initialized logger (must call Close() when done)
  • error: Any error during initialization (invalid config, file I/O failures, etc.)

Example:

cfg := logger.Config{
	LogOutput: "file",
	Path:      "/var/log/app.log",
	LogType:   "json",
	Level:     "info",
	MaxSize:   100,
	MaxBackups: 5,
	MaxAge:    30,
}
log, err := logger.InitLogger(cfg)
if err != nil {
	panic(err)
}
defer log.Close()
Example (JsonOutput)

ExampleInitLogger_jsonOutput demonstrates JSON formatted logging.

cfg := Config{
	LogOutput: "stdout",
	LogType:   "json", // Switch to JSON format
	Level:     "debug",
}

log, err := InitLogger(cfg)
if err != nil {
	fmt.Printf("Error: %v\n", err)
	return
}
defer log.Close()

log.Info("request processed", "status", 200, "duration_ms", 145)
// Output shows JSON structured logging format with time, level, message, and key-value pairs
Example (Stdout)

ExampleInitLogger_stdout demonstrates basic logging to stdout.

cfg := Config{
	LogOutput: "stdout",
	LogType:   "text",
	Level:     "info",
}

log, err := InitLogger(cfg)
if err != nil {
	fmt.Printf("Error: %v\n", err)
	return
}
defer log.Close()

log.Info("Application started", "version", "1.0.0")
log.Debug("Debug messages not shown at info level")
log.Warn("Warning: cache miss", "cache_key", "user:123")
log.Error("Error occurred", "err", errors.New("connection timeout"))
// Output shows structured logging format

func (*CloseableLogger) Close

func (c *CloseableLogger) Close() error

Close flushes any pending log entries and releases underlying resources. Returns any error from closing the underlying io.Closer (e.g., file writer). Must be called before application shutdown to ensure all logs are written. Safe to call on nil logger.

func (*CloseableLogger) Console

func (c *CloseableLogger) Console(msg string, keysAndValues ...interface{})

Console outputs a message directly to stderr (used for configuration warnings). Bypasses the normal slog handler chain for immediate visibility. Safe to call on nil logger.

func (*CloseableLogger) Debug

func (c *CloseableLogger) Debug(msg string, keysAndValues ...interface{})

Debug logs a debug level message with optional key-value pairs. Safe to call on nil logger.

func (*CloseableLogger) Error

func (c *CloseableLogger) Error(msg string, keysAndValues ...interface{})

Error logs an error level message with optional key-value pairs. Automatically includes stack trace if "error", "err", or "panic" keys are found. Safe to call on nil logger.

func (*CloseableLogger) ErrorStack

func (c *CloseableLogger) ErrorStack(msg string, keysAndValues ...interface{})

ErrorStack logs an error level message with explicit stack trace appended. Always includes full runtime stack regardless of provided keys. Safe to call on nil logger.

func (*CloseableLogger) Info

func (c *CloseableLogger) Info(msg string, keysAndValues ...interface{})

Info logs an info level message with optional key-value pairs. Safe to call on nil logger.

func (*CloseableLogger) Warn

func (c *CloseableLogger) Warn(msg string, keysAndValues ...interface{})

Warn logs a warn level message with optional key-value pairs. Automatically includes stack trace if "error", "err", or "panic" keys are found. Safe to call on nil logger.

func (*CloseableLogger) WarnStack

func (c *CloseableLogger) WarnStack(msg string, keysAndValues ...interface{})

WarnStack logs a warn level message with explicit stack trace appended. Always includes full runtime stack regardless of provided keys. Safe to call on nil logger.

type Config

type Config struct {
	Level      string `mapstructure:"level"`
	Path       string `mapstructure:"path"`
	MaxSize    int    `mapstructure:"max_size"`
	MaxBackups int    `mapstructure:"max_backups"`
	MaxAge     int    `mapstructure:"max_age"`
	Compress   bool   `mapstructure:"compress"`
	LogType    string `mapstructure:"log_type"`
	LogOutput  string `mapstructure:"log_output"`
}

Config holds the configuration for logger initialization.

Fields:

  • LogType: Format of log output ("json" or "text")
  • LogOutput: Output destination ("stdout" or "file")
  • Level: Minimum log level ("debug", "info", "warn", "error")
  • Path: Absolute path to log file (required for file output, ignored for stdout)
  • MaxSize: Maximum size of log file in MB before rotation
  • MaxBackups: Number of backup files to keep during rotation
  • MaxAge: Maximum age of backup files in days
  • Compress: Whether to gzip compress rotated backup files
Example

ExampleConfig demonstrates file output configuration.

// This example shows how to configure file output
// Note: This doesn't actually run, just shows the structure
_ = Config{
	LogType:    "json",
	LogOutput:  "file",
	Level:      "info",
	Path:       "/var/log/myapp/app.log", // absolute path required
	MaxSize:    100,                      // MB before rotation
	MaxBackups: 5,                        // keep 5 backup files
	MaxAge:     30,                       // days before deletion
	Compress:   true,                     // gzip compress backups
}

Jump to

Keyboard shortcuts

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