Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 12, 19:30 UTC
logging: Add `zap.Option` support (#5944)
Francis Lavoie committed
Dec 18, 2023 at 15:48 UTC
3248e4c89f510ad832bc9fb0ed6f6b945355304d
2 files changed
+88
-27
logging.go
+87
-26
@@ -150,12 +150,18 @@ func (logging *Logging) setupNewDefault(ctx Context) error {
150
logging.Logs[DefaultLoggerName] = newDefault.CustomLog
151
}
152
153
+ // options for the default logger
154
+ options, err := newDefault.CustomLog.buildOptions()
155
+ if err != nil {
156
+ return fmt.Errorf("setting up default log: %v", err)
157
+ }
158
+
159
// set up this new log
154
- err := newDefault.CustomLog.provision(ctx, logging)
160
+ err = newDefault.CustomLog.provision(ctx, logging)
161
if err != nil {
162
return fmt.Errorf("setting up default log: %v", err)
163
}
158
- newDefault.logger = zap.New(newDefault.CustomLog.core)
164
+ newDefault.logger = zap.New(newDefault.CustomLog.core, options...)
165
166
// redirect the default caddy logs
167
defaultLoggerMu.Lock()
@@ -201,6 +207,7 @@ func (logging *Logging) closeLogs() error {
207
func (logging *Logging) Logger(mod Module) *zap.Logger {
208
modID := string(mod.CaddyModule().ID)
209
var cores []zapcore.Core
210
+ var options []zap.Option
211
212
if logging != nil {
213
for _, l := range logging.Logs {
@@ -209,6 +216,13 @@ func (logging *Logging) Logger(mod Module) *zap.Logger {
216
cores = append(cores, l.core)
217
continue
218
}
219
+ if len(options) == 0 {
220
+ newOptions, err := l.buildOptions()
221
+ if err != nil {
222
+ Log().Error("building options for logger", zap.String("module", modID), zap.Error(err))
223
+ }
224
+ options = newOptions
225
+ }
226
cores = append(cores, &filteringCore{Core: l.core, cl: l})
227
}
228
}
@@ -216,7 +230,7 @@ func (logging *Logging) Logger(mod Module) *zap.Logger {
230
231
multiCore := zapcore.NewTee(cores...)
232
219
- return zap.New(multiCore).Named(modID)
233
+ return zap.New(multiCore, options...).Named(modID)
234
}
235
236
// openWriter opens a writer using opener, and returns true if
@@ -277,6 +291,20 @@ type BaseLog struct {
291
// servers.
292
Sampling *LogSampling `json:"sampling,omitempty"`
293
294
+ // If true, the log entry will include the caller's
295
+ // file name and line number. Default off.
296
+ WithCaller bool `json:"with_caller,omitempty"`
297
+
298
+ // If non-zero, and `with_caller` is true, this many
299
+ // stack frames will be skipped when determining the
300
+ // caller. Default 0.
301
+ WithCallerSkip int `json:"with_caller_skip,omitempty"`
302
+
303
+ // If not empty, the log entry will include a stack trace
304
+ // for all logs at the given level or higher. See `level`
305
+ // for possible values. Default off.
306
+ WithStacktrace string `json:"with_stacktrace,omitempty"`
307
+
308
writerOpener WriterOpener
309
writer io.WriteCloser
310
encoder zapcore.Encoder
@@ -301,29 +329,10 @@ func (cl *BaseLog) provisionCommon(ctx Context, logging *Logging) error {
329
return fmt.Errorf("opening log writer using %#v: %v", cl.writerOpener, err)
330
}
331
304
- repl := NewReplacer()
305
- level, err := repl.ReplaceOrErr(cl.Level, true, true)
306
- if err != nil {
307
- return fmt.Errorf("invalid log level: %v", err)
308
- }
309
- level = strings.ToLower(level)
310
-
332
// set up the log level
312
- switch level {
313
- case "debug":
314
- cl.levelEnabler = zapcore.DebugLevel
315
- case "", "info":
316
- cl.levelEnabler = zapcore.InfoLevel
317
- case "warn":
318
- cl.levelEnabler = zapcore.WarnLevel
319
- case "error":
320
- cl.levelEnabler = zapcore.ErrorLevel
321
- case "panic":
322
- cl.levelEnabler = zapcore.PanicLevel
323
- case "fatal":
324
- cl.levelEnabler = zapcore.FatalLevel
325
- default:
326
- return fmt.Errorf("unrecognized log level: %s", cl.Level)
333
+ cl.levelEnabler, err = parseLevel(cl.Level)
334
+ if err != nil {
335
+ return err
336
}
337
338
if cl.EncoderRaw != nil {
@@ -376,6 +385,24 @@ func (cl *BaseLog) buildCore() {
385
cl.core = c
386
}
387
388
+func (cl *BaseLog) buildOptions() ([]zap.Option, error) {
389
+ var options []zap.Option
390
+ if cl.WithCaller {
391
+ options = append(options, zap.AddCaller())
392
+ if cl.WithCallerSkip != 0 {
393
+ options = append(options, zap.AddCallerSkip(cl.WithCallerSkip))
394
+ }
395
+ }
396
+ if cl.WithStacktrace != "" {
397
+ levelEnabler, err := parseLevel(cl.WithStacktrace)
398
+ if err != nil {
399
+ return options, fmt.Errorf("setting up default Caddy log: %v", err)
400
+ }
401
+ options = append(options, zap.AddStacktrace(levelEnabler))
402
+ }
403
+ return options, nil
404
+}
405
+
406
// SinkLog configures the default Go standard library
407
// global logger in the log package. This is necessary because
408
// module dependencies which are not built specifically for
@@ -389,7 +416,14 @@ func (sll *SinkLog) provision(ctx Context, logging *Logging) error {
416
if err := sll.provisionCommon(ctx, logging); err != nil {
417
return err
418
}
392
- ctx.cleanupFuncs = append(ctx.cleanupFuncs, zap.RedirectStdLog(zap.New(sll.core)))
419
+
420
+ options, err := sll.buildOptions()
421
+ if err != nil {
422
+ return err
423
+ }
424
+
425
+ logger := zap.New(sll.core, options...)
426
+ ctx.cleanupFuncs = append(ctx.cleanupFuncs, zap.RedirectStdLog(logger))
427
return nil
428
}
429
@@ -678,6 +712,33 @@ func newDefaultProductionLogEncoder(colorize bool) zapcore.Encoder {
712
return zapcore.NewJSONEncoder(encCfg)
713
}
714
715
+func parseLevel(levelInput string) (zapcore.LevelEnabler, error) {
716
+ repl := NewReplacer()
717
+ level, err := repl.ReplaceOrErr(levelInput, true, true)
718
+ if err != nil {
719
+ return nil, fmt.Errorf("invalid log level: %v", err)
720
+ }
721
+ level = strings.ToLower(level)
722
+
723
+ // set up the log level
724
+ switch level {
725
+ case "debug":
726
+ return zapcore.DebugLevel, nil
727
+ case "", "info":
728
+ return zapcore.InfoLevel, nil
729
+ case "warn":
730
+ return zapcore.WarnLevel, nil
731
+ case "error":
732
+ return zapcore.ErrorLevel, nil
733
+ case "panic":
734
+ return zapcore.PanicLevel, nil
735
+ case "fatal":
736
+ return zapcore.FatalLevel, nil
737
+ default:
738
+ return nil, fmt.Errorf("unrecognized log level: %s", level)
739
+ }
740
+}
741
+
742
// Log returns the current default logger.
743
func Log() *zap.Logger {
744
defaultLoggerMu.RLock()
modules/caddyhttp/reverseproxy/streaming.go
+1
-1
@@ -68,7 +68,7 @@ func (h *Handler) handleUpgradeResponse(logger *zap.Logger, rw http.ResponseWrit
68
//nolint:bodyclose
69
conn, brw, hijackErr := http.NewResponseController(rw).Hijack()
70
if errors.Is(hijackErr, http.ErrNotSupported) {
71
- h.logger.Sugar().Errorf("can't switch protocols using non-Hijacker ResponseWriter type %T", rw)
71
+ h.logger.Error("can't switch protocols using non-Hijacker ResponseWriter", zap.String("type", fmt.Sprintf("%T", rw)))
72
return
73
}
74