-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathlog.go
146 lines (130 loc) · 3.64 KB
/
log.go
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package alimns
import (
"encoding/json"
"time"
"go.uber.org/multierr"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// Entry 在zapcore.Entry基础上增加 error & []zap.Fields
type Entry struct {
Level zapcore.Level `json:"-"`
LevelStr string `json:"level"`
LoggerName string `json:"logger_name"`
Message string `json:"message"`
Caller string `json:"caller"`
Stack string `json:"stack"`
Fields []zap.Field `json:"-"` // 不包含error字段
FieldsJSON string `json:"-"`
Err error `json:"-"`
ErrStr string `json:"error"`
}
// NewLogger 创建一个logger
func NewLogger() (logger *zap.Logger, err error) {
conf := zap.NewProductionConfig()
conf.Sampling = nil
conf.EncoderConfig = newEncoderConfig()
logger, err = conf.Build()
return
}
// Hooks 回调钩子(warn级别以上回调)
func Hooks(hooks ...func(entry Entry) error) zap.Option {
return zap.WrapCore(func(core zapcore.Core) zapcore.Core {
return registerHooksWithErrField(core, hooks...)
})
}
// DefaultHook 提供一个默认钩子
func DefaultHook(callback func(entryJson string, fieldsJson string)) func(entry Entry) error {
return func(en Entry) error {
if en.Level < zapcore.WarnLevel {
return nil
}
b, err := json.Marshal(&en)
if err != nil {
return err
}
callback(string(b), en.FieldsJSON)
return nil
}
}
// NewEntryFromZapEntry zapcore.Entry转换到Entry
func NewEntryFromZapEntry(ent zapcore.Entry) Entry {
return Entry{
Level: ent.Level,
LevelStr: ent.Level.String(),
LoggerName: ent.LoggerName,
Message: ent.Message,
Caller: ent.Caller.String(),
Stack: ent.Stack,
}
}
type hookedWithErrField struct {
zapcore.Core
enc zapcore.Encoder
funcs []func(entry Entry) error
fields []zap.Field
}
func (h *hookedWithErrField) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
// Let the wrapped Core decide whether to log this message or not. This
// also gives the downstream a chance to register itself directly with the
// CheckedEntry.
if downstream := h.Core.Check(ent, ce); downstream != nil {
return downstream.AddCore(ent, h)
}
return ce
}
func (h *hookedWithErrField) With(fields []zapcore.Field) zapcore.Core {
fields = append(fields, h.fields...)
return &hookedWithErrField{
Core: h.Core.With(fields),
enc: h.enc,
funcs: h.funcs,
fields: fields,
}
}
func (h *hookedWithErrField) Write(ent zapcore.Entry, fs []zapcore.Field) error {
if ent.Level < zapcore.WarnLevel {
return nil
}
var err error
entry := NewEntryFromZapEntry(ent)
fs = append(h.fields, fs...)
for _, v := range fs {
if v.Key == "error" && v.Type == zapcore.ErrorType {
entry.Err = v.Interface.(error)
entry.ErrStr = entry.Err.Error()
} else {
entry.Fields = append(entry.Fields, v)
}
}
buf, _ := h.enc.EncodeEntry(ent, entry.Fields)
entry.FieldsJSON = buf.String()
buf.Free()
for i := range h.funcs {
err = multierr.Append(err, h.funcs[i](entry))
}
return err
}
func registerHooksWithErrField(core zapcore.Core, hooks ...func(entry Entry) error) zapcore.Core {
funcList := append([]func(entry Entry) error{}, hooks...)
ec := newEncoderConfig()
ec.CallerKey = ""
ec.LevelKey = ""
ec.MessageKey = ""
ec.NameKey = ""
ec.TimeKey = ""
ec.StacktraceKey = ""
enc := zapcore.NewJSONEncoder(ec)
return &hookedWithErrField{
Core: core,
enc: enc,
funcs: funcList,
}
}
func newEncoderConfig() zapcore.EncoderConfig {
ec := zap.NewProductionEncoderConfig()
ec.EncodeTime = func(i time.Time, encoder zapcore.PrimitiveArrayEncoder) {
encoder.AppendString(i.Format("2006-01-02 15:04:05"))
}
return ec
}