77 lines
2.4 KiB
Go
77 lines
2.4 KiB
Go
package lh
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/olekukonko/ll/lx"
|
|
)
|
|
|
|
// 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 Pipe(h lx.Handler, wraps ...lx.Wrap) lx.Handler {
|
|
for _, w := range wraps {
|
|
if w != nil {
|
|
h = w(h)
|
|
}
|
|
}
|
|
return h
|
|
}
|
|
|
|
// PipeDedup returns a wrapper that applies deduplication to the handler.
|
|
func PipeDedup(ttl time.Duration, opts ...DedupOpt[lx.Handler]) lx.Wrap {
|
|
return func(next lx.Handler) lx.Handler {
|
|
return NewDedup(next, ttl, opts...)
|
|
}
|
|
}
|
|
|
|
// PipeBuffer returns a wrapper that applies buffering to the handler.
|
|
func PipeBuffer(opts ...BufferingOpt) lx.Wrap {
|
|
return func(next lx.Handler) lx.Handler {
|
|
return NewBuffered(next, opts...)
|
|
}
|
|
}
|
|
|
|
// 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.
|
|
func PipeRotate(maxSizeBytes int64, src RotateSource) lx.Wrap {
|
|
return func(next lx.Handler) lx.Handler {
|
|
// Attempt to cast to HandlerOutputter (Handler + Outputter interface)
|
|
h, ok := next.(lx.HandlerOutputter)
|
|
if !ok {
|
|
fmt.Fprintf(os.Stderr, "ll/lh: PipeRotate skipped - handler does not implement SetOutput(io.Writer)\n")
|
|
return next
|
|
}
|
|
|
|
// Initialize the rotating handler
|
|
r, err := NewRotating(h, maxSizeBytes, src)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "ll/lh: PipeRotate initialization failed: %v\n", err)
|
|
return next
|
|
}
|
|
return r
|
|
}
|
|
}
|