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
- Variables
- func AddWriter(writer io.Writer) error
- func Debug(args ...any)
- func DebugCtx(ctx context.Context, args ...any)
- func DebugWith(msg string, fields ...Field)
- func DebugWithCtx(ctx context.Context, msg string, fields ...Field)
- func Debugf(format string, args ...any)
- func DebugfCtx(ctx context.Context, format string, args ...any)
- func DefaultHookErrorHandler(event HookEvent, hookCtx *HookContext, err error)
- func DefaultInitError() error
- func DefaultUsedFallback() bool
- func Error(args ...any)
- func ErrorCtx(ctx context.Context, args ...any)
- func ErrorWith(msg string, fields ...Field)
- func ErrorWithCtx(ctx context.Context, msg string, fields ...Field)
- func Errorf(format string, args ...any)
- func ErrorfCtx(ctx context.Context, format string, args ...any)
- func Exit(data ...any)
- func Exitf(format string, args ...any)
- func Fatal(args ...any)
- func FatalCtx(ctx context.Context, args ...any)
- func FatalWith(msg string, fields ...Field)
- func FatalWithCtx(ctx context.Context, msg string, fields ...Field)
- func Fatalf(format string, args ...any)
- func FatalfCtx(ctx context.Context, format string, args ...any)
- func Flush() error
- func GetRequestID(ctx context.Context) string
- func GetSpanID(ctx context.Context) string
- func GetTraceID(ctx context.Context) string
- func Info(args ...any)
- func InfoCtx(ctx context.Context, args ...any)
- func InfoWith(msg string, fields ...Field)
- func InfoWithCtx(ctx context.Context, msg string, fields ...Field)
- func Infof(format string, args ...any)
- func InfofCtx(ctx context.Context, format string, args ...any)
- func IsDebugEnabled() bool
- func IsErrorEnabled() bool
- func IsFatalEnabled() bool
- func IsInfoEnabled() bool
- func IsLevelEnabled(level LogLevel) bool
- func IsWarnEnabled() bool
- func JSON(data ...any)
- func JSONF(format string, args ...any)
- func Log(level LogLevel, args ...any)
- func LogCtx(ctx context.Context, level LogLevel, args ...any)
- func LogWith(level LogLevel, msg string, fields ...Field)
- func LogWithCtx(ctx context.Context, level LogLevel, msg string, fields ...Field)
- func Logf(level LogLevel, format string, args ...any)
- func LogfCtx(ctx context.Context, level LogLevel, format string, args ...any)
- func Must2[T1 any, T2 any](val1 T1, val2 T2, err error) (T1, T2)
- func MustVal[T any](val T, err error) T
- func Print(args ...any)
- func Printf(format string, args ...any)
- func Println(args ...any)
- func RemoveWriter(writer io.Writer) error
- func SetDefault(logger *Logger)
- func SetLevel(level LogLevel)
- func SetSampling(config *SamplingConfig)
- func Text(data ...any)
- func Textf(format string, args ...any)
- func Warn(args ...any)
- func WarnCtx(ctx context.Context, args ...any)
- func WarnWith(msg string, fields ...Field)
- func WarnWithCtx(ctx context.Context, msg string, fields ...Field)
- func Warnf(format string, args ...any)
- func WarnfCtx(ctx context.Context, format string, args ...any)
- func WithRequestID(ctx context.Context, requestID string) context.Context
- func WithSpanID(ctx context.Context, spanID string) context.Context
- func WithTraceID(ctx context.Context, traceID string) context.Context
- func WriterCount() int
- type AuditConfig
- type AuditEvent
- type AuditEventType
- type AuditLogger
- func (al *AuditLogger) Close() error
- func (al *AuditLogger) Log(event AuditEvent)
- func (al *AuditLogger) LogIntegrityViolation(message string, metadata map[string]any)
- func (al *AuditLogger) LogPathTraversalAttempt(path, message string)
- func (al *AuditLogger) LogRateLimitExceeded(message string, metadata map[string]any)
- func (al *AuditLogger) LogReDoSAttempt(pattern, message string)
- func (al *AuditLogger) LogSecurityViolation(violationType string, message string, metadata map[string]any)
- func (al *AuditLogger) LogSensitiveDataRedaction(pattern, field, message string)
- func (al *AuditLogger) Stats() AuditStats
- type AuditSeverity
- type AuditStats
- type AuditVerificationResult
- type BufferedWriter
- type Config
- type ConfigurableLogger
- type ContextExtractor
- type ContextExtractorRegistry
- type ContextKey
- type ContextLogger
- type CoreLogger
- type FatalHandler
- type Field
- func Any(key string, value any) Field
- func Bool(key string, value bool) Field
- func Duration(key string, value time.Duration) Field
- func Err(err error) Field
- func ErrWithKey(key string, err error) Field
- func ErrWithStack(err error) Field
- func Float32(key string, value float32) Field
- func Float64(key string, value float64) Field
- func Int(key string, value int) Field
- func Int8(key string, value int8) Field
- func Int16(key string, value int16) Field
- func Int32(key string, value int32) Field
- func Int64(key string, value int64) Field
- func NamedErr(key string, err error) Field
- func String(key, value string) Field
- func Time(key string, value time.Time) Field
- func Uint(key string, value uint) Field
- func Uint8(key string, value uint8) Field
- func Uint16(key string, value uint16) Field
- func Uint32(key string, value uint32) Field
- func Uint64(key string, value uint64) Field
- type FieldNamingConvention
- type FieldValidationConfig
- type FieldValidationMode
- type FileConfig
- type FileWriter
- type FileWriterConfig
- type FilterStats
- type Flusher
- type HashAlgorithm
- type Hook
- type HookBuilder
- func (b *HookBuilder) AfterLog(hook Hook) *HookBuilder
- func (b *HookBuilder) BeforeLog(hook Hook) *HookBuilder
- func (b *HookBuilder) Build() *HookRegistry
- func (b *HookBuilder) OnClose(hook Hook) *HookBuilder
- func (b *HookBuilder) OnError(hook Hook) *HookBuilder
- func (b *HookBuilder) OnFilter(hook Hook) *HookBuilder
- func (b *HookBuilder) OnRotate(hook Hook) *HookBuilder
- type HookContext
- type HookErrorHandler
- type HookErrorInfo
- type HookErrorRecorder
- type HookEvent
- type HookRegistry
- func (r *HookRegistry) Add(event HookEvent, hook Hook)
- func (r *HookRegistry) Clear()
- func (r *HookRegistry) ClearFor(event HookEvent)
- func (r *HookRegistry) Clone() *HookRegistry
- func (r *HookRegistry) Count() int
- func (r *HookRegistry) CountFor(event HookEvent) int
- func (r *HookRegistry) Remove(event HookEvent)
- func (r *HookRegistry) SetErrorHandler(handler HookErrorHandler)
- func (r *HookRegistry) Trigger(ctx context.Context, event HookEvent, hookCtx *HookContext) (err error)
- type IntegrityConfig
- type IntegritySigner
- func (s *IntegritySigner) GetSequence() uint64
- func (s *IntegritySigner) ResetSequence()
- func (s *IntegritySigner) Sign(message string) string
- func (s *IntegritySigner) SignFields(message string, fields []Field) string
- func (s *IntegritySigner) Stats() IntegrityStats
- func (s *IntegritySigner) Verify(entry string) (*LogIntegrity, error)
- type IntegrityStats
- type JSONFieldNames
- type JSONOptions
- type LevelLogger
- type LevelResolver
- type LogFormat
- type LogIntegrity
- type LogLevel
- type LogProvider
- type Logger
- func Default() *Logger
- func DefaultWithErr() (*Logger, error)
- func Must(cfgs ...*Config) *Logger
- func MustNew(cfgs ...*Config) *Logger
- func MustToAll(filename ...string) *Logger
- func MustToAllJSON(filename ...string) *Logger
- func MustToConsole() *Logger
- func MustToFile(filename ...string) *Logger
- func MustToJSONFile(filename ...string) *Logger
- func MustToWriter(w io.Writer) *Logger
- func MustToWriters(writers ...io.Writer) *Logger
- func New(cfgs ...*Config) (*Logger, error)
- func ToAll(filename ...string) (*Logger, error)
- func ToAllJSON(filename ...string) (*Logger, error)
- func ToConsole() (*Logger, error)
- func ToFile(filename ...string) (*Logger, error)
- func ToJSONFile(filename ...string) (*Logger, error)
- func ToWriter(w io.Writer) (*Logger, error)
- func ToWriters(writers ...io.Writer) (*Logger, error)
- func (l *Logger) ActiveFilterGoroutines() int32
- func (l *Logger) AddContextExtractor(extractor ContextExtractor) error
- func (l *Logger) AddHook(event HookEvent, hook Hook) error
- func (l *Logger) AddWriter(writer io.Writer) error
- func (l *Logger) Close() error
- func (l *Logger) Debug(args ...any)
- func (l *Logger) DebugCtx(ctx context.Context, args ...any)
- func (l *Logger) DebugWith(msg string, fields ...Field)
- func (l *Logger) DebugWithCtx(ctx context.Context, msg string, fields ...Field)
- func (l *Logger) Debugf(format string, args ...any)
- func (l *Logger) DebugfCtx(ctx context.Context, format string, args ...any)
- func (l *Logger) Error(args ...any)
- func (l *Logger) ErrorCtx(ctx context.Context, args ...any)
- func (l *Logger) ErrorWith(msg string, fields ...Field)
- func (l *Logger) ErrorWithCtx(ctx context.Context, msg string, fields ...Field)
- func (l *Logger) Errorf(format string, args ...any)
- func (l *Logger) ErrorfCtx(ctx context.Context, format string, args ...any)
- func (l *Logger) Fatal(args ...any)
- func (l *Logger) FatalCtx(ctx context.Context, args ...any)
- func (l *Logger) FatalWith(msg string, fields ...Field)
- func (l *Logger) FatalWithCtx(ctx context.Context, msg string, fields ...Field)
- func (l *Logger) Fatalf(format string, args ...any)
- func (l *Logger) FatalfCtx(ctx context.Context, format string, args ...any)
- func (l *Logger) Flush() error
- func (l *Logger) GetContextExtractors() []ContextExtractor
- func (l *Logger) GetFieldValidation() *FieldValidationConfig
- func (l *Logger) GetHooks() *HookRegistry
- func (l *Logger) GetLevel() LogLevel
- func (l *Logger) GetLevelResolver() LevelResolver
- func (l *Logger) GetSampling() *SamplingConfig
- func (l *Logger) GetSecurityConfig() *SecurityConfig
- func (l *Logger) Info(args ...any)
- func (l *Logger) InfoCtx(ctx context.Context, args ...any)
- func (l *Logger) InfoWith(msg string, fields ...Field)
- func (l *Logger) InfoWithCtx(ctx context.Context, msg string, fields ...Field)
- func (l *Logger) Infof(format string, args ...any)
- func (l *Logger) InfofCtx(ctx context.Context, format string, args ...any)
- func (l *Logger) IsClosed() bool
- func (l *Logger) IsDebugEnabled() bool
- func (l *Logger) IsErrorEnabled() bool
- func (l *Logger) IsFatalEnabled() bool
- func (l *Logger) IsInfoEnabled() bool
- func (l *Logger) IsLevelEnabled(level LogLevel) bool
- func (l *Logger) IsWarnEnabled() bool
- func (l *Logger) JSON(data ...any)
- func (l *Logger) JSONF(format string, args ...any)
- func (l *Logger) Log(level LogLevel, args ...any)
- func (l *Logger) LogCtx(ctx context.Context, level LogLevel, args ...any)
- func (l *Logger) LogWith(level LogLevel, msg string, fields ...Field)
- func (l *Logger) LogWithCtx(ctx context.Context, level LogLevel, msg string, fields ...Field)
- func (l *Logger) Logf(level LogLevel, format string, args ...any)
- func (l *Logger) LogfCtx(ctx context.Context, level LogLevel, format string, args ...any)
- func (l *Logger) MustAddContextExtractor(extractor ContextExtractor)
- func (l *Logger) MustAddHook(event HookEvent, hook Hook)
- func (l *Logger) MustSetContextExtractors(extractors ...ContextExtractor)
- func (l *Logger) MustSetHooks(registry *HookRegistry)
- func (l *Logger) Print(args ...any)
- func (l *Logger) Printf(format string, args ...any)
- func (l *Logger) Println(args ...any)
- func (l *Logger) RemoveWriter(writer io.Writer) error
- func (l *Logger) SetContextExtractors(extractors ...ContextExtractor) error
- func (l *Logger) SetFieldValidation(config *FieldValidationConfig)
- func (l *Logger) SetHooks(registry *HookRegistry) error
- func (l *Logger) SetLevel(level LogLevel) error
- func (l *Logger) SetLevelResolver(resolver LevelResolver)
- func (l *Logger) SetSampling(config *SamplingConfig)
- func (l *Logger) SetSecurityConfig(config *SecurityConfig)
- func (l *Logger) SetWriteErrorHandler(handler WriteErrorHandler)
- func (l *Logger) Shutdown(ctx context.Context) error
- func (l *Logger) Text(data ...any)
- func (l *Logger) Textf(format string, args ...any)
- func (l *Logger) WaitForFilterGoroutines(timeout time.Duration) bool
- func (l *Logger) Warn(args ...any)
- func (l *Logger) WarnCtx(ctx context.Context, args ...any)
- func (l *Logger) WarnWith(msg string, fields ...Field)
- func (l *Logger) WarnWithCtx(ctx context.Context, msg string, fields ...Field)
- func (l *Logger) Warnf(format string, args ...any)
- func (l *Logger) WarnfCtx(ctx context.Context, format string, args ...any)
- func (l *Logger) WithField(key string, value any) *LoggerEntry
- func (l *Logger) WithFields(fields ...Field) *LoggerEntry
- func (l *Logger) WriterCount() int
- type LoggerEntry
- func (e *LoggerEntry) Debug(args ...any)
- func (e *LoggerEntry) DebugCtx(ctx context.Context, args ...any)
- func (e *LoggerEntry) DebugWith(msg string, fields ...Field)
- func (e *LoggerEntry) DebugWithCtx(ctx context.Context, msg string, fields ...Field)
- func (e *LoggerEntry) Debugf(format string, args ...any)
- func (e *LoggerEntry) DebugfCtx(ctx context.Context, format string, args ...any)
- func (e *LoggerEntry) Error(args ...any)
- func (e *LoggerEntry) ErrorCtx(ctx context.Context, args ...any)
- func (e *LoggerEntry) ErrorWith(msg string, fields ...Field)
- func (e *LoggerEntry) ErrorWithCtx(ctx context.Context, msg string, fields ...Field)
- func (e *LoggerEntry) Errorf(format string, args ...any)
- func (e *LoggerEntry) ErrorfCtx(ctx context.Context, format string, args ...any)
- func (e *LoggerEntry) Fatal(args ...any)
- func (e *LoggerEntry) FatalCtx(ctx context.Context, args ...any)
- func (e *LoggerEntry) FatalWith(msg string, fields ...Field)
- func (e *LoggerEntry) FatalWithCtx(ctx context.Context, msg string, fields ...Field)
- func (e *LoggerEntry) Fatalf(format string, args ...any)
- func (e *LoggerEntry) FatalfCtx(ctx context.Context, format string, args ...any)
- func (e *LoggerEntry) Info(args ...any)
- func (e *LoggerEntry) InfoCtx(ctx context.Context, args ...any)
- func (e *LoggerEntry) InfoWith(msg string, fields ...Field)
- func (e *LoggerEntry) InfoWithCtx(ctx context.Context, msg string, fields ...Field)
- func (e *LoggerEntry) Infof(format string, args ...any)
- func (e *LoggerEntry) InfofCtx(ctx context.Context, format string, args ...any)
- func (e *LoggerEntry) Log(level LogLevel, args ...any)
- func (e *LoggerEntry) LogCtx(ctx context.Context, level LogLevel, args ...any)
- func (e *LoggerEntry) LogWith(level LogLevel, msg string, fields ...Field)
- func (e *LoggerEntry) LogWithCtx(ctx context.Context, level LogLevel, msg string, fields ...Field)
- func (e *LoggerEntry) Logf(level LogLevel, format string, args ...any)
- func (e *LoggerEntry) LogfCtx(ctx context.Context, level LogLevel, format string, args ...any)
- func (e *LoggerEntry) Print(args ...any)
- func (e *LoggerEntry) Printf(format string, args ...any)
- func (e *LoggerEntry) Println(args ...any)
- func (e *LoggerEntry) Warn(args ...any)
- func (e *LoggerEntry) WarnCtx(ctx context.Context, args ...any)
- func (e *LoggerEntry) WarnWith(msg string, fields ...Field)
- func (e *LoggerEntry) WarnWithCtx(ctx context.Context, msg string, fields ...Field)
- func (e *LoggerEntry) Warnf(format string, args ...any)
- func (e *LoggerEntry) WarnfCtx(ctx context.Context, format string, args ...any)
- func (e *LoggerEntry) WithField(key string, value any) *LoggerEntry
- func (e *LoggerEntry) WithFields(fields ...Field) *LoggerEntry
- type LoggerError
- type MultiWriter
- type MultiWriterError
- type SamplingConfig
- type SecurityConfig
- type SecurityLevel
- type SensitiveDataFilter
- func NewBasicSensitiveDataFilter() *SensitiveDataFilter
- func NewCustomSensitiveDataFilter(patterns ...string) (*SensitiveDataFilter, error)
- func NewEmptySensitiveDataFilter() *SensitiveDataFilter
- func NewFullSensitiveDataFilter() *SensitiveDataFilter
- func NewSensitiveDataFilter() *SensitiveDataFilter
- func (f *SensitiveDataFilter) ActiveGoroutineCount() int32
- func (f *SensitiveDataFilter) AddPattern(pattern string) error
- func (f *SensitiveDataFilter) AddPatterns(patterns ...string) error
- func (f *SensitiveDataFilter) ClearPatterns()
- func (f *SensitiveDataFilter) Clone() *SensitiveDataFilter
- func (f *SensitiveDataFilter) Close() bool
- func (f *SensitiveDataFilter) Disable()
- func (f *SensitiveDataFilter) Enable()
- func (f *SensitiveDataFilter) Filter(input string) string
- func (f *SensitiveDataFilter) FilterFieldValue(key string, value any) any
- func (f *SensitiveDataFilter) FilterValueRecursive(key string, value any) any
- func (f *SensitiveDataFilter) GetFilterStats() FilterStats
- func (f *SensitiveDataFilter) IsEnabled() bool
- func (f *SensitiveDataFilter) PatternCount() int
- func (f *SensitiveDataFilter) WaitForGoroutines(timeout time.Duration) bool
- type WriteErrorHandler
- type WriterError
Constants ¶
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 )
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 )
const ( MaxBackupCount = 1000 MaxFileSizeMB = 10240 )
const ( DefaultMaxSizeMB = 100 DefaultMaxBackups = 10 DefaultMaxAge = 30 * 24 * time.Hour DefaultBufferSizeKB = 1 MaxBufferSizeKB = 10 * 1024 AutoFlushThreshold = 2 AutoFlushInterval = 100 * time.Millisecond )
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 )
const ( DefaultTimeFormat = "2006-01-02T15:04:05Z07:00" DevTimeFormat = "15:04:05.000" )
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 )
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 )
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.
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().
const ( LevelDebug = internal.LevelDebug LevelInfo = internal.LevelInfo LevelWarn = internal.LevelWarn LevelError = internal.LevelError LevelFatal = internal.LevelFatal )
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 )
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 )
const DefaultLogPath = "logs/app.log"
DefaultLogPath is the default path for log files.
const (
// DirPermissions is the permission mode for creating directories (rwx------).
DirPermissions = 0700
)
File system permission constants.
Variables ¶
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 DebugCtx ¶ added in v1.2.0
DebugCtx logs a debug message with context support using the default logger.
func DebugWithCtx ¶ added in v1.2.0
DebugWithCtx logs a structured debug message with context support using the default logger.
func DebugfCtx ¶ added in v1.2.0
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 ErrorCtx ¶ added in v1.2.0
ErrorCtx logs an error message with context support using the default logger.
func ErrorWithCtx ¶ added in v1.2.0
ErrorWithCtx logs a structured error message with context support using the default logger.
func ErrorfCtx ¶ added in v1.2.0
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
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
FatalCtx logs a fatal message with context support using the default logger.
func FatalWith ¶
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
FatalWithCtx logs a structured fatal message with context support using the default logger.
func Fatalf ¶
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
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
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
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
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 InfoCtx ¶ added in v1.2.0
InfoCtx logs an info message with context support using the default logger.
func InfoWithCtx ¶ added in v1.2.0
InfoWithCtx logs a structured info message with context support using the default logger.
func InfofCtx ¶ added in v1.2.0
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
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
JSONF outputs formatted data as compact JSON to stdout with caller info for debugging.
func LogCtx ¶ added in v1.2.0
LogCtx logs a message at the specified level with context using the default logger.
func LogWith ¶ added in v1.2.0
LogWith logs a structured message at the specified level using the default logger.
func LogWithCtx ¶ added in v1.2.0
LogWithCtx logs a structured message at the specified level with context using the default logger.
func Logf ¶ added in v1.2.0
Logf logs a formatted message at the specified level using the default logger.
func LogfCtx ¶ added in v1.2.0
LogfCtx logs a formatted message at the specified level with context using the default logger.
func Must2 ¶ added in v1.2.0
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
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
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
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 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
Textf outputs formatted data as pretty-printed format to stdout for debugging.
func WarnCtx ¶ added in v1.2.0
WarnCtx logs a warning message with context support using the default logger.
func WarnWithCtx ¶ added in v1.2.0
WarnWithCtx logs a structured warning message with context support using the default logger.
func WarnfCtx ¶ added in v1.2.0
WarnfCtx logs a formatted warning message with context support using the default logger.
func WithRequestID ¶ added in v1.2.0
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
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
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
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
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
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
func (r *ContextExtractorRegistry) Clone() *ContextExtractorRegistry
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 ¶
Field represents a structured log field with a key-value pair. Type alias to internal.Field for API compatibility.
func Err ¶
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
ErrWithKey creates a field from an error with a custom key.
func ErrWithStack ¶ added in v1.2.0
ErrWithStack creates a field from an error including its stack trace. Note: Stack trace capture has a small performance overhead.
func NamedErr ¶ added in v1.2.0
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.
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
type FileWriterConfig ¶
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 )
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
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 ¶
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 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
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
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
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
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
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
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
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
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
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 ¶
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 ¶
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
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 ¶
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 ¶
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 ¶
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
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
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
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
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) Close ¶
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) DebugWithCtx ¶ added in v1.2.0
func (*Logger) ErrorWithCtx ¶ added in v1.2.0
func (*Logger) Fatal ¶
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
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 ¶
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
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 ¶
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
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
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) 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) InfoWithCtx ¶ added in v1.2.0
func (*Logger) IsClosed ¶ added in v1.2.0
IsClosed returns true if the logger has been closed (thread-safe).
func (*Logger) IsDebugEnabled ¶ added in v1.2.0
IsDebugEnabled returns true if debug level logging is enabled.
func (*Logger) IsErrorEnabled ¶ added in v1.2.0
IsErrorEnabled returns true if error level logging is enabled.
func (*Logger) IsFatalEnabled ¶ added in v1.2.0
IsFatalEnabled returns true if fatal level logging is enabled.
func (*Logger) IsInfoEnabled ¶ added in v1.2.0
IsInfoEnabled returns true if info level logging is enabled.
func (*Logger) IsLevelEnabled ¶ added in v1.2.0
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
IsWarnEnabled returns true if warn level logging is enabled.
func (*Logger) LogCtx ¶ added in v1.2.0
LogCtx logs a message at the specified level with context support.
func (*Logger) LogWithCtx ¶ added in v1.2.0
LogWithCtx logs a structured message with fields and 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
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
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
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
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 ¶
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) 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
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:
- Marks the logger as closed to prevent new log entries
- Triggers OnClose hooks with the provided context
- Waits for any in-flight operations to complete
- 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
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) WaitForFilterGoroutines ¶ added in v1.2.0
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) WarnWithCtx ¶ added in v1.2.0
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
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
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
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) Close ¶
func (mw *MultiWriter) Close() error
func (*MultiWriter) RemoveWriter ¶
func (mw *MultiWriter) RemoveWriter(w io.Writer) 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 ¶
func (f *SensitiveDataFilter) Clone() *SensitiveDataFilter
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 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.