mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-04 10:12:29 +08:00 
			
		
		
		
	log: Make sink logs encodable (#5441)
* log: make `sink` encodable * deduplicate logger fields * extract common fields into `BaseLog` and embed it into `SinkLog` * amend godoc on `BaseLog` and `SinkLog` * minor style change --------- Co-authored-by: Francis Lavoie <lavofr@gmail.com>
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							e16a886814
						
					
				
				
					commit
					1aef807c71
				
			@ -241,7 +241,9 @@ func (st ServerType) Setup(inputServerBlocks []caddyfile.ServerBlock,
 | 
				
			|||||||
		if _, ok := options["debug"]; ok {
 | 
							if _, ok := options["debug"]; ok {
 | 
				
			||||||
			customLogs = append(customLogs, namedCustomLog{
 | 
								customLogs = append(customLogs, namedCustomLog{
 | 
				
			||||||
				name: caddy.DefaultLoggerName,
 | 
									name: caddy.DefaultLoggerName,
 | 
				
			||||||
				log:  &caddy.CustomLog{Level: zap.DebugLevel.CapitalString()},
 | 
									log: &caddy.CustomLog{
 | 
				
			||||||
 | 
										BaseLog: caddy.BaseLog{Level: zap.DebugLevel.CapitalString()},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										240
									
								
								logging.go
									
									
									
									
									
								
							
							
						
						
									
										240
									
								
								logging.go
									
									
									
									
									
								
							@ -62,7 +62,7 @@ type Logging struct {
 | 
				
			|||||||
	// in dependencies that are not designed specifically for use
 | 
						// in dependencies that are not designed specifically for use
 | 
				
			||||||
	// in Caddy. Because it is global and unstructured, the sink
 | 
						// in Caddy. Because it is global and unstructured, the sink
 | 
				
			||||||
	// lacks most advanced features and customizations.
 | 
						// lacks most advanced features and customizations.
 | 
				
			||||||
	Sink *StandardLibLog `json:"sink,omitempty"`
 | 
						Sink *SinkLog `json:"sink,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Logs are your logs, keyed by an arbitrary name of your
 | 
						// Logs are your logs, keyed by an arbitrary name of your
 | 
				
			||||||
	// choosing. The default log can be customized by defining
 | 
						// choosing. The default log can be customized by defining
 | 
				
			||||||
@ -259,55 +259,11 @@ func (wdest writerDestructor) Destruct() error {
 | 
				
			|||||||
	return wdest.Close()
 | 
						return wdest.Close()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StandardLibLog configures the default Go standard library
 | 
					// BaseLog contains the common logging parameters for logging.
 | 
				
			||||||
// global logger in the log package. This is necessary because
 | 
					type BaseLog struct {
 | 
				
			||||||
// module dependencies which are not built specifically for
 | 
					 | 
				
			||||||
// Caddy will use the standard logger. This is also known as
 | 
					 | 
				
			||||||
// the "sink" logger.
 | 
					 | 
				
			||||||
type StandardLibLog struct {
 | 
					 | 
				
			||||||
	// The module that writes out log entries for the sink.
 | 
						// The module that writes out log entries for the sink.
 | 
				
			||||||
	WriterRaw json.RawMessage `json:"writer,omitempty" caddy:"namespace=caddy.logging.writers inline_key=output"`
 | 
						WriterRaw json.RawMessage `json:"writer,omitempty" caddy:"namespace=caddy.logging.writers inline_key=output"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	writer io.WriteCloser
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (sll *StandardLibLog) provision(ctx Context, logging *Logging) error {
 | 
					 | 
				
			||||||
	if sll.WriterRaw != nil {
 | 
					 | 
				
			||||||
		mod, err := ctx.LoadModule(sll, "WriterRaw")
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return fmt.Errorf("loading sink log writer module: %v", err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		wo := mod.(WriterOpener)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		var isNew bool
 | 
					 | 
				
			||||||
		sll.writer, isNew, err = logging.openWriter(wo)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return fmt.Errorf("opening sink log writer %#v: %v", mod, err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if isNew {
 | 
					 | 
				
			||||||
			log.Printf("[INFO] Redirecting sink to: %s", wo)
 | 
					 | 
				
			||||||
			log.SetOutput(sll.writer)
 | 
					 | 
				
			||||||
			log.Printf("[INFO] Redirected sink to here (%s)", wo)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// CustomLog represents a custom logger configuration.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
// By default, a log will emit all log entries. Some entries
 | 
					 | 
				
			||||||
// will be skipped if sampling is enabled. Further, the Include
 | 
					 | 
				
			||||||
// and Exclude parameters define which loggers (by name) are
 | 
					 | 
				
			||||||
// allowed or rejected from emitting in this log. If both Include
 | 
					 | 
				
			||||||
// and Exclude are populated, their values must be mutually
 | 
					 | 
				
			||||||
// exclusive, and longer namespaces have priority. If neither
 | 
					 | 
				
			||||||
// are populated, all logs are emitted.
 | 
					 | 
				
			||||||
type CustomLog struct {
 | 
					 | 
				
			||||||
	// The writer defines where log entries are emitted.
 | 
					 | 
				
			||||||
	WriterRaw json.RawMessage `json:"writer,omitempty" caddy:"namespace=caddy.logging.writers inline_key=output"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// The encoder is how the log entries are formatted or encoded.
 | 
						// The encoder is how the log entries are formatted or encoded.
 | 
				
			||||||
	EncoderRaw json.RawMessage `json:"encoder,omitempty" caddy:"namespace=caddy.logging.encoders inline_key=format"`
 | 
						EncoderRaw json.RawMessage `json:"encoder,omitempty" caddy:"namespace=caddy.logging.encoders inline_key=format"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -321,16 +277,6 @@ type CustomLog struct {
 | 
				
			|||||||
	// servers.
 | 
						// servers.
 | 
				
			||||||
	Sampling *LogSampling `json:"sampling,omitempty"`
 | 
						Sampling *LogSampling `json:"sampling,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Include defines the names of loggers to emit in this
 | 
					 | 
				
			||||||
	// log. For example, to include only logs emitted by the
 | 
					 | 
				
			||||||
	// admin API, you would include "admin.api".
 | 
					 | 
				
			||||||
	Include []string `json:"include,omitempty"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Exclude defines the names of loggers that should be
 | 
					 | 
				
			||||||
	// skipped by this log. For example, to exclude only
 | 
					 | 
				
			||||||
	// HTTP access logs, you would exclude "http.log.access".
 | 
					 | 
				
			||||||
	Exclude []string `json:"exclude,omitempty"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	writerOpener WriterOpener
 | 
						writerOpener WriterOpener
 | 
				
			||||||
	writer       io.WriteCloser
 | 
						writer       io.WriteCloser
 | 
				
			||||||
	encoder      zapcore.Encoder
 | 
						encoder      zapcore.Encoder
 | 
				
			||||||
@ -338,8 +284,23 @@ type CustomLog struct {
 | 
				
			|||||||
	core         zapcore.Core
 | 
						core         zapcore.Core
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (cl *CustomLog) provision(ctx Context, logging *Logging) error {
 | 
					func (cl *BaseLog) provisionCommon(ctx Context, logging *Logging) error {
 | 
				
			||||||
	// Replace placeholder for log level
 | 
						if cl.WriterRaw != nil {
 | 
				
			||||||
 | 
							mod, err := ctx.LoadModule(cl, "WriterRaw")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("loading log writer module: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							cl.writerOpener = mod.(WriterOpener)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if cl.writerOpener == nil {
 | 
				
			||||||
 | 
							cl.writerOpener = StderrWriter{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						cl.writer, _, err = logging.openWriter(cl.writerOpener)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("opening log writer using %#v: %v", cl.writerOpener, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repl := NewReplacer()
 | 
						repl := NewReplacer()
 | 
				
			||||||
	level, err := repl.ReplaceOrErr(cl.Level, true, true)
 | 
						level, err := repl.ReplaceOrErr(cl.Level, true, true)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -365,6 +326,101 @@ func (cl *CustomLog) provision(ctx Context, logging *Logging) error {
 | 
				
			|||||||
		return fmt.Errorf("unrecognized log level: %s", cl.Level)
 | 
							return fmt.Errorf("unrecognized log level: %s", cl.Level)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if cl.EncoderRaw != nil {
 | 
				
			||||||
 | 
							mod, err := ctx.LoadModule(cl, "EncoderRaw")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("loading log encoder module: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							cl.encoder = mod.(zapcore.Encoder)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if cl.encoder == nil {
 | 
				
			||||||
 | 
							// only allow colorized output if this log is going to stdout or stderr
 | 
				
			||||||
 | 
							var colorize bool
 | 
				
			||||||
 | 
							switch cl.writerOpener.(type) {
 | 
				
			||||||
 | 
							case StdoutWriter, StderrWriter,
 | 
				
			||||||
 | 
								*StdoutWriter, *StderrWriter:
 | 
				
			||||||
 | 
								colorize = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							cl.encoder = newDefaultProductionLogEncoder(colorize)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cl.buildCore()
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cl *BaseLog) buildCore() {
 | 
				
			||||||
 | 
						// logs which only discard their output don't need
 | 
				
			||||||
 | 
						// to perform encoding or any other processing steps
 | 
				
			||||||
 | 
						// at all, so just shorcut to a nop core instead
 | 
				
			||||||
 | 
						if _, ok := cl.writerOpener.(*DiscardWriter); ok {
 | 
				
			||||||
 | 
							cl.core = zapcore.NewNopCore()
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c := zapcore.NewCore(
 | 
				
			||||||
 | 
							cl.encoder,
 | 
				
			||||||
 | 
							zapcore.AddSync(cl.writer),
 | 
				
			||||||
 | 
							cl.levelEnabler,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if cl.Sampling != nil {
 | 
				
			||||||
 | 
							if cl.Sampling.Interval == 0 {
 | 
				
			||||||
 | 
								cl.Sampling.Interval = 1 * time.Second
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if cl.Sampling.First == 0 {
 | 
				
			||||||
 | 
								cl.Sampling.First = 100
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if cl.Sampling.Thereafter == 0 {
 | 
				
			||||||
 | 
								cl.Sampling.Thereafter = 100
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							c = zapcore.NewSamplerWithOptions(c, cl.Sampling.Interval,
 | 
				
			||||||
 | 
								cl.Sampling.First, cl.Sampling.Thereafter)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cl.core = c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SinkLog configures the default Go standard library
 | 
				
			||||||
 | 
					// global logger in the log package. This is necessary because
 | 
				
			||||||
 | 
					// module dependencies which are not built specifically for
 | 
				
			||||||
 | 
					// Caddy will use the standard logger. This is also known as
 | 
				
			||||||
 | 
					// the "sink" logger.
 | 
				
			||||||
 | 
					type SinkLog struct {
 | 
				
			||||||
 | 
						BaseLog
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (sll *SinkLog) provision(ctx Context, logging *Logging) error {
 | 
				
			||||||
 | 
						if err := sll.provisionCommon(ctx, logging); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ctx.cleanupFuncs = append(ctx.cleanupFuncs, zap.RedirectStdLog(zap.New(sll.core)))
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CustomLog represents a custom logger configuration.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// By default, a log will emit all log entries. Some entries
 | 
				
			||||||
 | 
					// will be skipped if sampling is enabled. Further, the Include
 | 
				
			||||||
 | 
					// and Exclude parameters define which loggers (by name) are
 | 
				
			||||||
 | 
					// allowed or rejected from emitting in this log. If both Include
 | 
				
			||||||
 | 
					// and Exclude are populated, their values must be mutually
 | 
				
			||||||
 | 
					// exclusive, and longer namespaces have priority. If neither
 | 
				
			||||||
 | 
					// are populated, all logs are emitted.
 | 
				
			||||||
 | 
					type CustomLog struct {
 | 
				
			||||||
 | 
						BaseLog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Include defines the names of loggers to emit in this
 | 
				
			||||||
 | 
						// log. For example, to include only logs emitted by the
 | 
				
			||||||
 | 
						// admin API, you would include "admin.api".
 | 
				
			||||||
 | 
						Include []string `json:"include,omitempty"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Exclude defines the names of loggers that should be
 | 
				
			||||||
 | 
						// skipped by this log. For example, to exclude only
 | 
				
			||||||
 | 
						// HTTP access logs, you would exclude "http.log.access".
 | 
				
			||||||
 | 
						Exclude []string `json:"exclude,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cl *CustomLog) provision(ctx Context, logging *Logging) error {
 | 
				
			||||||
 | 
						if err := cl.provisionCommon(ctx, logging); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// If both Include and Exclude lists are populated, then each item must
 | 
						// If both Include and Exclude lists are populated, then each item must
 | 
				
			||||||
	// be a superspace or subspace of an item in the other list, because
 | 
						// be a superspace or subspace of an item in the other list, because
 | 
				
			||||||
	// populating both lists means that any given item is either a rule
 | 
						// populating both lists means that any given item is either a rule
 | 
				
			||||||
@ -394,75 +450,9 @@ func (cl *CustomLog) provision(ctx Context, logging *Logging) error {
 | 
				
			|||||||
			return fmt.Errorf("when both include and exclude are populated, each element must be a superspace or subspace of one in the other list; check '%s' in include", allow)
 | 
								return fmt.Errorf("when both include and exclude are populated, each element must be a superspace or subspace of one in the other list; check '%s' in include", allow)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if cl.WriterRaw != nil {
 | 
					 | 
				
			||||||
		mod, err := ctx.LoadModule(cl, "WriterRaw")
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return fmt.Errorf("loading log writer module: %v", err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		cl.writerOpener = mod.(WriterOpener)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if cl.writerOpener == nil {
 | 
					 | 
				
			||||||
		cl.writerOpener = StderrWriter{}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cl.writer, _, err = logging.openWriter(cl.writerOpener)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return fmt.Errorf("opening log writer using %#v: %v", cl.writerOpener, err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if cl.EncoderRaw != nil {
 | 
					 | 
				
			||||||
		mod, err := ctx.LoadModule(cl, "EncoderRaw")
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return fmt.Errorf("loading log encoder module: %v", err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		cl.encoder = mod.(zapcore.Encoder)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if cl.encoder == nil {
 | 
					 | 
				
			||||||
		// only allow colorized output if this log is going to stdout or stderr
 | 
					 | 
				
			||||||
		var colorize bool
 | 
					 | 
				
			||||||
		switch cl.writerOpener.(type) {
 | 
					 | 
				
			||||||
		case StdoutWriter, StderrWriter,
 | 
					 | 
				
			||||||
			*StdoutWriter, *StderrWriter:
 | 
					 | 
				
			||||||
			colorize = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		cl.encoder = newDefaultProductionLogEncoder(colorize)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cl.buildCore()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (cl *CustomLog) buildCore() {
 | 
					 | 
				
			||||||
	// logs which only discard their output don't need
 | 
					 | 
				
			||||||
	// to perform encoding or any other processing steps
 | 
					 | 
				
			||||||
	// at all, so just shorcut to a nop core instead
 | 
					 | 
				
			||||||
	if _, ok := cl.writerOpener.(*DiscardWriter); ok {
 | 
					 | 
				
			||||||
		cl.core = zapcore.NewNopCore()
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	c := zapcore.NewCore(
 | 
					 | 
				
			||||||
		cl.encoder,
 | 
					 | 
				
			||||||
		zapcore.AddSync(cl.writer),
 | 
					 | 
				
			||||||
		cl.levelEnabler,
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	if cl.Sampling != nil {
 | 
					 | 
				
			||||||
		if cl.Sampling.Interval == 0 {
 | 
					 | 
				
			||||||
			cl.Sampling.Interval = 1 * time.Second
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if cl.Sampling.First == 0 {
 | 
					 | 
				
			||||||
			cl.Sampling.First = 100
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if cl.Sampling.Thereafter == 0 {
 | 
					 | 
				
			||||||
			cl.Sampling.Thereafter = 100
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		c = zapcore.NewSamplerWithOptions(c, cl.Sampling.Interval,
 | 
					 | 
				
			||||||
			cl.Sampling.First, cl.Sampling.Thereafter)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	cl.core = c
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (cl *CustomLog) matchesModule(moduleID string) bool {
 | 
					func (cl *CustomLog) matchesModule(moduleID string) bool {
 | 
				
			||||||
	return cl.loggerAllowed(moduleID, true)
 | 
						return cl.loggerAllowed(moduleID, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -134,7 +134,9 @@ func cmdFileServer(fs caddycmd.Flags) (int, error) {
 | 
				
			|||||||
	if debug {
 | 
						if debug {
 | 
				
			||||||
		cfg.Logging = &caddy.Logging{
 | 
							cfg.Logging = &caddy.Logging{
 | 
				
			||||||
			Logs: map[string]*caddy.CustomLog{
 | 
								Logs: map[string]*caddy.CustomLog{
 | 
				
			||||||
				"default": {Level: zap.DebugLevel.CapitalString()},
 | 
									"default": {
 | 
				
			||||||
 | 
										BaseLog: caddy.BaseLog{Level: zap.DebugLevel.CapitalString()},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -280,7 +280,7 @@ func cmdReverseProxy(fs caddycmd.Flags) (int, error) {
 | 
				
			|||||||
	if debug {
 | 
						if debug {
 | 
				
			||||||
		cfg.Logging = &caddy.Logging{
 | 
							cfg.Logging = &caddy.Logging{
 | 
				
			||||||
			Logs: map[string]*caddy.CustomLog{
 | 
								Logs: map[string]*caddy.CustomLog{
 | 
				
			||||||
				"default": {Level: zap.DebugLevel.CapitalString()},
 | 
									"default": {BaseLog: caddy.BaseLog{Level: zap.DebugLevel.CapitalString()}},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -407,7 +407,7 @@ func cmdRespond(fl caddycmd.Flags) (int, error) {
 | 
				
			|||||||
	if debug {
 | 
						if debug {
 | 
				
			||||||
		cfg.Logging = &caddy.Logging{
 | 
							cfg.Logging = &caddy.Logging{
 | 
				
			||||||
			Logs: map[string]*caddy.CustomLog{
 | 
								Logs: map[string]*caddy.CustomLog{
 | 
				
			||||||
				"default": {Level: zap.DebugLevel.CapitalString()},
 | 
									"default": {BaseLog: caddy.BaseLog{Level: zap.DebugLevel.CapitalString()}},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user