logger

package
v1.19.3 Latest Latest
Warning

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

Go to latest
Published: Feb 11, 2026 License: MIT Imports: 26 Imported by: 0

README

Logger Package

Go Version Coverage

Production-ready structured logging system for Go applications with flexible output management, field injection, level-based filtering, and extensive integration capabilities.


Table of Contents


Overview

The logger package provides a comprehensive structured logging solution built on top of logrus. It extends logrus with advanced features while maintaining compatibility with standard Go logging interfaces.

Design Philosophy
  1. Structured Logging: JSON-formatted logs with custom fields for better observability
  2. Flexible Output: Multiple simultaneous outputs (file, syslog, stdout/stderr)
  3. Thread-Safe: Concurrent logging without data races
  4. Performance: Efficient buffering and minimal overhead
  5. Integration-Ready: Compatible with popular frameworks (GORM, Hashicorp, spf13)
  6. Observable: Level-based filtering and customizable formatting
Key Features
  • 8 Log Levels: Panic, Fatal, Error, Warning, Info, Debug, Trace, + Null
  • Multiple Outputs: File, syslog, stdout, stderr, custom writers
  • Field Injection: Persistent and per-entry custom fields
  • Hooks System: Extensible logging pipeline
  • File Rotation: Size and age-based automatic rotation
  • JSON/Text Format: Configurable output formatting
  • io.Writer Interface: Standard Go writer compatibility
  • Thread-Safe: Safe for concurrent use
  • Clone Support: Duplicate loggers with custom settings
  • Integration: GORM, Hashicorp, spf13/cobra adapters

Architecture

Component Diagram
logger/
├── logger               # Core logging implementation
│   ├── interface.go     # Logger interface
│   ├── model.go         # Logger state management
│   ├── log.go           # Log methods (Debug, Info, etc.)
│   ├── manage.go        # Configuration management
│   └── iowritecloser.go # io.Writer implementation
├── config/              # Configuration management
│   ├── model.go         # Config structure
│   ├── validation.go    # Config validation
│   └── options.go       # Logger options
├── entry/               # Log entry management
│   ├── interface.go     # Entry interface
│   ├── model.go         # Entry implementation
│   └── format.go        # Entry formatting
├── fields/              # Custom fields management
│   ├── interface.go     # Fields interface
│   ├── model.go         # Fields implementation
│   └── merge.go         # Fields merging
├── level/               # Log level enumeration
│   ├── interface.go     # Level interface
│   ├── model.go         # Level implementation
│   └── parse.go         # Level parsing
├── hooks/               # Output hooks
│   ├── hookfile/        # File output hook
│   ├── hooksyslog/      # Syslog output hook
│   ├── hookstdout/      # Stdout hook
│   ├── hookstderr/      # Stderr hook
│   └── hookwriter/      # Custom writer hook
├── integrations/        # Third-party integrations
│   ├── gorm/            # GORM logger adapter
│   ├── hashicorp/       # Hashicorp logger adapter
│   └── types/           # Common types
└── spf13.go             # spf13/jwalterweatherman integration
Component Hierarchy
┌──────────────────────────────────────┐
│            Logger Package            │
│       Structured Logging System      │
└──────┬──────────┬────────┬───────────┘
       │          │        │
   ┌───▼──┐  ┌────▼───┐  ┌─▼──────┐
   │Entry │  │Fields  │  │ Level  │
   │      │  │        │  │        │
   │Format│  │Persist │  │Filter  │
   └───┬──┘  └────┬───┘  └─┬──────┘
       │          │        │
       └──────────┴────────┘
                  │
           ┌──────▼──────┐
           │    Hooks    │
           │             │
           ├─ File       │
           ├─ Syslog     │
           ├─ Stdout     │
           ├─ Stderr     │
           └─ Custom     │
           └─────────────┘
Data Flow
Application Code
       │
       ▼
┌────────────────┐
│ Logger.Info()  │  Create log entry
└──────┬─────────┘
       │
       ▼
┌────────────────┐
│ Entry + Fields │  Merge persistent fields
└──────┬─────────┘
       │
       ▼
┌────────────────┐
│  Level Filter  │  Check minimum level
└──────┬─────────┘
       │
       ▼
┌────────────────┐
│ Formatter      │  JSON or Text
└──────┬─────────┘
       │
       ▼
┌────────────────┐
│    Hooks       │  Distribute to outputs
└──────┬─────────┘
       │
       ├─→ File
       ├─→ Syslog
       ├─→ Stdout
       └─→ Custom

Quick Start

Installation
go get github.com/nabbar/golib/logger

Dependencies:

  • Go ≥ 1.24 (hookfile requires os.OpenRoot introduced in Go 1.24)
  • github.com/sirupsen/logrus
  • github.com/nabbar/golib/logger/config
  • github.com/nabbar/golib/logger/level
Basic Logging
import (
    "github.com/nabbar/golib/logger"
    "github.com/nabbar/golib/logger/config"
    "github.com/nabbar/golib/logger/level"
)

// Create logger with default configuration
log, err := logger.New(context.Background)
if err != nil {
    panic(err)
}
defer log.Close()

// Set minimum level
log.SetLevel(level.InfoLevel)

// Log messages
log.Info("Application started", nil)
log.Debug("Debug message", map[string]interface{}{
    "key": "value",
})
log.Error("Error occurred", nil, fmt.Errorf("example error"))
Configured Logger
import (
    logcfg "github.com/nabbar/golib/logger/config"
    loglvl "github.com/nabbar/golib/logger/level"
)

// Create configuration
opts := &logcfg.Options{
    LogLevel:      loglvl.InfoLevel,
    LogFormatter:  logcfg.FormatJSON,
    EnableTrace:   true,
    EnableConsole: true,
    DisableStack:  false,
}

// Add file output
opts.LogFile = &logcfg.OptionsFile{
    LogFileName:      "/var/log/app.log",
    LogFileMaxSize:   100,  // MB
    LogFileMaxAge:    30,   // days
    LogFileMaxBackup: 10,   // files
    LogFileCompress:  true,
}

// Create logger
log, err := logger.New(context.Background)
if err != nil {
    panic(err)
}

if err := log.SetOptions(opts); err != nil {
    panic(err)
}
defer log.Close()
With Persistent Fields
import (
    "github.com/nabbar/golib/logger/fields"
)

// Create fields
flds := fields.New()
flds.Add("service", "api-gateway")
flds.Add("version", "1.2.3")
flds.Add("environment", "production")

// Set on logger
log.SetFields(flds)

