package logx import ( "context" "fmt" "io" "github.com/cloudwego/hertz/pkg/common/hlog" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) var _ hlog.FullLogger = (*Logger)(nil) type Logger struct { l *zap.Logger config *config } func NewLogger(opts ...Option) *Logger { config := defaultConfig() // apply options for _, opt := range opts { opt.apply(config) } cores := make([]zapcore.Core, 0, len(config.coreConfigs)) for _, coreConfig := range config.coreConfigs { cores = append(cores, zapcore.NewCore(coreConfig.Enc, coreConfig.Ws, coreConfig.Lvl)) } logger := zap.New( zapcore.NewTee(cores[:]...), config.zapOpts...) return &Logger{ l: logger, config: config, } } // GetExtraKeys get extraKeys from logger config func (l *Logger) GetExtraKeys() []ExtraKey { return l.config.extraKeys } // PutExtraKeys add extraKeys after init func (l *Logger) PutExtraKeys(keys ...ExtraKey) { for _, k := range keys { if !InArray(k, l.config.extraKeys) { l.config.extraKeys = append(l.config.extraKeys, k) } } } func (l *Logger) Log(level hlog.Level, kvs ...interface{}) { if len(kvs) == 0 { return } // 第一个参数作为 msg msg := fmt.Sprint(kvs[0]) // 后续参数作为 zap.Field fields := make([]zap.Field, 0, len(kvs)-1) for _, v := range kvs[1:] { if f, ok := v.(zap.Field); ok { fields = append(fields, f) } } switch level { case hlog.LevelTrace, hlog.LevelDebug: l.l.Debug(msg, fields...) case hlog.LevelInfo: l.l.Info(msg, fields...) case hlog.LevelNotice, hlog.LevelWarn: l.l.Warn(msg, fields...) case hlog.LevelError: l.l.Error(msg, fields...) case hlog.LevelFatal: l.l.Fatal(msg, fields...) default: l.l.Warn(msg, fields...) } } func (l *Logger) Logf(level hlog.Level, format string, kvs ...interface{}) { logger := l.l.Sugar().With() switch level { case hlog.LevelTrace, hlog.LevelDebug: logger.Debugf(format, kvs...) case hlog.LevelInfo: logger.Infof(format, kvs...) case hlog.LevelNotice, hlog.LevelWarn: logger.Warnf(format, kvs...) case hlog.LevelError: logger.Errorf(format, kvs...) case hlog.LevelFatal: logger.Fatalf(format, kvs...) default: logger.Warnf(format, kvs...) } } func (l *Logger) CtxLogf(level hlog.Level, ctx context.Context, format string, kvs ...interface{}) { zLevel := hLevelToZapLevel(level) if !l.config.coreConfigs[0].Lvl.Enabled(zLevel) { return } zapLogger := l.l if len(l.config.extraKeys) > 0 { for _, k := range l.config.extraKeys { if l.config.extraKeyAsStr { v := ctx.Value(string(k)) if v != nil { zapLogger = zapLogger.With(zap.Any(string(k), v)) } } else { v := ctx.Value(k) if v != nil { zapLogger = zapLogger.With(zap.Any(string(k), v)) } } } } log := zapLogger.Sugar() switch level { case hlog.LevelDebug, hlog.LevelTrace: log.Debugf(format, kvs...) case hlog.LevelInfo: log.Infof(format, kvs...) case hlog.LevelNotice, hlog.LevelWarn: log.Warnf(format, kvs...) case hlog.LevelError: log.Errorf(format, kvs...) case hlog.LevelFatal: log.Fatalf(format, kvs...) default: log.Warnf(format, kvs...) } } func (l *Logger) Trace(v ...interface{}) { l.Log(hlog.LevelTrace, v...) } func (l *Logger) Debug(v ...interface{}) { l.Log(hlog.LevelDebug, v...) } func (l *Logger) Info(v ...interface{}) { l.Log(hlog.LevelInfo, v...) } func (l *Logger) Notice(v ...interface{}) { l.Log(hlog.LevelNotice, v...) } func (l *Logger) Warn(v ...interface{}) { l.Log(hlog.LevelWarn, v...) } func (l *Logger) Error(v ...interface{}) { l.Log(hlog.LevelError, v...) } func (l *Logger) Fatal(v ...interface{}) { l.Log(hlog.LevelFatal, v...) } func (l *Logger) Tracef(format string, v ...interface{}) { l.Logf(hlog.LevelTrace, format, v...) } func (l *Logger) Debugf(format string, v ...interface{}) { l.Logf(hlog.LevelDebug, format, v...) } func (l *Logger) Infof(format string, v ...interface{}) { l.Logf(hlog.LevelInfo, format, v...) } func (l *Logger) Noticef(format string, v ...interface{}) { l.Logf(hlog.LevelWarn, format, v...) } func (l *Logger) Warnf(format string, v ...interface{}) { l.Logf(hlog.LevelWarn, format, v...) } func (l *Logger) Errorf(format string, v ...interface{}) { l.Logf(hlog.LevelError, format, v...) } func (l *Logger) Fatalf(format string, v ...interface{}) { l.Logf(hlog.LevelFatal, format, v...) } func (l *Logger) CtxTracef(ctx context.Context, format string, v ...interface{}) { l.CtxLogf(hlog.LevelDebug, ctx, format, v...) } func (l *Logger) CtxDebugf(ctx context.Context, format string, v ...interface{}) { l.CtxLogf(hlog.LevelDebug, ctx, format, v...) } func (l *Logger) CtxInfof(ctx context.Context, format string, v ...interface{}) { l.CtxLogf(hlog.LevelInfo, ctx, format, v...) } func (l *Logger) CtxNoticef(ctx context.Context, format string, v ...interface{}) { l.CtxLogf(hlog.LevelWarn, ctx, format, v...) } func (l *Logger) CtxWarnf(ctx context.Context, format string, v ...interface{}) { l.CtxLogf(hlog.LevelWarn, ctx, format, v...) } func (l *Logger) CtxErrorf(ctx context.Context, format string, v ...interface{}) { l.CtxLogf(hlog.LevelError, ctx, format, v...) } func (l *Logger) CtxFatalf(ctx context.Context, format string, v ...interface{}) { l.CtxLogf(hlog.LevelFatal, ctx, format, v...) } func (l *Logger) SetLevel(level hlog.Level) { lvl := hLevelToZapLevel(level) l.config.coreConfigs[0].Lvl = lvl cores := make([]zapcore.Core, 0, len(l.config.coreConfigs)) for _, coreConfig := range l.config.coreConfigs { cores = append(cores, zapcore.NewCore(coreConfig.Enc, coreConfig.Ws, coreConfig.Lvl)) } logger := zap.New( zapcore.NewTee(cores[:]...), l.config.zapOpts...) l.l = logger } func (l *Logger) SetOutput(writer io.Writer) { l.config.coreConfigs[0].Ws = zapcore.AddSync(writer) cores := make([]zapcore.Core, 0, len(l.config.coreConfigs)) for _, coreConfig := range l.config.coreConfigs { cores = append(cores, zapcore.NewCore(coreConfig.Enc, coreConfig.Ws, coreConfig.Lvl)) } logger := zap.New( zapcore.NewTee(cores[:]...), l.config.zapOpts...) l.l = logger } // Logger is used to return an instance of *zap.Logger for custom fields, etc. func (l *Logger) Logger() *zap.Logger { return l.l } func (l *Logger) Sync() { _ = l.l.Sync() }