sequence
This paper mainly studies uber’s zap’s NewProduction.
Golang’s logs include Zap, Logrus, and others, although Logrus is now in maintenance.
The instance
SugaredLogger
func main() {
logger, _ := zap.NewProduction()
defer logger.Sync() // flushes buffer, if any
sugar := logger.Sugar()
url := "https://abc.com"
sugar.Infow("failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", url,
"attempt", 3,
"backoff", time.Second,
)
}
Copy the code
SugaredLogger is 4-10 times faster than a normal structured logging package
The output
{" level ", "info", "ts" : 1607095287.638658, "caller" : "the log - demo/zap_demo. Go: 14", "MSG" : "failed to fetch URL","url":"https://abc.com","attempt":3,"backoff":1}Copy the code
Logger
func main() {
logger, _ := zap.NewProduction()
defer logger.Sync()
url := "https://abc.com"
logger.Info("failed to fetch URL",
// Structured context as strongly typed Field values.
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
}
Copy the code
Logger is used for scenarios where performance and type-safety requirements are high. It is faster than SugaredLogger, but it only supports structured logging
The output
{" level ", "info", "ts" : 1607095675.5623732, "caller" : "the log - demo/zap_demo. Go: 25", "MSG" : "failed to fetch URL","url":"https://abc.com","attempt":3,"backoff":1}Copy the code
NewProduction
[email protected] / logger. Go
func NewProduction(options ... Option) (*Logger, error) { return NewProductionConfig().Build(options...) }Copy the code
NewProduction executes the NewProductionConfig().build method internally
NewProductionConfig
[email protected] / config. Go
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"},
}
}
Copy the code
The NewProductionConfig method creates Config with the default parameters, where encoding is JSON and output is STD
NewProductionEncoderConfig
[email protected] / config. Go
func NewProductionEncoderConfig() zapcore.EncoderConfig {
return zapcore.EncoderConfig{
TimeKey: "ts",
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
FunctionKey: zapcore.OmitKey,
MessageKey: "msg",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: zapcore.EpochTimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
}
}
Copy the code
NewProductionEncoderConfig created here zapcore EncoderConfig
Build
[email protected] / config. Go
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 } if cfg.Level == (AtomicLevel{}) { return nil, fmt.Errorf("missing Level") } log := New( zapcore.NewCore(enc, sink, cfg.Level), cfg.buildOptions(errSink)... , ) if len(opts) > 0 { log = log.WithOptions(opts...) } return log, nil }Copy the code
Build method executes cfg.buildEncoder(), cfg.openSinks(), zapcore.newcore and New methods
New
[email protected] / logger. Go
func New(core zapcore.Core, options ... Option) *Logger { if core == nil { return NewNop() } log := &Logger{ core: core, errorOutput: zapcore.Lock(os.Stderr), addStack: zapcore.FatalLevel + 1, } return log.WithOptions(options...) } func NewNop() *Logger { return &Logger{ core: zapcore.NewNopCore(), errorOutput: zapcore.AddSync(ioutil.Discard), addStack: zapcore.FatalLevel + 1, } }Copy the code
So here NewNop is returned for core nil, otherwise instantiate Logger; NewNop returns logger core as zapCore.newnopCore ()
Logger
[email protected] / logger. Go
type Logger struct {
core zapcore.Core
development bool
name string
errorOutput zapcore.WriteSyncer
addCaller bool
addStack zapcore.LevelEnabler
callerSkip int
onFatal zapcore.CheckWriteAction // default is WriteThenFatal
}
Copy the code
Logger defines core, development, name, errorOutput, addCaller, addStack, callerSkip, and onFatal attributes
summary
Zap. NewProduction () by creating NewProductionEncoderConfig again Build a Logger, set up a core, among which the New methods in the Logger errorOutput, addStack attribute
doc
- zap
- How to implement level based logging in golang?