// All log entries will include these fields
log.Info("Request processed", map[string]interface{}{
    "request_id": "abc-123",
    "duration_ms": 45,
})

// Output (JSON):
// {"level":"info","msg":"Request processed","service":"api-gateway",
//  "version":"1.2.3","environment":"production","request_id":"abc-123",
//  "duration_ms":45,"time":"2024-01-15T10:30:00Z"}
Inheriting Logger

Use NewFrom to create a new logger based on an existing one, inheriting its fields and level.

// Parent logger
parentLog := logger.New(ctx)
parentLog.SetFields(fields.NewFromMap(map[string]interface{}{
    "app": "my-app",
}))

// Child logger inherits "app" field
childLog, err := logger.NewFrom(ctx, nil, parentLog)
if err != nil {
    panic(err)
}

// Add specific fields to child
childLog.SetFields(fields.NewFromMap(map[string]interface{}{
    "module": "auth",
}))

childLog.Info("User login", nil)
// Log contains: app="my-app", module="auth"

Performance

Benchmarks

Measured on: AMD Ryzen 9 5950X, 64GB RAM, Go 1.24+

Operation Time Memory Allocations
Logger Creation 2.5 µs 3.2 KB 28 allocs
Info() call (no output) 850 ns 512 B 6 allocs
Info() call (file) 12 µs 1.8 KB 18 allocs
Info() call (JSON + fields) 15 µs 2.1 KB 22 allocs
Field Add 120 ns 64 B 1 alloc
Clone() 3.2 µs 3.5 KB 30 allocs
Test Coverage

Latest test results (861 total specs):

Package Specs Coverage Status
logger 82 73.0% ✅ PASS
config 125 85.3% ✅ PASS
entry 135 85.8% ✅ PASS
fields 114 93.8% ✅ PASS
gorm 34 100.0% ✅ PASS
hashicorp 89 96.6% ✅ PASS
hookfile 28 84.0% ✅ PASS
hookstderr 30 100.0% ✅ PASS
hookstdout 30 100.0% ✅ PASS
hooksyslog 40 84.3% ✅ PASS
hookwriter 31 90.2% ✅ PASS
level 94 98.0% ✅ PASS
types 32 N/A ✅ PASS
TOTAL 861 84.6% ALL PASS
Memory Profile
  • Per Logger Instance: ~3KB base overhead
  • Per Log Entry: Amortized O(1), ~512B without outputs
  • With JSON Formatting: +600B per entry
  • With 10 Fields: +800B per entry
Concurrency
  • Write Operations: Thread-safe with mutex protection
  • Read Operations: Lock-free reads where possible
  • File Hooks: Buffered writes for performance
  • Race Detection: Clean (no data races)

Subpackages

config

Purpose: Configuration management for logger options and validation.

Key Features:

  • Complete logger configuration structure
  • JSON/YAML/TOML serialization support
  • File rotation settings (size, age, backup count)
  • Syslog configuration (network, host, level)
  • Format enumeration (JSON/Text)
  • Validation logic

Use Case: Application configuration, dynamic reconfiguration, config file parsing

Documentation: config/README.md


entry

Purpose: Log entry creation, formatting, and lifecycle management.

Key Features:

  • Entry creation with context
  • Field merging (persistent + per-entry)
  • Level association
  • Timestamp management
  • Formatting for output
  • Stack trace capture

Use Case: Structured log entry building, custom formatters, log aggregation

Documentation: entry/README.md


fields

Purpose: Custom field management and structured data injection.

Key Features:

  • Thread-safe field operations
  • Key-value storage with type preservation
  • Field merging and cloning
  • logrus.Fields conversion
  • Add/Get/Delete/List operations

Use Case: Contextual logging, request tracking, application metadata

Documentation: fields/README.md


level

Purpose: Log level enumeration, parsing, and filtering.

Key Features:

  • 8 log levels (Panic, Fatal, Error, Warning, Info, Debug, Trace, Null)
  • String parsing and validation
  • Comparison operations
  • logrus level conversion
  • Level-based filtering

Use Case: Log verbosity control, environment-based filtering, dynamic level changes

Documentation: level/README.md


gorm

Purpose: GORM ORM integration adapter.

Key Features:

  • Query logging with duration tracking
  • Slow query detection (configurable threshold)
  • Error logging
  • Record count tracking
  • Compatible with GORM v2 logger interface

Performance:

  • Query logging overhead: <100µs
  • No impact on query execution
  • 100% test coverage

Use Case: Database query monitoring, slow query analysis, ORM debugging

Documentation: gorm/README.md


hashicorp

Purpose: Hashicorp tools integration (Vault, Consul, Nomad, Terraform).

Key Features:

  • hclog adapter implementation
  • Level mapping (hclog ↔ logger levels)
  • Structured logging support
  • Context propagation
  • Named logger support

Performance:

  • Adapter overhead: <50µs
  • 96.6% test coverage

Use Case: Vault client logging, Consul integration, Terraform provider logs

Documentation: hashicorp/README.md


hookfile

Purpose: File output hook with rotation support.

Key Features:

  • Size-based rotation (MB threshold)
  • Age-based rotation (days threshold)
  • Backup file management (count limit)
  • Compression (gzip)
  • Buffered writes

Performance:

  • Write buffering reduces I/O calls
  • Compression saves disk space
  • Rotation overhead: <10ms

Use Case: Production log files, application logs, audit trails

Documentation: hookfile/README.md


hooksyslog

Purpose: Syslog protocol output (RFC 5424).

Key Features:

  • TCP/UDP transport
  • Local and network syslog
  • Priority mapping
  • Tag customization
  • Facility and severity codes

Performance:

  • Network latency dependent
  • Async write support

Use Case: Centralized logging, syslog servers, system integration

Documentation: hooksyslog/README.md


hookstdout / hookstderr

Purpose: Standard output/error stream hooks.

Key Features:

  • Console output (stdout/stderr)
  • Color support (if TTY detected)
  • Human-readable formatting
  • Development-friendly output

Performance:

  • Direct write (no buffering)
  • Minimal overhead
  • 100% test coverage (both packages)

Use Case: Development logging, console applications, CLI tools

Documentation: hookstdout/README.md, hookstderr/README.md


hookwriter

Purpose: Custom io.Writer integration hook.

Key Features:

  • Adapt any io.Writer as log output
  • Level filtering per writer
  • Buffering support
  • Error handling

Performance:

  • Overhead depends on underlying writer
  • 90.2% test coverage

Use Case: Custom outputs, network streams, database logging, message queues

