基于 `zap` 包封装。除了实现 `Go` 日志包的基本功能外,还实现了很多高级功能 本包基于`github.com/tkestack/tke/pkg/util/log`裁剪
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
4.7 KiB

package log
import (
"encoding/json"
"fmt"
"github.com/spf13/pflag"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"strings"
)
const (
flagLevel = "log.level"
flagDisableCaller = "log.disable-caller"
flagDisableStacktrace = "log.disable-stacktrace"
flagFormat = "log.format"
flagEnableColor = "log.enable-color"
flagOutputPaths = "log.output-paths"
flagErrorOutputPaths = "log.error-output-paths"
flagDevelopment = "log.development"
flagName = "log.name"
ConsoleFormat = "console"
JsonFormat = "json"
)
// Options 日志有关的配置. 设置参考zap的配置
type Options struct {
OutputPaths []string `json:"output-paths" mapstructure:"output-paths"`
ErrorOutputPaths []string `json:"error-output-paths" mapstructure:"error-output-paths"`
Level string `json:"level" mapstructure:"level"`
Format string `json:"format" mapstructure:"format"`
DisableCaller bool `json:"disable-caller" mapstructure:"disable-caller"`
DisableStacktrace bool `json:"disable-stacktrace" mapstructure:"disable-stacktrace"`
EnableColor bool `json:"enable-color" mapstructure:"enable-color"`
Development bool `json:"development" mapstructure:"development"`
Name string `json:"name" mapstructure:"name"`
}
// NewOptions 新建带默认参数的日志配置
func NewOptions() *Options {
return &Options{
Level: zapcore.InfoLevel.String(),
DisableCaller: false,
DisableStacktrace: false,
Format: ConsoleFormat,
EnableColor: false,
Development: false,
OutputPaths: []string{"stdout"},
ErrorOutputPaths: []string{"stderr"},
}
}
// Validate 验证日志配置.
func (o *Options) Validate() []error {
var errs []error
var zapLevel zapcore.Level
if err := zapLevel.UnmarshalText([]byte(o.Level)); err != nil {
errs = append(errs, err)
}
format := strings.ToLower(o.Format)
if format != ConsoleFormat && format != JsonFormat {
errs = append(errs, fmt.Errorf("not a valid log format: %q", o.Format))
}
return errs
}
// AddFlags 读取命令行参数设置日志配置
func (o *Options) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&o.Level, flagLevel, o.Level, "Minimum log output `LEVEL`.")
fs.BoolVar(&o.DisableCaller, flagDisableCaller, o.DisableCaller, "Disable output of caller information in the log.")
fs.BoolVar(&o.DisableStacktrace, flagDisableStacktrace,
o.DisableStacktrace, "Disable the log to record a stack trace for all messages at or above panic level.")
fs.StringVar(&o.Format, flagFormat, o.Format, "Log output `FORMAT`, support plain or json format.")
fs.BoolVar(&o.EnableColor, flagEnableColor, o.EnableColor, "Enable output ansi colors in plain format logs.")
fs.StringSliceVar(&o.OutputPaths, flagOutputPaths, o.OutputPaths, "Output paths of log.")
fs.StringSliceVar(&o.ErrorOutputPaths, flagErrorOutputPaths, o.ErrorOutputPaths, "Error output paths of log.")
fs.BoolVar(
&o.Development,
flagDevelopment,
o.Development,
"Development puts the logger in development mode, which changes "+
"the behavior of DPanicLevel and takes stacktraces more liberally.",
)
fs.StringVar(&o.Name, flagName, o.Name, "The name of the logger.")
}
func (o *Options) String() string {
data, _ := json.Marshal(o)
return string(data)
}
// Build 将设置安装到全局zap logger
func (o *Options) Build() error {
var zapLevel zapcore.Level
if err := zapLevel.UnmarshalText([]byte(o.Level)); err != nil {
zapLevel = zapcore.InfoLevel
}
encodeLevel := zapcore.CapitalLevelEncoder
if o.Format == ConsoleFormat && o.EnableColor {
encodeLevel = zapcore.CapitalColorLevelEncoder
}
zc := &zap.Config{
Level: zap.NewAtomicLevelAt(zapLevel),
Development: o.Development,
DisableCaller: o.DisableCaller,
DisableStacktrace: o.DisableStacktrace,
Sampling: &zap.SamplingConfig{
Initial: 100,
Thereafter: 100,
},
Encoding: o.Format,
EncoderConfig: zapcore.EncoderConfig{
MessageKey: "message",
LevelKey: "level",
TimeKey: "timestamp",
NameKey: "logger",
CallerKey: "caller",
StacktraceKey: "stacktrace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: encodeLevel,
EncodeTime: timeEncoder,
EncodeDuration: autoDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeName: zapcore.FullNameEncoder,
},
OutputPaths: o.OutputPaths,
ErrorOutputPaths: o.ErrorOutputPaths,
}
logger, err := zc.Build(zap.AddStacktrace(zapcore.PanicLevel))
if err != nil {
return err
}
zap.RedirectStdLog(logger.Named(o.Name))
zap.ReplaceGlobals(logger)
return nil
}