Documentation
¶
Index ¶
- func NewDefaultDedup() lx.Deduper
- func Pipe(h lx.Handler, wraps ...lx.Wrap) lx.Handler
- func PipeBuffer(opts ...BufferingOpt) lx.Wrap
- func PipeDedup(ttl time.Duration, opts ...DedupOpt) lx.Wrap
- func PipeRotate(maxSizeBytes int64, src RotateSource) lx.Wrap
- type Buffered
- type Buffering
- type BufferingOpt
- type ColorIntensity
- type ColorOption
- type ColorizedHandler
- type Dedup
- type DedupOpt
- type JSONHandler
- type JsonOutput
- type MemoryHandler
- type MultiHandler
- type Palette
- type RotateSource
- type Rotating
- type SlogHandler
- type TextHandler
- type TextOption
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewDefaultDedup ¶ added in v0.1.7
NewDefaultDedup creates a new default deduplication key generator.
func Pipe ¶ added in v0.1.5
Pipe chains multiple handler wrappers together, applying them from left to right. The wrappers are composed such that the first wrapper in the list becomes the innermost layer, and the last wrapper becomes the outermost layer.
Usage pattern: Pipe(baseHandler, wrapper1, wrapper2, wrapper3) Result: wrapper3(wrapper2(wrapper1(baseHandler)))
This enables clean, declarative construction of handler middleware chains.
Example - building a processing pipeline:
base := lx.NewJSONHandler(os.Stdout)
handler := lh.Pipe(base,
lh.NewDedup(2*time.Second), // 1. Deduplicate first
lh.NewRateLimit(10, time.Second), // 2. Then rate limit
)
logger := lx.NewLogger(handler)
In this example, logs flow: Dedup → RateLimit → AddTimestamp → JSONHandler
func PipeBuffer ¶ added in v0.1.5
func PipeBuffer(opts ...BufferingOpt) lx.Wrap
PipeBuffer returns a wrapper that applies buffering to the handler.
func PipeDedup ¶ added in v0.1.5
PipeDedup returns a wrapper that applies deduplication to the handler.
func PipeRotate ¶ added in v0.1.5
func PipeRotate(maxSizeBytes int64, src RotateSource) lx.Wrap
PipeRotate returns a wrapper that applies log rotation. Ideally, the 'next' handler should be one that writes to a file (like TextHandler or JSONHandler).
If the underlying handler does not implement lx.HandlerOutputter (cannot change output destination), or if rotation initialization fails, this will log a warning to stderr and return the original handler unmodified to prevent application crashes.
Types ¶
type Buffered ¶ added in v0.0.7
Buffered wraps any Handler to provide buffering capabilities. It buffers log entries in a channel and flushes them based on batch size, time interval, or explicit flush. The generic type H ensures compatibility with any lx.Handler implementation. Thread-safe via channels and sync primitives.
func NewBuffered ¶ added in v0.0.7
func NewBuffered[H lx.Handler](handler H, opts ...BufferingOpt) *Buffered[H]
NewBuffered creates a new buffered handler that wraps another handler. It initializes the handler with default or provided configuration options and starts a worker goroutine. Thread-safe via channel operations and finalizer for cleanup. Example:
textHandler := lh.NewTextHandler(os.Stdout) buffered := NewBuffered(textHandler, WithBatchSize(50))
func (*Buffered[H]) Close ¶ added in v0.0.7
Close flushes any remaining entries and stops the worker. It ensures shutdown is performed only once and waits for the worker to finish. If the underlying handler implements a Close() error method, it will be called to release resources. Thread-safe via sync.Once and WaitGroup. Returns any error from the underlying handler's Close, or nil. Example:
buffered.Close() // Flushes entries and stops worker
func (*Buffered[H]) Config ¶ added in v0.0.7
Config returns the current configuration of the Buffered handler.
func (*Buffered[H]) Final ¶ added in v0.0.7
func (b *Buffered[H]) Final()
Final ensures remaining entries are flushed during garbage collection.
func (*Buffered[H]) Flush ¶ added in v0.0.7
func (b *Buffered[H]) Flush()
Flush triggers an immediate flush of buffered entries. If a flush is already pending, it waits briefly and may exit without flushing. Thread-safe via non-blocking channel operations. Example:
buffered.Flush() // Flushes all buffered entries
type Buffering ¶ added in v0.0.7
type Buffering struct {
BatchSize int // Flush when this many entries are buffered (default: 100)
FlushInterval time.Duration // Maximum time between flushes (default: 10s)
FlushTimeout time.Duration // FlushTimeout specifies the duration to wait for a flush attempt to complete before timing out.
MaxBuffer int // Maximum buffer size before applying backpressure (default: 1000)
OnOverflow func(int) // Called when buffer reaches MaxBuffer (default: logs warning)
ErrorOutput io.Writer // Destination for internal errors like flush failures (default: os.Stderr)
}
Buffering holds configuration for the Buffered handler.
type BufferingOpt ¶ added in v0.0.7
type BufferingOpt func(*Buffering)
BufferingOpt configures Buffered handler.
func WithBatchSize ¶ added in v0.0.7
func WithBatchSize(size int) BufferingOpt
WithBatchSize sets the batch size for flushing.
func WithErrorOutput ¶ added in v0.1.5
func WithErrorOutput(w io.Writer) BufferingOpt
WithErrorOutput sets the destination for internal errors (e.g., downstream handler failures).
func WithFlushInterval ¶ added in v0.0.7
func WithFlushInterval(d time.Duration) BufferingOpt
WithFlushInterval sets the maximum time between flushes.
func WithFlushTimeout ¶ added in v0.1.8
func WithFlushTimeout(d time.Duration) BufferingOpt
WithFlushTimeout sets the maximum time to wait for a flush to complete.
func WithMaxBuffer ¶ added in v0.0.7
func WithMaxBuffer(size int) BufferingOpt
WithMaxBuffer sets the maximum buffer size before backpressure.
func WithOverflowHandler ¶ added in v0.0.7
func WithOverflowHandler(fn func(int)) BufferingOpt
WithOverflowHandler sets the overflow callback.
type ColorIntensity ¶ added in v0.1.5
type ColorIntensity int
ColorIntensity defines the intensity level for ANSI colors
const ( IntensityNormal ColorIntensity = iota IntensityBright IntensityPastel IntensityVibrant )
type ColorOption ¶
type ColorOption func(*ColorizedHandler)
ColorOption defines a configuration function for ColorizedHandler.
func WithColorField ¶ added in v0.1.5
func WithColorField(enable bool) ColorOption
WithColorField enables or disables field coloring specifically. This is useful for performance optimization or when field colors are too much. Example:
handler := NewColorizedHandler(os.Stdout, WithColorField(false)) // Disable field coloring only
func WithColorIntensity ¶ added in v0.1.5
func WithColorIntensity(intensity ColorIntensity) ColorOption
WithColorIntensity sets the color intensity for the ColorizedHandler.
func WithColorNone ¶ added in v0.1.5
func WithColorNone() ColorOption
WithColorNone disables all color output.
func WithColorPallet ¶
func WithColorPallet(pallet Palette) ColorOption
WithColorPallet sets the color palette for the ColorizedHandler.
func WithColorShowTime ¶ added in v0.1.4
func WithColorShowTime(show bool) ColorOption
WithColorShowTime enables or disables the display of timestamps.
func WithColorTheme ¶ added in v0.1.5
func WithColorTheme(theme string) ColorOption
WithColorTheme configures the ColorizedHandler to use a specific color theme based on the provided theme name.
type ColorizedHandler ¶
type ColorizedHandler struct {
// contains filtered or unexported fields
}
ColorizedHandler is a handler that outputs log entries with ANSI color codes.
func NewColorizedHandler ¶
func NewColorizedHandler(w io.Writer, opts ...ColorOption) *ColorizedHandler
NewColorizedHandler creates a new ColorizedHandler writing to the specified writer.
func (*ColorizedHandler) Handle ¶
func (h *ColorizedHandler) Handle(e *lx.Entry) error
Handle processes a log entry and writes it with ANSI color codes.
func (*ColorizedHandler) Output ¶ added in v0.1.5
func (h *ColorizedHandler) Output(w io.Writer)
func (*ColorizedHandler) Timestamped ¶ added in v0.0.9
func (h *ColorizedHandler) Timestamped(enable bool, format ...string)
Timestamped enables or disables timestamp display.
type Dedup ¶ added in v0.1.5
type Dedup struct {
// contains filtered or unexported fields
}
Dedup is a log handler that suppresses duplicate entries within a TTL window. It wraps another handler and filters out repeated log entries that match within the deduplication period.
type DedupOpt ¶ added in v0.1.5
type DedupOpt func(*Dedup)
DedupOpt configures a Dedup handler.
func WithDedupCleanupInterval ¶ added in v0.1.5
WithDedupCleanupInterval sets how often expired deduplication keys are purged.
func WithDedupIgnore ¶ added in v0.1.7
WithDedupIgnore specifies fields to ignore in the default key function.
func WithDedupKeyFunc ¶ added in v0.1.5
WithDedupKeyFunc customizes how deduplication keys are generated.
func WithDedupMaxKeys ¶ added in v0.1.5
WithDedupMaxKeys sets a soft limit on tracked deduplication keys.
type JSONHandler ¶
type JSONHandler struct {
// contains filtered or unexported fields
}
JSONHandler is a handler that outputs log entries as JSON objects. It formats log entries with timestamp, level, message, namespace, fields, and optional stack traces or dump segments, writing the result to the provided writer. Thread-safe with a mutex to protect concurrent writes.
func NewJSONHandler ¶
func NewJSONHandler(w io.Writer, opts ...func(*JSONHandler)) *JSONHandler
NewJSONHandler creates a new JSONHandler writing to the specified writer. It initializes the handler with a default timestamp format (RFC3339Nano) and optional configuration functions to customize settings like pretty printing. Example:
handler := NewJSONHandler(os.Stdout)
logger := ll.New("app").Enable().Handler(handler)
logger.Info("Test") // Output: {"ts":"...","lvl":"INFO","class":"Text","msg":"Test","ns":"app","stack":null,"dump":null,"fields":null}
func (*JSONHandler) Handle ¶
func (h *JSONHandler) Handle(e *lx.Entry) error
Handle processes a log entry and writes it as JSON. It delegates to specialized methods based on the entry's class (Dump or regular), ensuring thread-safety with a mutex. Returns an error if JSON encoding or writing fails. Example:
handler.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Writes JSON object
func (*JSONHandler) Output ¶ added in v0.1.5
func (h *JSONHandler) Output(w io.Writer)
Output sets the Writer destination for JSONHandler's output, ensuring thread safety with a mutex lock.
type JsonOutput ¶
type JsonOutput struct {
Time string `json:"ts"` // Timestamp in specified format
Level string `json:"lvl"` // Log level (e.g., "INFO")
Class string `json:"class"` // Entry class (e.g., "Text", "Dump")
Msg string `json:"msg"` // Log message
Namespace string `json:"ns"` // Namespace path
Stack []byte `json:"stack"` // Stack trace (if present)
Dump []dumpSegment `json:"dump"` // Hex/ASCII dump segments (for ClassDump)
Fields map[string]interface{} `json:"fields"` // Custom fields
}
JsonOutput represents the JSON structure for a log entry. It includes all relevant log data, such as timestamp, level, message, and optional stack trace or dump segments, serialized as a JSON object.
type MemoryHandler ¶
type MemoryHandler struct {
// contains filtered or unexported fields
}
MemoryHandler is an lx.Handler that stores log entries in memory. Useful for testing or buffering logs for later inspection. It maintains a thread-safe slice of log entries, protected by a read-write mutex.
func NewMemoryHandler ¶
func NewMemoryHandler() *MemoryHandler
NewMemoryHandler creates a new MemoryHandler. It initializes an empty slice for storing log entries, ready for use in logging or testing. Example:
handler := NewMemoryHandler()
logger := ll.New("app").Enable().Handler(handler)
logger.Info("Test") // Stores entry in memory
func (*MemoryHandler) Dump ¶
func (h *MemoryHandler) Dump(w io.Writer) error
Dump writes all stored log entries to the provided io.Writer in text format. Entries are formatted as they would be by a TextHandler, including namespace, level, message, and fields. Thread-safe with read lock. Returns an error if writing fails. Example:
logger := ll.New("test", ll.WithHandler(NewMemoryHandler())).Enable()
logger.Info("Test message")
handler := logger.handler.(*MemoryHandler)
handler.Dump(os.Stdout) // Output: [test] INFO: Test message
func (*MemoryHandler) Entries ¶
func (h *MemoryHandler) Entries() []*lx.Entry
Entries returns a copy of the stored log entries. It creates a new slice with copies of all entries, ensuring thread-safety with a read lock. The returned slice is safe for external use without affecting the handler's internal state. Example:
entries := handler.Entries() // Returns copy of stored entries
func (*MemoryHandler) Handle ¶
func (h *MemoryHandler) Handle(entry *lx.Entry) error
Handle stores the log entry in memory. It appends the provided entry to the entries slice, ensuring thread-safety with a write lock. Always returns nil, as it does not perform I/O operations. Example:
handler.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Stores entry
func (*MemoryHandler) Reset ¶
func (h *MemoryHandler) Reset()
Reset clears all stored entries. It truncates the entries slice to zero length, preserving capacity, using a write lock for thread-safety. Example:
handler.Reset() // Clears all stored entries
func (*MemoryHandler) Timestamped ¶ added in v0.0.9
func (h *MemoryHandler) Timestamped(enable bool, format ...string)
Timestamped enables/disables timestamp display when dumping and optionally sets a time format. Consistent with TextHandler and ColorizedHandler signature. Example:
handler.Timestamped(true) // Enable with default format handler.Timestamped(true, time.StampMilli) // Enable with custom format handler.Timestamped(false) // Disable
type MultiHandler ¶
MultiHandler combines multiple handlers to process log entries concurrently. It holds a list of lx.Handler instances and delegates each log entry to all handlers, collecting any errors into a single combined error. Thread-safe if the underlying handlers are thread-safe.
func NewMultiHandler ¶
func NewMultiHandler(h ...lx.Handler) *MultiHandler
NewMultiHandler creates a new MultiHandler with the specified handlers. It accepts a variadic list of handlers to be executed in order. The returned handler processes log entries by passing them to each handler in sequence. Example:
textHandler := NewTextHandler(os.Stdout)
jsonHandler := NewJSONHandler(os.Stdout)
multi := NewMultiHandler(textHandler, jsonHandler)
logger := ll.New("app").Enable().Handler(multi)
logger.Info("Test") // Processed by both text and JSON handlers
func (*MultiHandler) Append ¶ added in v0.1.4
func (h *MultiHandler) Append(handlers ...lx.Handler)
Append adds one or more handlers to the MultiHandler. Handlers will receive log entries in the order they were appended. This method modifies the MultiHandler in place.
Example:
multi := &MultiHandler{}
multi.Append(
lx.NewJSONHandler(os.Stdout),
lx.NewTextHandler(logFile),
)
// Now multi broadcasts to both stdout and file
func (*MultiHandler) Handle ¶
func (h *MultiHandler) Handle(e *lx.Entry) error
Handle implements the Handler interface, calling Handle on each handler in sequence. It collects any errors from handlers and combines them into a single error using errors.Join. If no errors occur, it returns nil. Thread-safe if the underlying handlers are thread-safe. Example:
multi.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Calls Handle on all handlers
func (*MultiHandler) Len ¶ added in v0.1.4
func (h *MultiHandler) Len() int
Len returns the number of handlers in the MultiHandler. Useful for monitoring or debugging handler composition.
Example:
multi := &MultiHandler{}
multi.Append(h1, h2, h3)
count := multi.Len() // Returns 3
type Palette ¶
type Palette struct {
Header string // Color for stack trace header and dump separators
Goroutine string // Color for goroutine lines in stack traces
Func string // Color for function names in stack traces
Path string // Color for file paths in stack traces
FileLine string // Color for file line numbers
Reset string // Reset code to clear color formatting
Pos string // Color for position in hex dumps
Hex string // Color for hex values in dumps
Ascii string // Color for ASCII values in dumps
Debug string // Color for Debug level messages
Info string // Color for Info level messages
Warn string // Color for Warn level messages
Error string // Color for Error level messages
Fatal string // Color for Fatal level messages
Title string // Color for dump titles (BEGIN/END separators)
// Field type colors
Key string // Color for field keys
Number string // Color for numbers
String string // Color for strings
Bool string // Color for booleans
Time string // Color for timestamps/durations
Nil string // Color for nil values
Default string // Default color for unknown types
// JSON and Inspect specific colors
JSONKey string // Color for JSON keys
JSONString string // Color for JSON string values
JSONNumber string // Color for JSON number values
JSONBool string // Color for JSON boolean values
JSONNull string // Color for JSON null values
JSONBrace string // Color for JSON braces and brackets
InspectKey string // Color for inspect keys
InspectValue string // Color for inspect values
InspectMeta string // Color for inspect metadata (annotations)
}
Palette defines ANSI color codes for various log components.
type RotateSource ¶ added in v0.1.5
type RotateSource struct {
// Open returns a fresh destination for log output.
// Called on initialization and after each rotation.
Open func() (io.WriteCloser, error)
// Size returns the current size in bytes of the active destination.
// Return an error if size cannot be determined (rotation will be skipped).
Size func() (int64, error)
// Rotate performs all cleanup/rotation actions before a new destination is
// opened, including closing or renaming the previous writer when required.
// Rotating will NOT close the old writer itself; that is the responsibility
// of this callback. May be nil if no pre-open actions are needed.
Rotate func() error
}
RotateSource defines the callbacks needed to implement log rotation. It abstracts the destination lifecycle: opening, sizing, and rotating.
Example for file rotation:
src := lh.RotateSource{
Open: func() (io.WriteCloser, error) {
return os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
},
Size: func() (int64, error) {
if fi, err := os.Stat("app.log"); err == nil {
return fi.Size(), nil
}
return 0, nil // File doesn't exist yet
},
Rotate: func() error {
// Close and rename the current log before creating a new one.
return os.Rename("app.log", "app.log."+time.Now().Format("20060102-150405"))
},
}
type Rotating ¶ added in v0.1.5
type Rotating[H interface {
lx.Handler
lx.Outputter
}] struct {
// contains filtered or unexported fields
}
Rotating wraps a handler to rotate its output when maxSize is exceeded. The wrapped handler must implement both Handler and Outputter interfaces. Rotation is triggered on each Handle call if the current size >= maxSize.
Example:
handler := lx.NewJSONHandler(os.Stdout)
src := lh.RotateSource{...} // see RotateSource example
rotator, err := lh.NewRotating(handler, 10*1024*1024, src) // 10 MB
logger := lx.NewLogger(rotator)
logger.Info("This log may trigger rotation when file reaches 10MB")
func NewRotating ¶ added in v0.1.5
func NewRotating[H interface {
lx.Handler
lx.Outputter
}](handler H, maxSizeBytes int64, src RotateSource) (*Rotating[H], error)
NewRotating creates a rotating wrapper around handler. Handler's output will be replaced with destinations from src.Open. If maxSizeBytes <= 0, rotation is disabled. src.Rotate may be nil if no pre-open actions are needed.
Example:
// Create a JSON handler that rotates at 5MB
handler := lx.NewJSONHandler(os.Stdout)
rotator, err := lh.NewRotating(handler, 5*1024*1024, src)
if err != nil {
log.Fatal(err)
}
// Use rotator as your logger's handler
logger := lx.NewLogger(rotator)
func (*Rotating[H]) Close ¶ added in v0.1.5
Close releases resources (closes the current output). Safe to call multiple times.
Example:
defer rotator.Close()
type SlogHandler ¶
type SlogHandler struct {
// contains filtered or unexported fields
}
SlogHandler adapts a slog.Handler to implement lx.Handler. It converts lx.Entry objects to slog.Record objects and delegates to an underlying slog.Handler for processing, enabling compatibility with Go's standard slog package. Thread-safe if the underlying slog.Handler is thread-safe.
func NewSlogHandler ¶
func NewSlogHandler(h slog.Handler) *SlogHandler
NewSlogHandler creates a new SlogHandler wrapping the provided slog.Handler. It initializes the handler with the given slog.Handler, allowing lx.Entry logs to be processed by slog's logging infrastructure. Example:
slogText := slog.NewTextHandler(os.Stdout, nil)
handler := NewSlogHandler(slogText)
logger := ll.New("app").Enable().Handler(handler)
logger.Info("Test") // Output: level=INFO msg=Test namespace=app class=Text
func (*SlogHandler) Handle ¶
func (h *SlogHandler) Handle(e *lx.Entry) error
Handle converts an lx.Entry to slog.Record and delegates to the slog.Handler. It maps the entry's fields, level, namespace, class, and stack trace to slog attributes, passing the resulting record to the underlying slog.Handler. Returns an error if the slog.Handler fails to process the record. Thread-safe if the underlying slog.Handler is thread-safe. Example:
handler.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Processes as slog record
Handle converts an lx.Entry to slog.Record and delegates to the slog.Handler. It maps the entry's fields, level, namespace, class, and stack trace to slog attributes, passing the resulting record to the underlying slog.Handler. Returns an error if the slog.Handler fails to process the record. Thread-safe if the underlying slog.Handler is thread-safe. Example:
handler.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Processes as slog record
type TextHandler ¶
type TextHandler struct {
// contains filtered or unexported fields
}
TextHandler is a handler that outputs log entries as plain text. It formats log entries with namespace, level, message, fields, and optional stack traces, writing the result to the provided writer. Thread-safe if the underlying writer is thread-safe.
func NewTextHandler ¶
func NewTextHandler(w io.Writer, opts ...TextOption) *TextHandler
NewTextHandler creates a new TextHandler writing to the specified writer. It initializes the handler with the given writer, suitable for outputs like stdout or files. Example:
handler := NewTextHandler(os.Stdout)
logger := ll.New("app").Enable().Handler(handler)
logger.Info("Test") // Output: [app] INFO: Test
func (*TextHandler) Handle ¶
func (h *TextHandler) Handle(e *lx.Entry) error
Handle processes a log entry and writes it as plain text. It delegates to specialized methods based on the entry's class (Dump, Raw, or regular). Returns an error if writing to the underlying writer fails. Thread-safe if the writer is thread-safe. Example:
handler.Handle(&lx.Entry{Message: "test", Level: lx.LevelInfo}) // Writes "INFO: test"
func (*TextHandler) Output ¶ added in v0.1.5
func (h *TextHandler) Output(w io.Writer)
Output sets a new writer for the TextHandler. Thread-safe - safe for concurrent use.
func (*TextHandler) Timestamped ¶ added in v0.0.9
func (h *TextHandler) Timestamped(enable bool, format ...string)
Timestamped enables or disables timestamp display and optionally sets a custom time format. If format is empty, defaults to RFC3339. Example:
handler := NewTextHandler(os.Stdout).TextWithTime(true, time.StampMilli) // Output: Jan 02 15:04:05.000 [app] INFO: Test
type TextOption ¶ added in v0.1.4
type TextOption func(*TextHandler)
func WithTextShowTime ¶ added in v0.1.4
func WithTextShowTime(show bool) TextOption
WithTextShowTime enables or disables timestamp display in log entries. This option provides direct control over the visibility of the time prefix without altering the underlying time format configured in the handler. Setting show to true will prepend timestamps to all subsequent regular log outputs.
func WithTextTimeFormat ¶ added in v0.1.4
func WithTextTimeFormat(format string) TextOption
WithTextTimeFormat enables timestamp display and optionally sets a custom time format. It configures the TextHandler to include temporal information in each log entry, allowing for precise tracking of when log events occur. If the format string is empty, it defaults to time.RFC3339.