Documentation: hookwriter/README.md


types

Purpose: Common types and structures used across logger packages.

Key Features:

  • Logger type definitions
  • Configuration structures
  • Compatibility types (GORM, Hashicorp)
  • Interface definitions

Use Case: Type safety, interface compliance, API contracts

Documentation: types/README.md


Use Cases

1. Web Application Logging
// HTTP middleware logging
func LoggingMiddleware(log logger.Logger) func(http.Handler) http.Handler {
    return func(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            start := time.Now()
            
            // Clone logger for this request
            reqLog, _ := log.Clone()
            reqLog.SetFields(fields.NewFromMap(map[string]interface{}{
                "request_id": generateRequestID(),
                "method":     r.Method,
                "path":       r.URL.Path,
                "remote_ip":  r.RemoteAddr,
            }))
            
            // Wrap response writer
            wrapped := &responseWriter{ResponseWriter: w, statusCode: 200}
            
            next.ServeHTTP(wrapped, r)
            
            // Log request completion
            reqLog.Info("Request completed", map[string]interface{}{
                "status":      wrapped.statusCode,
                "duration_ms": time.Since(start).Milliseconds(),
            })
        })
    }
}
2. Database Query Logging
import (
    "github.com/nabbar/golib/logger/gorm"
    "gorm.io/gorm"
)

// Integrate with GORM
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
    Logger: gorm.New(log, gorm.Config{
        SlowThreshold: 200 * time.Millisecond,
        LogLevel:      gorm.Info,
    }),
})

// Queries are automatically logged
db.Find(&users) // Logs query, duration, rows affected
3. Background Job Logging
func ProcessJob(log logger.Logger, job Job) error {
    // Clone logger with job context
    jobLog, _ := log.Clone()
    jobLog.SetFields(fields.NewFromMap(map[string]interface{}{
        "job_id":   job.ID,
        "job_type": job.Type,
    }))
    
    jobLog.Info("Job started", nil)
    
    if err := job.Execute(); err != nil {
        jobLog.Error("Job failed", nil, err)
        return err
    }
    
    jobLog.Info("Job completed", map[string]interface{}{
        "duration": job.Duration(),
    })
    return nil
}
4. Microservice Distributed Tracing
// Add trace ID to logger
func WithTraceID(log logger.Logger, traceID string) logger.Logger {
    clone, _ := log.Clone()
    flds := clone.GetFields()
    flds.Add("trace_id", traceID)
    flds.Add("span_id", generateSpanID())
    clone.SetFields(flds)
    return clone
}

// Use in service calls
func HandleRequest(ctx context.Context, log logger.Logger) {
    traceID := ctx.Value("trace_id").(string)
    log = WithTraceID(log, traceID)
    
    log.Info("Service called", nil)
    // Trace ID included in all logs
}
5. Multi-Output Logging
opts := &logcfg.Options{
    EnableConsole: true,  // Development visibility
}

// Production file logging
opts.LogFile = &logcfg.OptionsFile{
    LogFileName: "/var/log/app.log",
    LogFileMaxSize: 100,
}

// Critical errors to syslog
opts.LogSyslog = &logcfg.OptionsSyslog{
    LogSyslogNetwork: "tcp",
    LogSyslogHost:    "syslog.example.com:514",
    LogSyslogLevel:   loglvl.ErrorLevel,
}

log.SetOptions(opts)

// Logs go to console, file, AND syslog (if level >= Error)
log.Error("Critical error", nil, err)

Best Practices

1. Use Structured Logging
// DON'T: String formatting
log.Info(fmt.Sprintf("User %s logged in from %s", user, ip), nil)

// DO: Structured fields
log.Info("User logged in", map[string]interface{}{
    "user_id": user.ID,
    "username": user.Name,
    "ip_address": ip,
})
2. Clone for Context
// DON'T: Modify shared logger
log.SetFields(requestFields)
processRequest()
log.SetFields(originalFields) // Error-prone

// DO: Clone for isolated context
reqLog, _ := log.Clone()
reqLog.SetFields(requestFields)
processRequest(reqLog)
3. Use Appropriate Levels
// Trace: Very detailed (function entry/exit)
log.Trace("Entering function", map[string]interface{}{"args": args})

// Debug: Diagnostic information
log.Debug("Cache miss", map[string]interface{}{"key": key})

// Info: General information
log.Info("Request processed", map[string]interface{}{"duration_ms": 45})

// Warning: Unexpected but handled
log.Warning("Retry attempt", map[string]interface{}{"attempt": 2})

// Error: Error conditions
log.Error("Database query failed", nil, err)

// Fatal: Unrecoverable (exits program)
log.Fatal("Failed to start server", nil, err)

// Panic: Programming errors (panics)
log.Panic("Nil pointer", nil, err)
4. Cleanup Resources
// DO: Always close logger
log, err := logger.New(ctx)
if err != nil {
    return err
}
defer log.Close()  // Flushes buffers, closes files
5. Configure Early
// DO: Configure before logging
log, _ := logger.New(ctx)
log.SetOptions(opts)
log.SetLevel(level.InfoLevel)
log.SetFields(appFields)

// Now start logging
log.Info("Application started", nil)

API Reference

Logger Interface
type Logger interface {
    io.WriteCloser
    
    // Level management
    SetLevel(lvl level.Level)
    GetLevel() level.Level
    SetIOWriterLevel(lvl level.Level)
    GetIOWriterLevel() level.Level
    
    // Configuration
    SetOptions(opt *config.Options) error
    GetOptions() *config.Options
    
    // Fields
    SetFields(field fields.Fields)
    GetFields() fields.Fields
    
    // Cloning
    Clone() (Logger, error)
    
    // Instantiation
    // NewFrom creates a new logger based on an existing one
    // NewFrom(ctx context.Context, opt *config.Options, other ...any) (Logger, error)
    
    // Integrations
    GetStdLogger(lvl level.Level, flags int) *log.Logger
    SetStdLogger(lvl level.Level, flags int)
    SetSPF13Level(lvl level.Level, log *jww.Notepad)
    
    // Logging methods
    Debug(message string, data interface{}, args ...interface{})
    Info(message string, data interface{}, args ...interface{})
    Warning(message string, data interface{}, args ...interface{})
    Error(message string, data interface{}, args ...interface{})
    Fatal(message string, data interface{}, args ...interface{})
    Panic(message string, data interface{}, args ...interface{})
    Trace(message string, data interface{}, args ...interface{})
    Log(level level.Level, message string, data interface{}, args ...interface{})
    
    // Entry-based logging
    Entry(lvl level.Level, data interface{}, args ...interface{}) entry.Entry
    CheckIn(ent entry.Entry)
    CheckOut(ent entry.Entry)
}
Configuration

