vendor/github.com/olekukonko/ll/middleware.go
package ll
import (
"github.com/olekukonko/ll/lx"
)
// Middleware represents a registered middleware and its operations in the logging pipeline.
// It holds an ID for identification, a reference to the parent logger, and the handler function
// that processes log entries. Middleware is used to transform or filter log entries before they
// are passed to the logger's output handler.
type Middleware struct {
id int // Unique identifier for the middleware
logger *Logger // Parent logger instance for context and logging operations
fn lx.Handler // Handler function that processes log entries
}
// Remove unregisters the middleware from the logger’s middleware chain.
// It safely removes the middleware by its ID, ensuring thread-safety with a mutex lock.
// If the middleware or logger is nil, it returns early to prevent panics.
// Example usage:
//
// // Using a named middleware function
// mw := logger.Use(authMiddleware)
// defer mw.Remove()
//
// // Using an inline middleware
// mw = logger.Use(ll.Middle(func(e *lx.Entry) error {
// if e.Level < lx.LevelWarn {
// return fmt.Errorf("level too low")
// }
// return nil
// }))
// defer mw.Remove()
func (m *Middleware) Remove() {
// Check for nil middleware or logger to avoid panics
if m == nil || m.logger == nil {
return
}
// Acquire write lock to modify middleware slice
m.logger.mu.Lock()
defer m.logger.mu.Unlock()
// Iterate through middleware slice to find and remove matching ID
for i, entry := range m.logger.middleware {
if entry.id == m.id {
// Remove middleware by slicing out the matching entry
m.logger.middleware = append(m.logger.middleware[:i], m.logger.middleware[i+1:]...)
return
}
}
}
// Logger returns the parent logger for optional chaining.
// This allows middleware to access the logger for additional operations, such as logging errors
// or creating derived loggers. It is useful for fluent API patterns.
// Example:
//
// mw := logger.Use(authMiddleware)
// mw.Logger().Info("Middleware registered")
func (m *Middleware) Logger() *Logger {
return m.logger
}
// Error logs an error message at the Error level if the middleware blocks a log entry.
// It uses the parent logger to emit the error and returns the middleware for chaining.
// This is useful for debugging or auditing when middleware rejects a log.
// Example:
//
// mw := logger.Use(ll.Middle(func(e *lx.Entry) error {
// if e.Level < lx.LevelWarn {
// return fmt.Errorf("level too low")
// }
// return nil
// }))
// mw.Error("Rejected low-level log")
func (m *Middleware) Error(args ...any) *Middleware {
m.logger.Error(args...)
return m
}
// Errorf logs an error message at the Error level if the middleware blocks a log entry.
// It uses the parent logger to emit the error and returns the middleware for chaining.
// This is useful for debugging or auditing when middleware rejects a log.
// Example:
//
// mw := logger.Use(ll.Middle(func(e *lx.Entry) error {
// if e.Level < lx.LevelWarn {
// return fmt.Errorf("level too low")
// }
// return nil
// }))
// mw.Errorf("Rejected low-level log")
func (m *Middleware) Errorf(format string, args ...any) *Middleware {
m.logger.Errorf(format, args...)
return m
}
// middlewareFunc is a function adapter that implements the lx.Handler interface.
// It allows plain functions with the signature `func(*lx.Entry) error` to be used as middleware.
// The function should return nil to allow the log to proceed or a non-nil error to reject it,
// stopping the log from being emitted by the logger.
type middlewareFunc func(*lx.Entry) error
// Handle implements the lx.Handler interface for middlewareFunc.
// It calls the underlying function with the log entry and returns its result.
// This enables seamless integration of function-based middleware into the logging pipeline.
func (mf middlewareFunc) Handle(e *lx.Entry) error {
return mf(e)
}
// Middle creates a middleware handler from a function.
// It wraps a function with the signature `func(*lx.Entry) error` into a middlewareFunc,
// allowing it to be used in the logger’s middleware pipeline. A non-nil error returned by
// the function will stop the log from being emitted, ensuring precise control over logging.
// Example:
//
// logger.Use(ll.Middle(func(e *lx.Entry) error {
// if e.Level == lx.LevelDebug {
// return fmt.Errorf("debug logs disabled")
// }
// return nil
// }))
func Middle(fn func(*lx.Entry) error) lx.Handler {
return middlewareFunc(fn)
}