...
1
16
17
18
19 package zap
20
21 import (
22 "flag"
23 "io"
24 "os"
25 "time"
26
27 "github.com/go-logr/logr"
28 "github.com/go-logr/zapr"
29 "go.uber.org/zap"
30 "go.uber.org/zap/zapcore"
31 )
32
33
34 type EncoderConfigOption func(*zapcore.EncoderConfig)
35
36
37 type NewEncoderFunc func(...EncoderConfigOption) zapcore.Encoder
38
39
40
41
42 func New(opts ...Opts) logr.Logger {
43 return zapr.NewLogger(NewRaw(opts...))
44 }
45
46
47 type Opts func(*Options)
48
49
50
51
52 func UseDevMode(enabled bool) Opts {
53 return func(o *Options) {
54 o.Development = enabled
55 }
56 }
57
58
59
60 func WriteTo(out io.Writer) Opts {
61 return func(o *Options) {
62 o.DestWriter = out
63 }
64 }
65
66
67
68 func Encoder(encoder zapcore.Encoder) func(o *Options) {
69 return func(o *Options) {
70 o.Encoder = encoder
71 }
72 }
73
74
75 func JSONEncoder(opts ...EncoderConfigOption) func(o *Options) {
76 return func(o *Options) {
77 o.Encoder = newJSONEncoder(opts...)
78 }
79 }
80
81 func newJSONEncoder(opts ...EncoderConfigOption) zapcore.Encoder {
82 encoderConfig := zap.NewProductionEncoderConfig()
83 for _, opt := range opts {
84 opt(&encoderConfig)
85 }
86 return zapcore.NewJSONEncoder(encoderConfig)
87 }
88
89
90 func ConsoleEncoder(opts ...EncoderConfigOption) func(o *Options) {
91 return func(o *Options) {
92 o.Encoder = newConsoleEncoder(opts...)
93 }
94 }
95
96 func newConsoleEncoder(opts ...EncoderConfigOption) zapcore.Encoder {
97 encoderConfig := zap.NewDevelopmentEncoderConfig()
98 for _, opt := range opts {
99 opt(&encoderConfig)
100 }
101 return zapcore.NewConsoleEncoder(encoderConfig)
102 }
103
104
105
106
107
108 func Level(level zapcore.LevelEnabler) func(o *Options) {
109 return func(o *Options) {
110 o.Level = level
111 }
112 }
113
114
115
116
117 func StacktraceLevel(stacktraceLevel zapcore.LevelEnabler) func(o *Options) {
118 return func(o *Options) {
119 o.StacktraceLevel = stacktraceLevel
120 }
121 }
122
123
124
125 func RawZapOpts(zapOpts ...zap.Option) func(o *Options) {
126 return func(o *Options) {
127 o.ZapOpts = append(o.ZapOpts, zapOpts...)
128 }
129 }
130
131
132 type Options struct {
133
134
135
136 Development bool
137
138
139 Encoder zapcore.Encoder
140
141
142
143
144 EncoderConfigOptions []EncoderConfigOption
145
146
147 NewEncoder NewEncoderFunc
148
149
150 DestWriter io.Writer
151
152
153
154
155
156 Level zapcore.LevelEnabler
157
158
159
160
161 StacktraceLevel zapcore.LevelEnabler
162
163
164 ZapOpts []zap.Option
165
166
167 TimeEncoder zapcore.TimeEncoder
168 }
169
170
171 func (o *Options) addDefaults() {
172 if o.DestWriter == nil {
173 o.DestWriter = os.Stderr
174 }
175
176 if o.Development {
177 if o.NewEncoder == nil {
178 o.NewEncoder = newConsoleEncoder
179 }
180 if o.Level == nil {
181 lvl := zap.NewAtomicLevelAt(zap.DebugLevel)
182 o.Level = &lvl
183 }
184 if o.StacktraceLevel == nil {
185 lvl := zap.NewAtomicLevelAt(zap.WarnLevel)
186 o.StacktraceLevel = &lvl
187 }
188 o.ZapOpts = append(o.ZapOpts, zap.Development())
189 } else {
190 if o.NewEncoder == nil {
191 o.NewEncoder = newJSONEncoder
192 }
193 if o.Level == nil {
194 lvl := zap.NewAtomicLevelAt(zap.InfoLevel)
195 o.Level = &lvl
196 }
197 if o.StacktraceLevel == nil {
198 lvl := zap.NewAtomicLevelAt(zap.ErrorLevel)
199 o.StacktraceLevel = &lvl
200 }
201
202
203 if !o.Level.Enabled(zapcore.Level(-2)) {
204 o.ZapOpts = append(o.ZapOpts,
205 zap.WrapCore(func(core zapcore.Core) zapcore.Core {
206 return zapcore.NewSamplerWithOptions(core, time.Second, 100, 100)
207 }))
208 }
209 }
210
211 if o.TimeEncoder == nil {
212 o.TimeEncoder = zapcore.RFC3339TimeEncoder
213 }
214 f := func(ecfg *zapcore.EncoderConfig) {
215 ecfg.EncodeTime = o.TimeEncoder
216 }
217
218 o.EncoderConfigOptions = append([]EncoderConfigOption{f}, o.EncoderConfigOptions...)
219
220 if o.Encoder == nil {
221 o.Encoder = o.NewEncoder(o.EncoderConfigOptions...)
222 }
223 o.ZapOpts = append(o.ZapOpts, zap.AddStacktrace(o.StacktraceLevel))
224 }
225
226
227
228
229 func NewRaw(opts ...Opts) *zap.Logger {
230 o := &Options{}
231 for _, opt := range opts {
232 opt(o)
233 }
234 o.addDefaults()
235
236
237 sink := zapcore.AddSync(o.DestWriter)
238
239 o.ZapOpts = append(o.ZapOpts, zap.ErrorOutput(sink))
240 log := zap.New(zapcore.NewCore(&KubeAwareEncoder{Encoder: o.Encoder, Verbose: o.Development}, sink, o.Level))
241 log = log.WithOptions(o.ZapOpts...)
242 return log
243 }
244
245
246
247
248
249
250
251
252
253
254
255 func (o *Options) BindFlags(fs *flag.FlagSet) {
256
257 fs.BoolVar(&o.Development, "zap-devel", o.Development,
258 "Development Mode defaults(encoder=consoleEncoder,logLevel=Debug,stackTraceLevel=Warn). "+
259 "Production Mode defaults(encoder=jsonEncoder,logLevel=Info,stackTraceLevel=Error)")
260
261
262 var encVal encoderFlag
263 encVal.setFunc = func(fromFlag NewEncoderFunc) {
264 o.NewEncoder = fromFlag
265 }
266 fs.Var(&encVal, "zap-encoder", "Zap log encoding (one of 'json' or 'console')")
267
268
269 var levelVal levelFlag
270 levelVal.setFunc = func(fromFlag zapcore.LevelEnabler) {
271 o.Level = fromFlag
272 }
273 fs.Var(&levelVal, "zap-log-level",
274 "Zap Level to configure the verbosity of logging. Can be one of 'debug', 'info', 'error', "+
275 "or any integer value > 0 which corresponds to custom debug levels of increasing verbosity")
276
277
278 var stackVal stackTraceFlag
279 stackVal.setFunc = func(fromFlag zapcore.LevelEnabler) {
280 o.StacktraceLevel = fromFlag
281 }
282 fs.Var(&stackVal, "zap-stacktrace-level",
283 "Zap Level at and above which stacktraces are captured (one of 'info', 'error', 'panic').")
284
285
286 var timeEncoderVal timeEncodingFlag
287 timeEncoderVal.setFunc = func(fromFlag zapcore.TimeEncoder) {
288 o.TimeEncoder = fromFlag
289 }
290 fs.Var(&timeEncoderVal, "zap-time-encoding", "Zap time encoding (one of 'epoch', 'millis', 'nano', 'iso8601', 'rfc3339' or 'rfc3339nano'). Defaults to 'epoch'.")
291 }
292
293
294
295
296
297
298
299 func UseFlagOptions(in *Options) Opts {
300 return func(o *Options) {
301 *o = *in
302 }
303 }
304
View as plain text