Options Structure:

type Options struct {
    LogLevel      level.Level    // Minimum log level
    LogFormatter  Format         // JSON or Text
    EnableConsole bool           // Console output
    EnableTrace   bool           // Source location tracking
    DisableStack  bool           // Disable stack traces
    LogFile       *OptionsFile   // File configuration
    LogSyslog     *OptionsSyslog // Syslog configuration
}

Sub-packages:

  • config: Configuration management
  • entry: Log entry handling
  • fields: Custom field injection
  • level: Log level enumeration
  • gorm: GORM integration
  • hashicorp: Hashicorp tools adapter
Log Levels

Level Hierarchy (highest to lowest severity):

  • PanicLevel (0): Calls panic() after logging
  • FatalLevel (1): Calls os.Exit(1) after logging
  • ErrorLevel (2): Error conditions
  • WarnLevel (3): Warning conditions
  • InfoLevel (4): Informational messages (default)
  • DebugLevel (5): Debug information
  • TraceLevel (6): Very verbose tracing
  • NullLevel (7): Disables logging
Error Handling
// CheckError: Conditional logging based on error presence
hasError := log.CheckError(
    level.ErrorLevel,  // Log level if error
    level.InfoLevel,   // Log level if no error
    "Operation result",
    err,
)

// LogDetails: Advanced logging with multiple errors
log.LogDetails(
    level.ErrorLevel,
    "Complex operation failed",
    data,
    []error{err1, err2},
    fields,
    args...,
)

Contributing

Contributions are welcome! Please follow these guidelines:

  1. Code Quality

    • Follow Go best practices and idioms
    • Maintain or improve code coverage (target: >85%)
    • Pass all tests including race detector
    • Use gofmt and golint
  2. AI Usage Policy

    • AI must NEVER be used to generate package code or core functionality
    • AI assistance is limited to:
      • Testing (writing and improving tests)
      • Debugging (troubleshooting and bug resolution)
      • Documentation (comments, README, TESTING.md)
    • All AI-assisted work must be reviewed and validated by humans
  3. Testing

    • Add tests for new features
    • Use Ginkgo v2 / Gomega for test framework
    • Ensure zero race conditions
    • Maintain coverage above 85%
  4. Documentation

    • Update GoDoc comments for public APIs
    • Add examples for new features
    • Update README.md if adding subpackages
    • Update TESTING.md if changing test structure
  5. Pull Request Process

    • Fork the repository
    • Create a feature branch
    • Write clear commit messages
    • Ensure all tests pass
    • Update documentation
    • Submit PR with description of changes

Improvements & Security

Planned Improvements:

  • Structured query language for programmatic log querying
  • Log sampling for high-volume scenarios
  • Enhanced context integration with distributed trace IDs
  • Prometheus metrics for log rate monitoring
  • Direct integration with log aggregators (Elasticsearch, Loki, Grafana)

Security Considerations:

  • All log outputs are protected by file permissions
  • Sensitive data should be filtered before logging
  • File rotation prevents disk exhaustion
  • Syslog connections support TLS for secure transmission

Reporting Security Issues: Please report security vulnerabilities privately via GitHub Security Advisories or by contacting the maintainer directly.


Resources

Internal Documentation
  • GoDoc - Complete API documentation
  • TESTING.md - Comprehensive testing guide
  • Individual subpackage READMEs (linked in Subpackages)
External References

AI Transparency

In compliance with EU AI Act Article 50.4: AI assistance was used for testing, documentation, and bug resolution under human supervision. All core functionality is human-designed and validated.


License

MIT License - See LICENSE file for details.

Copyright (c) 2025 Nicolas JUHEL


Maintained by: Nicolas JUHEL
Package: github.com/nabbar/golib/logger
Version: See releases for versioning

Documentation

Overview

Package logger provides a comprehensive, production-ready structured logging solution built on top of logrus with extensive customization options, multiple output destinations, and seamless integration with popular Go frameworks and libraries.

Overview

The logger package offers a unified logging interface that extends io.WriteCloser, making it compatible with any Go code expecting a standard writer. It supports:

  • Multiple simultaneous output destinations (stdout/stderr, files, syslog)
  • Level-based filtering with six standard levels (Debug, Info, Warn, Error, Fatal, Panic)
  • Structured logging with custom fields
  • Automatic caller tracking (file, line, function name, goroutine ID)
  • Thread-safe concurrent logging
  • Integration with standard Go log package
  • Integration with spf13/jwalterweatherman (Hugo/Cobra logger)
  • Integration with Gin web framework
  • Integration with GORM ORM

Design Philosophy

1. Flexibility: Support multiple output destinations and formats simultaneously 2. Performance: Async hook processing to minimize logging overhead 3. Safety: Thread-safe operations with proper synchronization 4. Compatibility: Seamless integration with existing logging infrastructure 5. Observability: Automatic context capture (caller info, stack traces, timestamps) 6. Standards: Follows structured logging best practices

Key Features

Structured Logging:

  • Custom fields injection at logger or entry level
  • Automatic field propagation in logger clones
  • Support for complex data types (maps, structs, etc.)
  • Standardized field names via logger/types package

Multiple Output Destinations:

  • Standard output (stdout/stderr) with color support
  • File logging with rotation support
  • Syslog integration (local and remote)
  • Custom writer hooks for specialized outputs

Level Management:

  • Six standard levels: Debug, Info, Warn, Error, Fatal, Panic
  • Per-output level configuration
  • Dynamic level changes without restart
  • Separate level for io.Writer interface

Context Awareness:

  • Goroutine ID tracking
  • Caller information (file, line, function)
  • Stack traces for error scenarios
  • Timestamp with nanosecond precision

Architecture

Package Structure:

