This commit is contained in:
oneao committed 2026-02-25 17:31:09 +08:00
1 parent 835958886e
commit d04d22723b
155 files changed
+543 -9793

No files matched your search

+59
View File
@@ -0,0 +1,59 @@
package logx
import (
"context"
"github.com/cloudwego/hertz/pkg/common/hlog"
"go.uber.org/zap"
)
// getRequestID 从 context 中取 RequestID,如果没有则返回空字符串
func getRequestID(ctx context.Context) string {
if ctx == nil {
return ""
}
if rid, ok := ctx.Value("RequestID").(string); ok {
return rid
}
return ""
}
func CtxInfo(ctx context.Context, v ...interface{}) {
rid := getRequestID(ctx)
if rid != "" {
v = append(v, zap.String("RequestID", rid))
}
hlog.Info(v...)
}
func CtxError(ctx context.Context, v ...interface{}) {
rid := getRequestID(ctx)
if rid != "" {
v = append(v, zap.String("RequestID", rid))
}
hlog.Error(v...)
}
func CtxWarn(ctx context.Context, v ...interface{}) {
rid := getRequestID(ctx)
if rid != "" {
v = append(v, zap.String("RequestID", rid))
}
hlog.Warn(v...)
}
func CtxDebug(ctx context.Context, v ...interface{}) {
rid := getRequestID(ctx)
if rid != "" {
v = append(v, zap.String("RequestID", rid))
}
hlog.Debug(v...)
}
func CtxFatal(ctx context.Context, v ...interface{}) {
rid := getRequestID(ctx)
if rid != "" {
v = append(v, zap.String("RequestID", rid))
}
hlog.Fatal(v...)
}
+160
View File
@@ -0,0 +1,160 @@
package logx
import (
"fmt"
"os"
"sync"
"time"
"allapp/conf"
"github.com/cloudwego/hertz/pkg/common/hlog"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
)
var (
zapLogger *zap.Logger
mu sync.Mutex
currentDay = make(map[string]string)
currentSync = make(map[string]zapcore.WriteSyncer)
)
// InitLog 从配置初始化日志
func InitLog() {
cfg := conf.GetConf().Log // LogConfig 从 YAML 读取
if cfg.Dir == "" {
cfg.Dir = "./logs"
}
if cfg.MaxSize <= 0 {
cfg.MaxSize = 10
}
if cfg.MaxBackups <= 0 {
cfg.MaxBackups = 30
}
if cfg.MaxAge <= 0 {
cfg.MaxAge = 7
}
dynamicLevel := zap.NewAtomicLevel()
dynamicLevel.SetLevel(LogLevel())
logger := NewLogger(
WithCores([]CoreConfig{
{
Enc: zapcore.NewConsoleEncoder(consoleEncoderConfig()),
Ws: zapcore.AddSync(os.Stdout),
Lvl: dynamicLevel,
},
{
Enc: zapcore.NewJSONEncoder(humanEncoderConfig()),
Ws: getWriteSyncer(fmt.Sprintf("%s/debug", cfg.Dir), &cfg),
Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
return lev == zap.DebugLevel
}),
},
{
Enc: zapcore.NewJSONEncoder(humanEncoderConfig()),
Ws: getWriteSyncer(fmt.Sprintf("%s/info", cfg.Dir), &cfg),
Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
return lev == zap.InfoLevel
}),
},
{
Enc: zapcore.NewJSONEncoder(humanEncoderConfig()),
Ws: getWriteSyncer(fmt.Sprintf("%s/warn", cfg.Dir), &cfg),
Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
return lev == zap.WarnLevel
}),
},
{
Enc: zapcore.NewJSONEncoder(humanEncoderConfig()),
Ws: getWriteSyncer(fmt.Sprintf("%s/error", cfg.Dir), &cfg),
Lvl: zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
return lev >= zap.ErrorLevel
}),
},
}...),
)
hlog.SetLogger(logger)
zapLogger = logger.Logger()
}
func getWriteSyncer(basePath string, cfg *conf.LogConfig) zapcore.WriteSyncer {
mu.Lock()
defer mu.Unlock()
today := time.Now().Format("2006-01-02")
if day, ok := currentDay[basePath]; !ok || day != today {
currentDay[basePath] = today
file := fmt.Sprintf("%s/%s.log", basePath, today)
currentSync[basePath] = zapcore.AddSync(&lumberjack.Logger{
Filename: file,
MaxSize: cfg.MaxSize,
MaxBackups: cfg.MaxBackups,
MaxAge: cfg.MaxAge,
Compress: cfg.Compress,
LocalTime: true,
})
}
return currentSync[basePath]
}
func LogLevel() zapcore.Level {
level := conf.GetConf().Log.Level
switch level {
case "trace":
return zapcore.DebugLevel
case "debug":
return zapcore.DebugLevel
case "info":
return zapcore.InfoLevel
case "warn":
return zapcore.WarnLevel
case "error":
return zapcore.ErrorLevel
case "dpanic":
return zapcore.DPanicLevel
case "panic":
return zapcore.PanicLevel
case "fatal":
return zapcore.FatalLevel
default:
return zapcore.InfoLevel
}
}
func consoleEncoderConfig() zapcore.EncoderConfig {
return zapcore.EncoderConfig{
MessageKey: "msg",
LevelKey: "level",
TimeKey: "ts",
EncodeTime: customTimeEncoder,
EncodeLevel: zapcore.CapitalColorLevelEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
}
}
func humanEncoderConfig() zapcore.EncoderConfig {
return zapcore.EncoderConfig{
MessageKey: "Message",
LevelKey: "Level",
NameKey: "Name",
TimeKey: "Ts",
CallerKey: "Caller",
FunctionKey: "Func",
StacktraceKey: "Stacktrace",
LineEnding: "\n",
EncodeTime: customTimeEncoder,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
}
}
func customTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
}
+268
View File
@@ -0,0 +1,268 @@
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()
}
+115
View File
@@ -0,0 +1,115 @@
package logx
import (
"os"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type Option interface {
apply(cfg *config)
}
type ExtraKey string
type option func(cfg *config)
func (fn option) apply(cfg *config) {
fn(cfg)
}
type CoreConfig struct {
Enc zapcore.Encoder
Ws zapcore.WriteSyncer
Lvl zapcore.LevelEnabler
}
type config struct {
extraKeys []ExtraKey
coreConfigs []CoreConfig
zapOpts []zap.Option
extraKeyAsStr bool
}
// defaultCoreConfig default zapcore config: json encoder, atomic level, stdout write syncer
func defaultCoreConfig() *CoreConfig {
// default log encoder
enc := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
// default log level
lvl := zap.NewAtomicLevelAt(zap.InfoLevel)
// default write syncer stdout
ws := zapcore.AddSync(os.Stdout)
return &CoreConfig{
Enc: enc,
Ws: ws,
Lvl: lvl,
}
}
// defaultConfig default config
func defaultConfig() *config {
return &config{
coreConfigs: []CoreConfig{*defaultCoreConfig()},
zapOpts: []zap.Option{},
extraKeyAsStr: false,
}
}
// WithCoreEnc zapcore encoder
func WithCoreEnc(enc zapcore.Encoder) Option {
return option(func(cfg *config) {
cfg.coreConfigs[0].Enc = enc
})
}
// WithCoreWs zapcore write syncer
func WithCoreWs(ws zapcore.WriteSyncer) Option {
return option(func(cfg *config) {
cfg.coreConfigs[0].Ws = ws
})
}
// WithCoreLevel zapcore log level
func WithCoreLevel(lvl zap.AtomicLevel) Option {
return option(func(cfg *config) {
cfg.coreConfigs[0].Lvl = lvl
})
}
// WithCores zapcore
func WithCores(coreConfigs ...CoreConfig) Option {
return option(func(cfg *config) {
cfg.coreConfigs = coreConfigs
})
}
// WithZapOptions add origin zap option
func WithZapOptions(opts ...zap.Option) Option {
return option(func(cfg *config) {
cfg.zapOpts = append(cfg.zapOpts, opts...)
})
}
// WithExtraKeys allow you log extra values from context
func WithExtraKeys(keys []ExtraKey) Option {
return option(func(cfg *config) {
for _, k := range keys {
if !InArray(k, cfg.extraKeys) {
cfg.extraKeys = append(cfg.extraKeys, k)
}
}
})
}
// WithExtraKeyAsStr convert extraKey to a string type when retrieving value from context
// Not recommended for use, only for compatibility with certain situations
//
// For more information, refer to the documentation at
// `https://pkg.go.dev/context#WithValue`
func WithExtraKeyAsStr() Option {
return option(func(cfg *config) {
cfg.extraKeyAsStr = true
})
}
+36
View File
@@ -0,0 +1,36 @@
package logx
import (
"github.com/cloudwego/hertz/pkg/common/hlog"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
// InArray check if a string in a slice
func InArray(key ExtraKey, arr []ExtraKey) bool {
for _, k := range arr {
if k == key {
return true
}
}
return false
}
func hLevelToZapLevel(level hlog.Level) zapcore.Level {
var lvl zapcore.Level
switch level {
case hlog.LevelTrace, hlog.LevelDebug:
lvl = zap.DebugLevel
case hlog.LevelInfo:
lvl = zap.InfoLevel
case hlog.LevelWarn, hlog.LevelNotice:
lvl = zap.WarnLevel
case hlog.LevelError:
lvl = zap.ErrorLevel
case hlog.LevelFatal:
lvl = zap.FatalLevel
default:
lvl = zap.WarnLevel
}
return lvl
}