@@ -150,12 +150,18 @@ func (logging *Logging) setupNewDefault(ctx Context) error {
150
150
logging .Logs [DefaultLoggerName ] = newDefault .CustomLog
151
151
}
152
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
+
153
159
// set up this new log
154
- err : = newDefault .CustomLog .provision (ctx , logging )
160
+ err = newDefault .CustomLog .provision (ctx , logging )
155
161
if err != nil {
156
162
return fmt .Errorf ("setting up default log: %v" , err )
157
163
}
158
- newDefault .logger = zap .New (newDefault .CustomLog .core )
164
+ newDefault .logger = zap .New (newDefault .CustomLog .core , options ... )
159
165
160
166
// redirect the default caddy logs
161
167
defaultLoggerMu .Lock ()
@@ -201,6 +207,7 @@ func (logging *Logging) closeLogs() error {
201
207
func (logging * Logging ) Logger (mod Module ) * zap.Logger {
202
208
modID := string (mod .CaddyModule ().ID )
203
209
var cores []zapcore.Core
210
+ var options []zap.Option
204
211
205
212
if logging != nil {
206
213
for _ , l := range logging .Logs {
@@ -209,14 +216,21 @@ func (logging *Logging) Logger(mod Module) *zap.Logger {
209
216
cores = append (cores , l .core )
210
217
continue
211
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
+ }
212
226
cores = append (cores , & filteringCore {Core : l .core , cl : l })
213
227
}
214
228
}
215
229
}
216
230
217
231
multiCore := zapcore .NewTee (cores ... )
218
232
219
- return zap .New (multiCore ).Named (modID )
233
+ return zap .New (multiCore , options ... ).Named (modID )
220
234
}
221
235
222
236
// openWriter opens a writer using opener, and returns true if
@@ -277,6 +291,20 @@ type BaseLog struct {
277
291
// servers.
278
292
Sampling * LogSampling `json:"sampling,omitempty"`
279
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
+
280
308
writerOpener WriterOpener
281
309
writer io.WriteCloser
282
310
encoder zapcore.Encoder
@@ -301,29 +329,10 @@ func (cl *BaseLog) provisionCommon(ctx Context, logging *Logging) error {
301
329
return fmt .Errorf ("opening log writer using %#v: %v" , cl .writerOpener , err )
302
330
}
303
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
-
311
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
327
336
}
328
337
329
338
if cl .EncoderRaw != nil {
@@ -376,6 +385,24 @@ func (cl *BaseLog) buildCore() {
376
385
cl .core = c
377
386
}
378
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
+
379
406
// SinkLog configures the default Go standard library
380
407
// global logger in the log package. This is necessary because
381
408
// module dependencies which are not built specifically for
@@ -389,7 +416,14 @@ func (sll *SinkLog) provision(ctx Context, logging *Logging) error {
389
416
if err := sll .provisionCommon (ctx , logging ); err != nil {
390
417
return err
391
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 ))
393
427
return nil
394
428
}
395
429
@@ -678,6 +712,33 @@ func newDefaultProductionLogEncoder(colorize bool) zapcore.Encoder {
678
712
return zapcore .NewJSONEncoder (encCfg )
679
713
}
680
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
+
681
742
// Log returns the current default logger.
682
743
func Log () * zap.Logger {
683
744
defaultLoggerMu .RLock ()
0 commit comments