┌──────────────────────────────────────────────────────────┐
│  github.com/nabbar/golib/logger                          │
├──────────────────────────────────────────────────────────┤
│                                                          │
│  Logger Interface (interface.go)                         │
│  ├─ Main logging methods (Debug, Info, Warn, Error...)   │
│  ├─ Configuration (SetOptions, SetLevel, SetFields)      │
│  ├─ Integrations (SetStdLogger, SetSPF13Level)           │
│  └─ Advanced (Clone, Entry, CheckError)                  │
│                                                          │
│  Implementation (log.go, manage.go, model.go)            │
│  ├─ Entry creation with automatic context                │
│  ├─ Hook management and lifecycle                        │
│  ├─ Formatter configuration                              │
│  └─ Thread-safe operations                               │
│                                                          │
│  I/O Integration (iowritecloser.go, golog.go)            │
│  ├─ io.WriteCloser implementation                        │
│  ├─ Standard log.Logger bridge                           │
│  └─ Message filtering                                    │
│                                                          │
│  Framework Integration (spf13.go)                        │
│  └─ jwalterweatherman (Hugo/Cobra) integration           │
│                                                          │
└──────────────────────────────────────────────────────────┘
                          │
      ┌───────────────────┼───────────────────┐
      │                   │                   │
      ▼                   ▼                   ▼
┌───────────┐       ┌───────────┐      ┌───────────┐
│  config   │       │   entry   │      │  fields   │
│  Package  │       │  Package  │      │  Package  │
├───────────┤       ├───────────┤      ├───────────┤
│ Options   │       │ Entry     │      │ Fields    │
│ Files     │       │ Builder   │      │ Manager   │
│ Syslog    │       │ Context   │      │ Clone     │
└───────────┘       └───────────┘      └───────────┘
      │                   │                   │
      └───────────────────┼───────────────────┘
                          │
      ┌───────────────────┼───────────────────────┐
      │                   │                       │
      ▼                   ▼                       ▼
┌───────────┐       ┌───────────┐         ┌────────────┐
│   level   │       │   types   │         │ Hook Impl  │
│  Package  │       │  Package  │         │  Packages  │
├───────────┤       ├───────────┤         ├────────────┤
│ Level     │       │ Hook      │         │ hookfile   │
│ Constants │       │ Interface │         │ hookstdout │
│ Converters│       │ Field     │         │ hookstderr │
└───────────┘       │ Constants │         │ hooksyslog │
                    └───────────┘         │ hookwriter │
                                          └────────────┘

Data Flow:

Application
     │
     ▼
Logger.Debug/Info/Warn/Error...
     │
     ▼
Entry Creation (newEntry)
     │
     ├─ Capture caller info (file, line, function)
     ├─ Capture goroutine ID
     ├─ Merge default fields
     ├─ Attach custom data/errors
     └─ Format message
     │
     ▼
Entry.Log()
     │
     ▼
Logrus Logger
     │
     ├─ Level filtering
     └─ Formatter application
     │
     ▼
Registered Hooks (parallel)
     │
     ├─ Hook.Fire() (synchronous, quick)
     ├─ Queue entry for Hook.Run() (async)
     │
     └─ Hook.Run() (background goroutine)
          │
          ├─ File writing
          ├─ Syslog transmission
          ├─ Network streaming
          └─ Custom processing

Performance Characteristics

Hook Processing:

  • Fire() method is synchronous but must be fast (<1ms recommended)
  • Run() method processes entries asynchronously in background goroutines
  • Buffered channels prevent logging from blocking application code
  • Graceful shutdown ensures all queued entries are processed

Memory Usage:

  • Logger instance: ~512 bytes (excluding hooks and fields)
  • Entry overhead: ~256 bytes per log entry
  • Hook buffers: Configurable channel sizes (default: 1000 entries)
  • Field storage: Minimal overhead with copy-on-write semantics

Thread Safety:

  • All Logger methods are thread-safe
  • Concurrent logging from multiple goroutines is supported
  • Internal state protected by sync.RWMutex
  • Atomic operations for simple state management

Logger Instantiation

The package provides two main ways to create a logger instance:

  1. New(ctx context.Context) Logger Creates a fresh logger instance with default settings (InfoLevel).

  2. NewFrom(ctx context.Context, opt *config.Options, other ...any) (Logger, error) Creates a new logger by cloning an existing one or using a configuration. This is useful for: - Inheriting fields and levels from a parent logger - Applying new configuration options on top of an existing logger - Lazy initialization via FuncLog

Use Cases

1. Application Logging

Basic structured logging for any Go application:

import (
    "context"
    "github.com/nabbar/golib/logger"
    "github.com/nabbar/golib/logger/config"
    "github.com/nabbar/golib/logger/level"
)

func main() {
    log := logger.New(context.Background())
    log.SetLevel(level.InfoLevel)

    err := log.SetOptions(&config.Options{
        Stdout: &config.OptionsStd{
            EnableTrace: true,
        },
    })
    if err != nil {
        panic(err)
    }
    defer log.Close()

    log.Info("Application started", nil)
    log.Debug("Debug information", map[string]interface{}{
        "module": "main",
        "pid":    os.Getpid(),
    })
}

2. HTTP Server Logging

Integration with web frameworks:

func setupLogging(router *gin.Engine, log logger.Logger) {
    router.Use(func(c *gin.Context) {
        start := time.Now()
        c.Next()
        latency := time.Since(start)

        log.Access(
            c.ClientIP(), c.GetString("user"),
            start, latency,
            c.Request.Method, c.Request.URL.Path, c.Request.Proto,
            c.Writer.Status(), int64(c.Writer.Size()),
        ).Log()
    })
}

3. File and Syslog Logging

Multiple simultaneous destinations:

log.SetOptions(&config.Options{
    Stdout: &config.OptionsStd{
        DisableStandard: false,
    },
    LogFile: []config.OptionsFile{
        {
            Filepath:    "/var/log/app/app.log",
            Create:      true,
            CreatePath:  true,
            EnableTrace: true,
        },
    },
    LogSyslog: []config.OptionsSyslog{
        {
            Network:  "udp",
            Host:     "localhost",
            Port:     514,
            Severity: syslog.LOG_INFO,
            Facility: syslog.LOG_USER,
        },
    },
})

4. Third-Party Integration

Standard library integration:

// Replace global standard logger
log.SetStdLogger(level.WarnLevel, stdlog.LstdFlags)
stdlog.Println("Now logged through custom logger")

// Create logger for third-party code
stdLogger := log.GetStdLogger(level.InfoLevel, stdlog.LstdFlags)
thirdPartyFunc(stdLogger)

5. Advanced Error Tracking

Structured error logging with context:

err := performOperation()
if log.CheckError(level.ErrorLevel, level.InfoLevel, "Operation result", err) {
    // Error was logged at ErrorLevel
    return err
}
// Success was logged at InfoLevel

// Or with full context:
entry := log.Entry(level.ErrorLevel, "Database operation failed")
entry.FieldAdd("query", query)
entry.FieldAdd("duration", duration)
entry.ErrorAdd(true, err)
entry.Log()

