// Copyright 2019 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // See the License for the specific language governing permissions and // limitations under the License. package log import ( "time" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) const ( defaultLogMaxSize = 300 // MB ) // FileLogConfig serializes file log related config in toml/json. type FileLogConfig struct { // Log filename, leave empty to disable file log. Filename string `toml:"filename" json:"filename"` // Is log rotate enabled. LogRotate bool `toml:"log-rotate" json:"log-rotate"` // Max size for a single file, in MB. MaxSize int `toml:"max-size" json:"max-size"` // Max log keep days, default is never deleting. MaxDays int `toml:"max-days" json:"max-days"` // Maximum number of old log files to retain. MaxBackups int `toml:"max-backups" json:"max-backups"` } // Config serializes log related config in toml/json. type Config struct { // Log level. Level string `toml:"level" json:"level"` // Log format. one of json, text, or console. Format string `toml:"format" json:"format"` // Disable automatic timestamps in output. DisableTimestamp bool `toml:"disable-timestamp" json:"disable-timestamp"` // File log config. File FileLogConfig `toml:"file" json:"file"` // Development puts the logger in development mode, which changes the // behavior of DPanicLevel and takes stacktraces more liberally. Development bool `toml:"development" json:"development"` // DisableCaller stops annotating logs with the calling function's file // name and line number. By default, all logs are annotated. DisableCaller bool `toml:"disable-caller" json:"disable-caller"` // 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 `toml:"disable-stacktrace" json:"disable-stacktrace"` // 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. Sampling *zap.SamplingConfig `toml:"sampling" json:"sampling"` } // ZapProperties records some information about zap. type ZapProperties struct { Core zapcore.Core Syncer zapcore.WriteSyncer Level zap.AtomicLevel } func newZapTextEncoder(cfg *Config) zapcore.Encoder { cc := zapcore.EncoderConfig{ // Keys can be anything except the empty string. TimeKey: "time", LevelKey: "level", NameKey: "name", CallerKey: "caller", MessageKey: "message", StacktraceKey: "stack", LineEnding: zapcore.DefaultLineEnding, EncodeLevel: zapcore.CapitalLevelEncoder, EncodeTime: DefaultTimeEncoder, EncodeDuration: zapcore.StringDurationEncoder, EncodeCaller: ShortCallerEncoder, } if cfg.DisableTimestamp { cc.TimeKey = "" } return NewTextEncoder(cc) } func (cfg *Config) buildOptions(errSink zapcore.WriteSyncer) []zap.Option { opts := []zap.Option{zap.ErrorOutput(errSink)} if cfg.Development { opts = append(opts, zap.Development()) } if !cfg.DisableCaller { opts = append(opts, zap.AddCaller()) } stackLevel := zap.ErrorLevel if cfg.Development { stackLevel = zap.WarnLevel } if !cfg.DisableStacktrace { opts = append(opts, zap.AddStacktrace(stackLevel)) } if cfg.Sampling != nil { opts = append(opts, zap.WrapCore(func(core zapcore.Core) zapcore.Core { return zapcore.NewSampler(core, time.Second, int(cfg.Sampling.Initial), int(cfg.Sampling.Thereafter)) })) } return opts }