mirror of
https://github.com/TecharoHQ/anubis.git
synced 2026-04-05 16:28:17 +00:00
feat(lib/logging): add slog filter handler, move slog init logic here
Signed-off-by: Xe Iaso <me@xeiaso.net>
This commit is contained in:
67
lib/logging/filter.go
Normal file
67
lib/logging/filter.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
// Filterer is the shape of any type that can perform log filtering. This takes
|
||||
// the context of the log filtering call and the log record to be filtered.
|
||||
type Filterer interface {
|
||||
Filter(ctx context.Context, r slog.Record) bool
|
||||
}
|
||||
|
||||
// FilterFunc lets you make inline log filters with plain functions.
|
||||
type FilterFunc func(ctx context.Context, r *slog.Record) bool
|
||||
|
||||
// Filter implements Filterer for FilterFunc.
|
||||
func (ff FilterFunc) Filter(ctx context.Context, r *slog.Record) bool {
|
||||
return ff(ctx, r)
|
||||
}
|
||||
|
||||
// FilterHandler wraps a slog Handler with one or more filters, enabling administrators
|
||||
// to customize the logging subsystem of Anubis.
|
||||
type FilterHandler struct {
|
||||
next slog.Handler
|
||||
filters []Filterer
|
||||
}
|
||||
|
||||
// NewFilterHandler creates a new filtering handler with the given base handler and filters.
|
||||
func NewFilterHandler(handler slog.Handler, filters ...Filterer) *FilterHandler {
|
||||
return &FilterHandler{
|
||||
next: handler,
|
||||
filters: filters,
|
||||
}
|
||||
}
|
||||
|
||||
// Enabled passes through to the upstream slog Handler.
|
||||
func (h *FilterHandler) Enabled(ctx context.Context, level slog.Level) bool {
|
||||
return h.next.Enabled(ctx, level)
|
||||
}
|
||||
|
||||
// Handle implements slog.Handler and applies all filters before delegating to the base handler.
|
||||
func (h *FilterHandler) Handle(ctx context.Context, r slog.Record) error {
|
||||
// Apply all filters - if any filter returns false, skip the log
|
||||
for _, filter := range h.filters {
|
||||
if !filter.Filter(ctx, r) {
|
||||
return nil // Skip this log record
|
||||
}
|
||||
}
|
||||
return h.next.Handle(ctx, r)
|
||||
}
|
||||
|
||||
// WithAttrs implements slog.Handler.
|
||||
func (h *FilterHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||
return &FilterHandler{
|
||||
next: h.next.WithAttrs(attrs),
|
||||
filters: h.filters,
|
||||
}
|
||||
}
|
||||
|
||||
// WithGroup implements slog.Handler.
|
||||
func (h *FilterHandler) WithGroup(name string) slog.Handler {
|
||||
return &FilterHandler{
|
||||
next: h.next.WithGroup(name),
|
||||
filters: h.filters,
|
||||
}
|
||||
}
|
||||
24
lib/logging/logging.go
Normal file
24
lib/logging/logging.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
)
|
||||
|
||||
func Init(level string) slog.Handler {
|
||||
var programLevel slog.Level
|
||||
if err := (&programLevel).UnmarshalText([]byte(level)); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "invalid log level %s: %v, using info\n", level, err)
|
||||
programLevel = slog.LevelInfo
|
||||
}
|
||||
|
||||
leveler := &slog.LevelVar{}
|
||||
leveler.Set(programLevel)
|
||||
|
||||
h := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
|
||||
AddSource: true,
|
||||
Level: leveler,
|
||||
})
|
||||
return h
|
||||
}
|
||||
Reference in New Issue
Block a user