6. Inheriting Logger Context

Using NewFrom to create a sub-logger with inherited fields:

// Parent logger with common fields
parentLog := logger.New(ctx)
parentLog.SetFields(fields.NewFromMap(map[string]interface{}{
    "app": "my-app",
    "env": "prod",
}))

// Create child logger for a specific module
// It inherits "app" and "env" fields
childLog, _ := logger.NewFrom(ctx, nil, parentLog)
childLog.SetFields(fields.NewFromMap(map[string]interface{}{
    "module": "database",
}))

childLog.Info("Connecting to DB", nil)
// Log will contain: app=my-app, env=prod, module=database

Best Practices

DO:

  • Always call Close() when done with a logger (use defer)
  • Set appropriate log levels for production vs development
  • Use structured fields instead of string formatting when possible
  • Clone loggers instead of creating new ones for similar configurations
  • Use Entry() for complex logging with multiple fields
  • Set reasonable buffer sizes for file/syslog hooks

DON'T:

  • Don't log sensitive data (passwords, tokens, etc.)
  • Don't use Fatal or Panic unless absolutely necessary
  • Don't create multiple loggers when one with fields would suffice
  • Don't block in custom hook implementations
  • Don't ignore errors from SetOptions()
  • Don't use Debug level in production without careful consideration

Limitations

Hook Startup Timing:

  • Hooks start asynchronously when SetOptions() is called
  • There's a 500ms grace period to ensure hooks are running
  • Very early log entries might be delayed until hooks start

Log Ordering:

  • Multiple hooks may process entries in different orders
  • File writes are sequential per file but not across destinations
  • Use timestamp field for accurate event ordering

