mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-03 23:40:03 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			244 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright (c) 2016 Uber Technologies, Inc.
 | 
						|
//
 | 
						|
// Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
						|
// of this software and associated documentation files (the "Software"), to deal
 | 
						|
// in the Software without restriction, including without limitation the rights
 | 
						|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
						|
// copies of the Software, and to permit persons to whom the Software is
 | 
						|
// furnished to do so, subject to the following conditions:
 | 
						|
//
 | 
						|
// The above copyright notice and this permission notice shall be included in
 | 
						|
// all copies or substantial portions of the Software.
 | 
						|
//
 | 
						|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
						|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
						|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
						|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
						|
// THE SOFTWARE.
 | 
						|
 | 
						|
package zap
 | 
						|
 | 
						|
import (
 | 
						|
	"sort"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"go.uber.org/zap/zapcore"
 | 
						|
)
 | 
						|
 | 
						|
// SamplingConfig sets a sampling strategy for the logger. Sampling caps the
 | 
						|
// global CPU and I/O load that logging puts on your process while attempting
 | 
						|
// to preserve a representative subset of your logs.
 | 
						|
//
 | 
						|
// Values configured here are per-second. See zapcore.NewSampler for details.
 | 
						|
type SamplingConfig struct {
 | 
						|
	Initial    int `json:"initial" yaml:"initial"`
 | 
						|
	Thereafter int `json:"thereafter" yaml:"thereafter"`
 | 
						|
}
 | 
						|
 | 
						|
// Config offers a declarative way to construct a logger. It doesn't do
 | 
						|
// anything that can't be done with New, Options, and the various
 | 
						|
// zapcore.WriteSyncer and zapcore.Core wrappers, but it's a simpler way to
 | 
						|
// toggle common options.
 | 
						|
//
 | 
						|
// Note that Config intentionally supports only the most common options. More
 | 
						|
// unusual logging setups (logging to network connections or message queues,
 | 
						|
// splitting output between multiple files, etc.) are possible, but require
 | 
						|
// direct use of the zapcore package. For sample code, see the package-level
 | 
						|
// BasicConfiguration and AdvancedConfiguration examples.
 | 
						|
//
 | 
						|
// For an example showing runtime log level changes, see the documentation for
 | 
						|
// AtomicLevel.
 | 
						|
type Config struct {
 | 
						|
	// Level is the minimum enabled logging level. Note that this is a dynamic
 | 
						|
	// level, so calling Config.Level.SetLevel will atomically change the log
 | 
						|
	// level of all loggers descended from this config.
 | 
						|
	Level AtomicLevel `json:"level" yaml:"level"`
 | 
						|
	// Development puts the logger in development mode, which changes the
 | 
						|
	// behavior of DPanicLevel and takes stacktraces more liberally.
 | 
						|
	Development bool `json:"development" yaml:"development"`
 | 
						|
	// DisableCaller stops annotating logs with the calling function's file
 | 
						|
	// name and line number. By default, all logs are annotated.
 | 
						|
	DisableCaller bool `json:"disableCaller" yaml:"disableCaller"`
 | 
						|
	// DisableStacktrace completely disables automatic stacktrace capturing. By
 | 
						|
	// default, stacktraces are captured for WarnLevel and above logs in
 | 
						|
	// development and ErrorLevel and above in production.
 | 
						|
	DisableStacktrace bool `json:"disableStacktrace" yaml:"disableStacktrace"`
 | 
						|
	// Sampling sets a sampling policy. A nil SamplingConfig disables sampling.
 | 
						|
	Sampling *SamplingConfig `json:"sampling" yaml:"sampling"`
 | 
						|
	// Encoding sets the logger's encoding. Valid values are "json" and
 | 
						|
	// "console", as well as any third-party encodings registered via
 | 
						|
	// RegisterEncoder.
 | 
						|
	Encoding string `json:"encoding" yaml:"encoding"`
 | 
						|
	// EncoderConfig sets options for the chosen encoder. See
 | 
						|
	// zapcore.EncoderConfig for details.
 | 
						|
	EncoderConfig zapcore.EncoderConfig `json:"encoderConfig" yaml:"encoderConfig"`
 | 
						|
	// OutputPaths is a list of URLs or file paths to write logging output to.
 | 
						|
	// See Open for details.
 | 
						|
	OutputPaths []string `json:"outputPaths" yaml:"outputPaths"`
 | 
						|
	// ErrorOutputPaths is a list of URLs to write internal logger errors to.
 | 
						|
	// The default is standard error.
 | 
						|
	//
 | 
						|
	// Note that this setting only affects internal errors; for sample code that
 | 
						|
	// sends error-level logs to a different location from info- and debug-level
 | 
						|
	// logs, see the package-level AdvancedConfiguration example.
 | 
						|
	ErrorOutputPaths []string `json:"errorOutputPaths" yaml:"errorOutputPaths"`
 | 
						|
	// InitialFields is a collection of fields to add to the root logger.
 | 
						|
	InitialFields map[string]interface{} `json:"initialFields" yaml:"initialFields"`
 | 
						|
}
 | 
						|
 | 
						|
