Documentation
ΒΆ
Overview ΒΆ
Package loggerj provides an ultra-high-performance, asynchronous, and lock-free logging facility designed for high-throughput Go services. It offers near-zero heap allocations, atomic rate limiting, log rotation, and structured fields in both text and JSON formats.
Architecture: The "Dark Side" (Lock-Free SubProfiles) ΒΆ
Unlike traditional loggers that use mutexes and maps for rate limiting and sampling in the hot path, loggerj uses a "Pre-compiled Execution Profile" architecture.
- Cold Path (Init-time): You register log types using RegisterSub(). This pre-bakes JSON/Text prefixes into []byte and initializes lock-free atomic counters for rate limiting and sampling.
- Hot Path (Log-time): The Log() method performs ZERO map lookups and ZERO mutex locks. It uses atomic.CompareAndSwap (CAS) for rate limiting and atomic.Add for sampling.
- Worker: The dedicated worker goroutine simply appends the pre-baked []byte prefixes, resulting in near-zero CPU overhead for formatting.
This design ensures that logging never blocks the caller, eliminates GC pressure in the hot path, and scales linearly with CPU cores without lock contention.
Quick Start ΒΆ
logger := loggerj.NewLogger(loggerj.Config{
JSONOutput: true,
FlushTimeout: 50 * time.Millisecond,
})
// COLD PATH: Register profiles once at startup
logger.RegisterSub("HTTP",
loggerj.WithRateLimit(1000, time.Second),
loggerj.WithFields("env", "prod", "service", "gateway"),
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go logger.Start(ctx)
defer logger.Close()
// HOT PATH: Ultra-fast, zero-allocation logging
logger.InfoString("HTTP", "request received", "method", "GET", "path", "/api")
logger.ErrorString("DB", "connection failed", "host", "localhost", "err", "timeout")
Performance ΒΆ
On Apple M1 Pro, the lock-free architecture achieves:
- ~15-20 ns/op for Rate-Limited logs (Down from 48ns in v1)
- 8M+ logs/s single-thread (no fields)
- 10.9M+ logs/s parallel
- 0 allocs/op in the hot path
See BENCH.md for detailed benchmark results.
Index ΒΆ
- type Config
- type Entry
- type Level
- type Logger
- func (l *Logger) AsWriter(level Level, logType string) io.Writer
- func (l *Logger) Close() error
- func (l *Logger) Debug(logType string, msg []byte, fields ...string)
- func (l *Logger) DebugString(logType string, msg string, fields ...string)
- func (l *Logger) Drops() uint64
- func (l *Logger) Error(logType string, msg []byte, fields ...string)
- func (l *Logger) ErrorString(logType string, msg string, fields ...string)
- func (l *Logger) Flush()
- func (l *Logger) GetLevel() Level
- func (l *Logger) Info(logType string, msg []byte, fields ...string)
- func (l *Logger) InfoString(logType string, msg string, fields ...string)
- func (l *Logger) Log(level Level, logType string, msg []byte, fields ...string)
- func (l *Logger) RegisterSub(logType string, opts ...SubOption)
- func (l *Logger) ResetDrops()
- func (l *Logger) SetLevelValue(level Level)
- func (l *Logger) Start(ctx context.Context)
- func (l *Logger) StartWithWriter(ctx context.Context, w io.Writer)
- func (l *Logger) Stats() map[string]uint64
- func (l *Logger) Warn(logType string, msg []byte, fields ...string)
- func (l *Logger) WarnString(logType string, msg string, fields ...string)
- type StdLogWriter
- type SubOption
- type SubProfile
Constants ΒΆ
This section is empty.
Variables ΒΆ
This section is empty.
Functions ΒΆ
This section is empty.
Types ΒΆ
type Config ΒΆ
type Config struct {
// JSONOutput controls the output format. If true, logs are formatted as JSON.
// If false, logs are formatted as human-readable text. Default: false
JSONOutput bool
// FlushTimeout is the interval at which the worker flushes buffered logs.
// Shorter timeouts reduce latency but increase I/O operations. Default: 50ms
FlushTimeout time.Duration
// ChannelSize is the capacity of the internal log channel. Larger values
// provide more buffering for burst traffic. If full, entries are dropped. Default: 4096
ChannelSize int
// WorkerBufferSize is the initial capacity of the worker's format buffer.
// Minimum: 256. Default: 4096
WorkerBufferSize int
// FlushThreshold is the byte count at which the worker flushes the
// format buffer to the underlying writer. Should be <= WorkerBufferSize.
// Minimum: 256. Default: 4096
FlushThreshold int
// WriterBufferSize is the size of the bufio.Writer buffer used for I/O.
// Minimum: 512. Default: 8192
WriterBufferSize int
// RateLimitWindow is the default time window for rate limiting, in seconds.
// Used if a SubProfile doesn't specify its own window via WithRateLimit.
// Minimum: 1. Default: 1
RateLimitWindow int64
// IncludeCaller adds file:line information to each log entry.
// WARNING: Adds ~480ns overhead and 2 allocations per log entry.
// Should be disabled in production for maximum performance. Default: false
IncludeCaller bool
// OutputFile is the path to the log file. If empty, logs are written to stderr.
OutputFile string
// MaxFileSize is the maximum size of the log file before rotation.
// If 0, rotation is disabled. Default: 0
MaxFileSize int64
// MaxBackupFiles is the maximum number of rotated log files to keep.
// Only effective if MaxFileSize > 0. Default: 0
MaxBackupFiles int
}
Config holds the configuration for a Logger instance. All fields have sensible defaults and can be left at their zero values.
func DefaultConfig ΒΆ
func DefaultConfig() Config
DefaultConfig returns a Config with sensible defaults for production use.
type Entry ΒΆ
type Entry struct {
Level Level
Type string
Msg []byte
Ts int64
File string
Line int
Fields []string
Profile *SubProfile // π Pointer to the pre-compiled SubProfile
}
Entry represents a single log record. Entries are pooled using sync.Pool to minimize allocations. The Reset method clears all fields for reuse.
type Level ΒΆ
type Level uint8
Level represents the severity of a log entry. Lower values indicate more verbose logging. The logger filters entries below the configured threshold.
const ( // LevelDebug is the most verbose level, used for detailed debugging information. LevelDebug Level = 0 // LevelInfo is the default level, used for general operational messages. LevelInfo Level = 1 // LevelWarn indicates potential issues that should be monitored. LevelWarn Level = 2 // LevelError indicates serious problems that require immediate attention. LevelError Level = 3 )
type Logger ΒΆ
type Logger struct {
// contains filtered or unexported fields
}
Logger is the main logging instance. It provides asynchronous, high-throughput, lock-free logging.
func NewLogger ΒΆ
NewLogger creates a new Logger instance. The logger is not started; call Start or StartWithWriter to begin processing.
func (*Logger) AsWriter ΒΆ
AsWriter returns an io.Writer that routes all writes to the logger at the specified level and logType.
Note: This method is designed for intercepting standard library logs. It incurs a minor string allocation (string(p)) which is acceptable for stdlib interception, but should not be used in the application's hot path.
func (*Logger) DebugString ΒΆ
DebugString logs a string message at LevelDebug. Caller skip is 2.
func (*Logger) Drops ΒΆ
Drops returns the total number of log entries dropped because the channel was full.
func (*Logger) ErrorString ΒΆ
ErrorString logs a string message at LevelError. Caller skip is 2.
func (*Logger) Flush ΒΆ
func (l *Logger) Flush()
Flush forces an immediate flush of all pending log entries.
func (*Logger) InfoString ΒΆ
InfoString logs a string message at LevelInfo. Caller skip is 2.
func (*Logger) RegisterSub ΒΆ
RegisterSub registers a SubProfile for a specific logType. COLD PATH: Call this during application initialization, NOT inside HTTP handlers or hot loops.
func (*Logger) ResetDrops ΒΆ
func (l *Logger) ResetDrops()
ResetDrops resets the drop counter to zero.
func (*Logger) SetLevelValue ΒΆ
SetLevelValue sets the current log level threshold atomically.
func (*Logger) StartWithWriter ΒΆ
StartWithWriter begins the worker goroutine with a custom io.Writer.
type StdLogWriter ΒΆ
type StdLogWriter struct {
// contains filtered or unexported fields
}
StdLogWriter wraps a Logger to implement the io.Writer interface. This allows the standard library "log" package (and third-party libraries that rely on it) to route their output through loggerj's async, high-performance pipeline.
type SubOption ΒΆ
type SubOption func(*SubProfile)
SubOption configures a SubProfile during RegisterSub.
func WithFields ΒΆ
WithFields adds static key-value pairs that will be pre-baked into the JSON/Text prefixes. This avoids formatting these fields in the hot path.
func WithRateLimit ΒΆ
WithRateLimit sets a lock-free rate limit for this specific logType. limit is the max logs per window. window is the duration (e.g., time.Second).
func WithSampleRate ΒΆ
WithSampleRate sets a lock-free sampling rate for this logType. rate means 1 out of `rate` logs will be written (0 disables sampling).
type SubProfile ΒΆ
type SubProfile struct {
Name string
// contains filtered or unexported fields
}
SubProfile represents a pre-compiled execution profile for a specific logType. Unlike traditional loggers that use mutexes and maps in the hot path, SubProfile holds lock-free atomic counters for rate limiting/sampling and pre-baked []byte prefixes for zero-CPU formatting.