@marcel91200 / caddy Mirror · read-only / commits / 3248e4c8
Fork 0

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