Repository navigation
Expand file tree
/
Copy pathhook.go
More file actions
80 lines (65 loc) · 2.02 KB
/
Copy pathhook.go
File metadata and controls
80 lines (65 loc) · 2.02 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
package logging
import (
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// HookEntry describes a record passed to a hook. It holds no fields of the record.
type HookEntry struct {
// Time is the record time.
Time time.Time
// Level is the record level.
Level Level
// Logger is the name of the named logger, empty for others.
Logger string
// Message is the record text.
Message string
// Caller is the record caller as file:line, empty when callers are not collected.
Caller string
}
// HookFunc is called for every written record of the level it is registered for.
// It runs synchronously in the goroutine writing the record, so it must not block: update a counter,
// send to a channel without waiting. A panic of the function is recovered and ignored.
type HookFunc func(entry HookEntry)
type hook struct {
min Level
fn HookFunc
}
// WithHook registers fn to be called for every written record having level min or above,
// f.e. to count errors for metrics. Records dropped by a logger level are not passed.
// Hooks are called in order of registration, also for Fatal records before the process exit.
// Hooks are not loaded from YAML. Nil fn is ignored.
func WithHook(minLevel Level, fn HookFunc) Option {
return func(config *Config) {
if fn != nil {
config.hooks = append(config.hooks, hook{min: minLevel, fn: fn})
}
}
}
// makeHookOption makes zap option calling the hooks, nil if there is none.
func makeHookOption(hooks []hook) zap.Option {
if len(hooks) == 0 {
return nil
}
return zap.Hooks(func(entry zapcore.Entry) error {
level := fromZapLevel(entry.Level)
var info *HookEntry
for _, h := range hooks {
if level < h.min {
continue
}
if info == nil {
info = &HookEntry{Time: entry.Time, Level: level, Logger: entry.LoggerName, Message: entry.Message}
if entry.Caller.Defined {
info.Caller = entry.Caller.TrimmedPath()
}
}
callHook(h.fn, *info)
}
return nil
})
}
func callHook(fn HookFunc, entry HookEntry) {
defer func() { _ = recover() }()
fn(entry)
}