// NewProductionEncoderConfig returns an opinionated EncoderConfig for
 | 
						|
// production environments.
 | 
						|
func NewProductionEncoderConfig() zapcore.EncoderConfig {
 | 
						|
	return zapcore.EncoderConfig{
 | 
						|
		TimeKey:        "ts",
 | 
						|
		LevelKey:       "level",
 | 
						|
		NameKey:        "logger",
 | 
						|
		CallerKey:      "caller",
 | 
						|
		MessageKey:     "msg",
 | 
						|
		StacktraceKey:  "stacktrace",
 | 
						|
		LineEnding:     zapcore.DefaultLineEnding,
 | 
						|
		EncodeLevel:    zapcore.LowercaseLevelEncoder,
 | 
						|
		EncodeTime:     zapcore.EpochTimeEncoder,
 | 
						|
		EncodeDuration: zapcore.SecondsDurationEncoder,
 | 
						|
		EncodeCaller:   zapcore.ShortCallerEncoder,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// NewProductionConfig is a reasonable production logging configuration.
 | 
						|
// Logging is enabled at InfoLevel and above.
 | 
						|
//
 | 
						|
// It uses a JSON encoder, writes to standard error, and enables sampling.
 | 
						|
// Stacktraces are automatically included on logs of ErrorLevel and above.
 | 
						|
func NewProductionConfig() Config {
 | 
						|
	return Config{
 | 
						|
		Level:       NewAtomicLevelAt(InfoLevel),
 | 
						|
		Development: false,
 | 
						|
		Sampling: &SamplingConfig{
 | 
						|
			Initial:    100,
 | 
						|
			Thereafter: 100,
 | 
						|
		},
 | 
						|
		Encoding:         "json",
 | 
						|
		EncoderConfig:    NewProductionEncoderConfig(),
 | 
						|
		OutputPaths:      []string{"stderr"},
 | 
						|
		ErrorOutputPaths: []string{"stderr"},
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// NewDevelopmentEncoderConfig returns an opinionated EncoderConfig for
 | 
						|
// development environments.
 | 
						|
func NewDevelopmentEncoderConfig() zapcore.EncoderConfig {
 | 
						|
	return zapcore.EncoderConfig{
 | 
						|
		// Keys can be anything except the empty string.
 | 
						|
		TimeKey:        "T",
 | 
						|
		LevelKey:       "L",
 | 
						|
		NameKey:        "N",
 | 
						|
		CallerKey:      "C",
 | 
						|
		MessageKey:     "M",
 | 
						|
		StacktraceKey:  "S",
 | 
						|
		LineEnding:     zapcore.DefaultLineEnding,
 | 
						|
		EncodeLevel:    zapcore.CapitalLevelEncoder,
 | 
						|
		EncodeTime:     zapcore.ISO8601TimeEncoder,
 | 
						|
		EncodeDuration: zapcore.StringDurationEncoder,
 | 
						|
		EncodeCaller:   zapcore.ShortCallerEncoder,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// NewDevelopmentConfig is a reasonable development logging configuration.
 | 
						|
// Logging is enabled at DebugLevel and above.
 | 
						|
//
 | 
						|
// It enables development mode (which makes DPanicLevel logs panic), uses a
 | 
						|
// console encoder, writes to standard error, and disables sampling.
 | 
						|
// Stacktraces are automatically included on logs of WarnLevel and above.
 | 
						|
func NewDevelopmentConfig() Config {
 | 
						|
	return Config{
 | 
						|
		Level:            NewAtomicLevelAt(DebugLevel),
 | 
						|
		Development:      true,
 | 
						|
		Encoding:         "console",
 | 
						|
		EncoderConfig:    NewDevelopmentEncoderConfig(),
 | 
						|
		OutputPaths:      []string{"stderr"},
 | 
						|
		ErrorOutputPaths: []string{"stderr"},
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Build constructs a logger from the Config and Options.
 | 
						|
func (cfg Config) Build(opts ...Option) (*Logger, error) {
 | 
						|
	enc, err := cfg.buildEncoder()
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	sink, errSink, err := cfg.openSinks()
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	log := New(
 | 
						|
		zapcore.NewCore(enc, sink, cfg.Level),
 | 
						|
		cfg.buildOptions(errSink)...,
 | 
						|
	)
 | 
						|
	if len(opts) > 0 {
 | 
						|
		log = log.WithOptions(opts...)
 | 
						|
	}
 | 
						|
	return log, nil
 | 
						|
}
 | 
						|
 | 
						|
func (cfg Config) buildOptions(errSink zapcore.WriteSyncer) []Option {
 | 
						|
	opts := []Option{ErrorOutput(errSink)}
 | 
						|
 | 
						|
	if cfg.Development {
 | 
						|
		opts = append(opts, Development())
 | 
						|
	}
 | 
						|
 | 
						|
	if !cfg.DisableCaller {
 | 
						|
		opts = append(opts, AddCaller())
 | 
						|
	}
 | 
						|
 | 
						|
	stackLevel := ErrorLevel
 | 
						|
	if cfg.Development {
 | 
						|
		stackLevel = WarnLevel
 | 
						|
	}
 | 
						|
	if !cfg.DisableStacktrace {
 | 
						|
		opts = append(opts, AddStacktrace(stackLevel))
 | 
						|
	}
 | 
						|
 | 
						|
	if cfg.Sampling != nil {
 | 
						|
		opts = append(opts, WrapCore(func(core zapcore.Core) zapcore.Core {
 | 
						|
			return zapcore.NewSampler(core, time.Second, int(cfg.Sampling.Initial), int(cfg.Sampling.Thereafter))
 | 
						|
		}))
 | 
						|
	}
 | 
						|
 | 
						|
	if len(cfg.InitialFields) > 0 {
 | 
						|
		fs := make([]Field, 0, len(cfg.InitialFields))
 | 
						|
		keys := make([]string, 0, len(cfg.InitialFields))
 | 
						|
		for k := range cfg.InitialFields {
 | 
						|
			keys = append(keys, k)
 | 
						|
		}
 | 
						|
		sort.Strings(keys)
 | 
						|
		for _, k := range keys {
 | 
						|
			fs = append(fs, Any(k, cfg.InitialFields[k]))
 | 
						|
		}
 | 
						|
		opts = append(opts, Fields(fs...))
 | 
						|
	}
 | 
						|
 | 
						|
	return opts
 | 
						|
}
 | 
						|
 | 
						|
func (cfg Config) openSinks() (zapcore.WriteSyncer, zapcore.WriteSyncer, error) {
 | 
						|
	sink, closeOut, err := Open(cfg.OutputPaths...)
 | 
						|
	if err != nil {
 | 
						|
		return nil, nil, err
 | 
						|
	}
 | 
						|
	errSink, _, err := Open(cfg.ErrorOutputPaths...)
 | 
						|
	if err != nil {
 | 
						|
		closeOut()
 | 
						|
		return nil, nil, err
 | 
						|
	}
 | 
						|
	return sink, errSink, nil
 | 
						|
}
 | 
						|
 | 
						|
func (cfg Config) buildEncoder() (zapcore.Encoder, error) {
 | 
						|
	return newEncoder(cfg.Encoding, cfg.EncoderConfig)
 | 
						|
}
 |