Skip to content

AlexeiDKL/logger

Repository files navigation

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

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages