-
-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathfirstmatch.go
More file actions
96 lines (82 loc) · 2.99 KB
/
Copy pathfirstmatch.go
File metadata and controls
96 lines (82 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package slogmulti
import (
"context"
"log/slog"
"slices"
"github.com/samber/lo"
)
// Ensure FirstMatchHandler implements the slog.Handler interface at compile time
var _ slog.Handler = (*FirstMatchHandler)(nil)
type FirstMatchHandler struct {
handlers []*RoutableHandler
}
func FirstMatch(handlers ...*RoutableHandler) *FirstMatchHandler {
return &FirstMatchHandler{handlers: lo.Map(handlers, func(h *RoutableHandler, _ int) *RoutableHandler {
return &RoutableHandler{
predicates: h.predicates,
handler: h.handler,
groups: slices.Clone(h.groups),
attrs: slices.Clone(h.attrs),
skipPredicates: true, // prevent double matching
}
})}
}
// Enabled checks if any of the underlying handlers are enabled for the given log level.
// This method implements the slog.Handler interface requirement.
// See FanoutHandler.WithAttrs for details.
func (h *FirstMatchHandler) Enabled(ctx context.Context, l slog.Level) bool {
for i := range h.handlers {
if h.handlers[i].Enabled(ctx, l) {
return true
}
}
return false
}
// Handle distributes a log record to the first matching handler.
// This method implements the slog.Handler interface requirement.
//
// The method:
// 1. Iterates through each child handler.
// 2. Checks if the handler's predicates match the record.
// 3. If a match is found, it checks if the handler is enabled for the record's level.
// 4. If enabled, it forwards the record to that handler and returns.
// 5. If no handlers match, it returns nil.
func (h *FirstMatchHandler) Handle(ctx context.Context, r slog.Record) error {
for i := range h.handlers {
record, ok := h.handlers[i].isMatch(ctx, r)
if ok {
if h.handlers[i].Enabled(ctx, record.Level) {
return try(func() error {
return h.handlers[i].Handle(ctx, r)
})
}
return nil // Handler matched but is not enabled; do not proceed further
}
}
return nil
}
// WithAttrs creates a new FirstMatchHandler with additional attributes added to all child handlers.
// This method implements the slog.Handler interface requirement.
// See FanoutHandler.WithAttrs for details.
func (h *FirstMatchHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
handlers := lo.Map(h.handlers, func(h *RoutableHandler, _ int) *RoutableHandler {
return h.WithAttrs(slices.Clone(attrs)).(*RoutableHandler)
})
return newFirstMatch(handlers...)
}
// WithGroup creates a new FirstMatchHandler with a group name applied to all child handlers.
// This method implements the slog.Handler interface requirement.
// See FanoutHandler.WithGroup for details.
func (h *FirstMatchHandler) WithGroup(name string) slog.Handler {
// https://cs.opensource.google/go/x/exp/+/46b07846:slog/handler.go;l=247
if name == "" {
return h
}
handlers := lo.Map(h.handlers, func(h *RoutableHandler, _ int) *RoutableHandler {
return h.WithGroup(name).(*RoutableHandler)
})
return newFirstMatch(handlers...)
}
func newFirstMatch(handlers ...*RoutableHandler) *FirstMatchHandler {
return &FirstMatchHandler{handlers: handlers}
}