Fatal/Panic Behavior:

  • Fatal level calls os.Exit(1) after logging (deferred functions don't run)
  • Panic level triggers panic() (use with recover() for graceful handling)
  • Both levels may lose buffered log entries if exit is immediate

Memory Limits:

  • Default hook buffers can hold 1000 entries
  • Sustained high log volume can cause buffer overruns and dropped entries
  • Adjust buffer sizes based on expected load

Sub-Packages

  • config: Logger configuration structures and validation
  • entry: Log entry creation, manipulation, and lifecycle
  • fields: Structured field management with clone and merge operations
  • level: Log level definitions, conversions, and comparisons
  • types: Core types, interfaces, and field constants
  • hookfile: File output hook with rotation support
  • hookstdout: Standard output hook with color support
  • hookstderr: Standard error hook with color support
  • hooksyslog: Syslog hook with local and remote support
  • hookwriter: Generic io.Writer hook for custom outputs
  • gorm: GORM ORM logger integration
  • hashicorp: Hashicorp libraries logger integration (Vault, Consul, etc.)

External Dependencies

Core:

  • github.com/sirupsen/logrus: Underlying structured logging library
  • github.com/spf13/jwalterweatherman: Hugo/Cobra logger integration

Sub-packages may have additional dependencies for specialized functionality.

Compatibility

  • Go: Requires Go 1.24 or later (hookfile requires os.OpenRoot introduced in Go 1.24)
  • Logrus: Compatible with logrus v1.8+
  • Platforms: Linux, macOS, Windows
  • Architectures: amd64, arm64, arm, 386

Thread Safety:

  • All public methods are thread-safe
  • Safe for concurrent use from multiple goroutines
  • Internal state protected by appropriate synchronization primitives

See Also

Related packages in github.com/nabbar/golib:

  • github.com/nabbar/golib/context: Context management used by logger
  • github.com/nabbar/golib/ioutils/mapCloser: Closer management for hooks
  • github.com/nabbar/golib/semaphore: Concurrency control for logging

External references:

Example (AccessLog)

Example_accessLog demonstrates HTTP access logging.

package main

import (
	"context"
	"fmt"
	"time"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Simulate HTTP request logging
	logger.Access(
		"192.168.1.100",      // Remote address
		"john.doe",           // Remote user
		time.Now(),           // Request time
		150*time.Millisecond, // Latency
		"GET",                // Method
		"/api/users",         // Path
		"HTTP/1.1",           // Protocol
		200,                  // Status
		1024,                 // Size
	).Log()

	fmt.Println("Logged access entry")
}
Output:

Logged access entry
Example (BasicLogging)

Example_basicLogging demonstrates basic logging at different levels.

package main

import (
	"context"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	// Create logger
	logger := liblog.New(context.Background())
	defer logger.Close()

	// Configure for silent operation (no actual output in examples)
	logger.SetLevel(loglvl.DebugLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Log at different levels
	logger.Debug("Debug message", nil)
	logger.Info("Info message", nil)
	logger.Warning("Warning message", nil)
	logger.Error("Error message", nil)

	fmt.Println("Logged messages at multiple levels")
}
Output:

Logged messages at multiple levels
Example (CloningLogger)

Example_cloningLogger demonstrates creating independent logger clones.

package main

import (
	"context"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	logfld "github.com/nabbar/golib/logger/fields"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Set some fields on the original
	logger.SetFields(logfld.New(context.Background()).Add("logger", "main"))

	// Clone creates an independent copy
	clonedLogger, err := logger.Clone()
	if err != nil {
		panic(err)
	}
	defer clonedLogger.Close()

	// Modify the clone without affecting original
	clonedLogger.SetLevel(loglvl.DebugLevel)
	clonedLogger.SetFields(logfld.New(context.Background()).Add("logger", "worker"))

	logger.Info("Main logger message", nil)
	clonedLogger.Debug("Cloned logger message", nil)

	fmt.Println("Used cloned logger")
}
Output:

Used cloned logger
Example (ConcurrentLogging)

Example_concurrentLogging demonstrates thread-safe concurrent logging.

package main

import (
	"context"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Launch multiple goroutines
	done := make(chan bool)

	for i := 0; i < 5; i++ {
		go func(id int) {
			logger.Info("Message from goroutine", map[string]interface{}{
				"goroutine_id": id,
			})
			done <- true
		}(i)
	}

	// Wait for all goroutines
	for i := 0; i < 5; i++ {
		<-done
	}

	fmt.Println("Concurrent logging completed")
}
Output:

Concurrent logging completed
Example (EntryBuilder)

Example_entryBuilder demonstrates using the Entry builder pattern for complex logs.

package main

import (
	"context"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Build complex log entry
	entry := logger.Entry(loglvl.InfoLevel, "Database query executed")
	entry.FieldAdd("query", "SELECT * FROM users")
	entry.FieldAdd("duration", "45ms")
	entry.FieldAdd("rows", 127)
	entry.Log()

	fmt.Println("Logged with entry builder")
}
Output:

Logged with entry builder
Example (ErrorChecking)

Example_errorChecking demonstrates the CheckError convenience method.

package main

import (
	"context"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Simulate an operation that might fail
	performOperation := func() error {
		return nil // Success
	}

	err := performOperation()
	if logger.CheckError(loglvl.ErrorLevel, loglvl.InfoLevel, "Operation completed", err) {
		fmt.Println("Error occurred")
		return
	}

	fmt.Println("Operation successful")
}
Output:

Operation successful
Example (FilteringMessages)

Example_filteringMessages demonstrates filtering log messages.

package main

import (
	"context"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Set up filters to drop messages containing certain patterns
	logger.SetIOWriterFilter("password", "secret", "token")

	// These messages will be filtered out
	_, _ = logger.Write([]byte("User password is 12345"))
	_, _ = logger.Write([]byte("API token: abc123"))

	// This message will pass through
	_, _ = logger.Write([]byte("User logged in successfully"))

	fmt.Println("Filtering configured")
}
Output:

Filtering configured
Example (FormattedMessages)

Example_formattedMessages demonstrates using format strings in log messages.

package main

import (
	"context"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Format strings work like fmt.Sprintf
	userID := 42
	username := "john.doe"
	duration := 150

	logger.Info("User %s (ID: %d) processed in %dms", nil, username, userID, duration)

	fmt.Println("Logged formatted message")
}
Output:

Logged formatted message
Example (IoWriterIntegration)

Example_ioWriterIntegration demonstrates using logger as an io.Writer.

package main

import (
	"context"
	"fmt"
	"io"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Set the level for io.Writer interface
	logger.SetIOWriterLevel(loglvl.WarnLevel)

	// Use as io.Writer
	_, _ = io.WriteString(logger, "Message written through io.Writer")

	fmt.Println("Used as io.Writer")
}
Output:

Used as io.Writer
Example (LevelManagement)

Example_levelManagement demonstrates dynamic level changes.

package main

import (
	"context"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Start with Info level
	logger.SetLevel(loglvl.InfoLevel)
	logger.Debug("This won't be logged", nil)
	logger.Info("This will be logged", nil)

	// Change to Debug level
	logger.SetLevel(loglvl.DebugLevel)
	logger.Debug("Now this will be logged", nil)

	currentLevel := logger.GetLevel()
	fmt.Printf("Current level: %s\n", currentLevel.String())
}
Output:

Current level: Debug
Example (LogDetails)

Example_logDetails demonstrates the most flexible logging method.

package main

import (
	"context"
	"errors"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	logfld "github.com/nabbar/golib/logger/fields"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// LogDetails gives full control
	err1 := errors.New("first error")
	err2 := errors.New("second error")
	errs := []error{err1, err2}

	fields := logfld.New(context.Background())
	fields.Add("operation", "database_migration")
	fields.Add("step", 3)

	data := map[string]interface{}{
		"tables_affected": 5,
		"records_updated": 1523,
	}

	logger.LogDetails(
		loglvl.ErrorLevel,
		"Migration encountered errors",
		data,
		errs,
		fields,
	)

	fmt.Println("Logged detailed entry")
}
Output:

Logged detailed entry
Example (MultipleErrors)

Example_multipleErrors demonstrates logging multiple errors.

package main

import (
	"context"
	"errors"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.ErrorLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Multiple errors can be logged together
	err1 := errors.New("connection timeout")
	err2 := errors.New("retry limit exceeded")

	if logger.CheckError(loglvl.ErrorLevel, loglvl.NilLevel, "Operation failed", err1, err2) {
		fmt.Println("Multiple errors logged")
	}
}
Output:

Multiple errors logged
Example (StandardLoggerIntegration)

Example_standardLoggerIntegration demonstrates using logger with standard log package.

package main

import (
	"context"
	"fmt"
	"log"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Get a standard logger for third-party code
	stdLogger := logger.GetStdLogger(loglvl.InfoLevel, log.LstdFlags)

	// Use it like standard log.Logger
	stdLogger.Println("Message from standard logger")
	stdLogger.Printf("Formatted: %s", "message")

	fmt.Println("Used standard logger integration")
}
Output:

Used standard logger integration
Example (StructuredLogging)

Example_structuredLogging demonstrates logging with structured data.

package main

import (
	"context"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Log with structured data
	userData := map[string]interface{}{
		"user_id": 12345,
		"email":   "user@example.com",
		"role":    "admin",
	}

	logger.Info("User logged in", userData)

	fmt.Println("Logged structured data")
}
Output:

Logged structured data
Example (WithFields)

Example_withFields demonstrates using default fields that apply to all log entries.

package main

import (
	"context"
	"fmt"

	liblog "github.com/nabbar/golib/logger"
	logcfg "github.com/nabbar/golib/logger/config"

	logfld "github.com/nabbar/golib/logger/fields"

	loglvl "github.com/nabbar/golib/logger/level"
)

func main() {
	logger := liblog.New(context.Background())
	defer logger.Close()

	logger.SetLevel(loglvl.InfoLevel)
	_ = logger.SetOptions(&logcfg.Options{
		Stdout: &logcfg.OptionsStd{
			DisableStandard: true,
		},
	})

	// Set default fields
	fields := logfld.New(context.Background())
	fields.Add("service", "api")
	fields.Add("environment", "production")
	fields.Add("version", "1.2.3")
	logger.SetFields(fields)

	// These fields will be included in all log entries
	logger.Info("Request processed", nil)
	logger.Info("Response sent", nil)

	fmt.Println("Logged with default fields")
}
Output:

Logged with default fields

Index

Examples

Constants

View Source
const (
	KeyCancel
)

Variables

This section is empty.

Functions

This section is empty.

Types

type FuncLog added in v1.7.0

type FuncLog func() Logger

FuncLog is a function type that returns a Logger instance. This is used for dependency injection and lazy initialization of loggers.

type Logger added in v1.7.0

type Logger interface {
	io.WriteCloser

	//SetLevel allow to change the minimal level of log message
	SetLevel(lvl loglvl.Level)

	//GetLevel return the minimal level of log message
	GetLevel() loglvl.Level

	//SetIOWriterLevel allow to change the minimal level of log message for io.WriterCloser interface
	SetIOWriterLevel(lvl loglvl.Level)

	//GetIOWriterLevel return the minimal level of log message for io.WriterCloser interface
	GetIOWriterLevel() loglvl.Level

	// SetIOWriterFilter allow to filter message that contained the given pattern.
	// When received any message, if one pattern is found, the log is drop.
	// If the given pattern is empty, the pattern list is truncated to no one pattern.
	SetIOWriterFilter(pattern ...string)

	// SetIOWriterFilter allow to add a filter pattern into the filter message pattern list.
	AddIOWriterFilter(pattern ...string)

	//SetOptions allow to set or update the options for the logger
	SetOptions(opt *logcfg.Options) error

	//GetOptions return the options for the logger
	GetOptions() *logcfg.Options

	//SetFields allow to set or update the default fields for all logger entry
	// Fields are custom information added into log message
	SetFields(field logfld.Fields)

	//GetFields return the default fields for all logger entry
	// Fields are custom information added into log message
	GetFields() logfld.Fields

	//Clone allow to duplicate the logger with a copy of the logger
	Clone() (Logger, error)

	//SetSPF13Level allow to plus spf13 logger (jww) to this logger
	SetSPF13Level(lvl loglvl.Level, log *jww.Notepad)

	//GetStdLogger return a golang log.logger instance linked with this main logger.
	GetStdLogger(lvl loglvl.Level, logFlags int) *log.Logger

	//SetStdLogger force the default golang log.logger instance linked with this main logger.
	SetStdLogger(lvl loglvl.Level, logFlags int)

	//Debug add an entry with DebugLevel to the logger
	Debug(message string, data interface{}, args ...interface{})

	//Info add an entry with InfoLevel to the logger
	Info(message string, data interface{}, args ...interface{})

	//Warning add an entry with WarnLevel to the logger
	Warning(message string, data interface{}, args ...interface{})

	//Error add an entry with ErrorLevel level to the logger
	Error(message string, data interface{}, args ...interface{})

	//Fatal add an entry with FatalLevel to the logger
	//The function will break the process (os.exit) after log entry.
	Fatal(message string, data interface{}, args ...interface{})

	//Panic add an entry with PanicLevel level to the logger
	//The function will break the process (os.exit) after log entry.
	Panic(message string, data interface{}, args ...interface{})

	//LogDetails add an entry to the logger
	LogDetails(lvl loglvl.Level, message string, data interface{}, err []error, fields logfld.Fields, args ...interface{})

	//CheckError will check if a not nil error is given and if yes, will add an entry to the logger.
	// Othwise if the lvlOK is given (and not NilLevel) the function will add entry and said ok
	CheckError(lvlKO, lvlOK loglvl.Level, message string, err ...error) bool

	//Entry will return an entry struct to manage it (set gin context, add fields, log the entry...)
	Entry(lvl loglvl.Level, message string, args ...interface{}) logent.Entry

	//Access will return an entry struct to store info level access log message
	Access(remoteAddr, remoteUser string, localtime time.Time, latency time.Duration, method, request, proto string, status int, size int64) logent.Entry
}

Logger is the main interface for structured logging operations. It extends io.WriteCloser to allow using the logger as a standard Go writer. The logger supports multiple output destinations (file, syslog, stdout/stderr), level-based filtering, custom fields injection, and integration with popular frameworks.

func New added in v1.7.0

func New(ctx context.Context) Logger

New returns a new Logger instance with the given context. The context is used to configure the logger fields. The logger level is set to InfoLevel by default. The returned logger can be used to log messages at different levels. The logger can also be used to set the default golang log.logger instance.

func NewFrom added in v1.19.2

func NewFrom(ctx context.Context, opt *logcfg.Options, other ...any) (Logger, error)

NewFrom creates a new Logger instance based on an existing logger or configuration. It allows cloning an existing logger's state (level, fields, options) and applying new options.

Parameters:

  • ctx: The context for the new logger.
  • opt: Optional configuration options to apply. If nil, defaults are used.
  • other: Variadic list of sources to copy state from.

The other value will be used only if matching non-nil value of:

  • Logger: Copies level, fields, and options.
  • FuncLog: Executes the function and uses the returned Logger.

The function iterates through 'other' arguments and uses the last valid Logger found as the base. If a base logger is found, its level and fields are copied to the new logger. If options are provided in 'opt', they are merged with the base logger's options (if any).

Returns:

  • Logger: A new initialized Logger instance.
  • error: An error if applying options fails, otherwise nil.

Directories

Path Synopsis
Package config provides configuration structures and validation for the logger package.
Package config provides configuration structures and validation for the logger package.
Package entry provides a flexible, chainable logger entry wrapper for structured logging with logrus.
Package entry provides a flexible, chainable logger entry wrapper for structured logging with logrus.
Package fields provides a thread-safe, context-aware structured logging fields management system that seamlessly integrates with logrus and Go's standard context package.
Package fields provides a thread-safe, context-aware structured logging fields management system that seamlessly integrates with logrus and Go's standard context package.
Package gorm provides a thread-safe adapter that bridges golib's logging system with GORM v2's logger interface.
Package gorm provides a thread-safe adapter that bridges golib's logging system with GORM v2's logger interface.
Package hashicorp provides a thread-safe adapter that bridges golib's logging system with HashiCorp's hclog interface.
Package hashicorp provides a thread-safe adapter that bridges golib's logging system with HashiCorp's hclog interface.
Package hookfile provides file-based logging hooks for logrus.
Package hookfile provides file-based logging hooks for logrus.
Package hookstderr provides a logrus hook for writing log entries to standard error (stderr) with configurable field filtering and formatting options.
Package hookstderr provides a logrus hook for writing log entries to standard error (stderr) with configurable field filtering and formatting options.
Package hookstdout provides a logrus hook for writing log entries to stdout with configurable field filtering, formatting options, and cross-platform color support.
Package hookstdout provides a logrus hook for writing log entries to stdout with configurable field filtering, formatting options, and cross-platform color support.
Package hooksyslog provides a robust and flexible logrus hook for writing log entries to syslog endpoints.
Package hooksyslog provides a robust and flexible logrus hook for writing log entries to syslog endpoints.
Package hookwriter provides a logrus hook for writing log entries to custom io.Writer instances with configurable field filtering and formatting options.
Package hookwriter provides a logrus hook for writing log entries to custom io.Writer instances with configurable field filtering and formatting options.
Package level defines log severity levels with conversions and parsing capabilities.
Package level defines log severity levels with conversions and parsing capabilities.
Package types provides core types, interfaces, and constants for the logger subsystem.
Package types provides core types, interfaces, and constants for the logger subsystem.

Jump to

Keyboard shortcuts

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