m
This commit is contained in:
1 parent
76a6c81af2
commit
b19d083031
68 files changed
+3889
-343
No files matched your search
@@ -0,0 +1,86 @@
|
||||
package logx
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func String(key, val string) zap.Field { return zap.String(key, val) }
|
||||
func Stringp(key string, val *string) zap.Field { return zap.Stringp(key, val) }
|
||||
func Strings(key string, val []string) zap.Field { return zap.Strings(key, val) }
|
||||
|
||||
func Bool(key string, val bool) zap.Field { return zap.Bool(key, val) }
|
||||
func Boolp(key string, val *bool) zap.Field { return zap.Boolp(key, val) }
|
||||
func Bools(key string, val []bool) zap.Field { return zap.Bools(key, val) }
|
||||
|
||||
func Int(key string, val int) zap.Field { return zap.Int(key, val) }
|
||||
func Intp(key string, val *int) zap.Field { return zap.Intp(key, val) }
|
||||
func Ints(key string, val []int) zap.Field { return zap.Ints(key, val) }
|
||||
|
||||
func Int64(key string, val int64) zap.Field { return zap.Int64(key, val) }
|
||||
func Int64p(key string, val *int64) zap.Field { return zap.Int64p(key, val) }
|
||||
func Int64s(key string, val []int64) zap.Field { return zap.Int64s(key, val) }
|
||||
|
||||
func Int32(key string, val int32) zap.Field { return zap.Int32(key, val) }
|
||||
func Int32p(key string, val *int32) zap.Field { return zap.Int32p(key, val) }
|
||||
func Int32s(key string, val []int32) zap.Field { return zap.Int32s(key, val) }
|
||||
|
||||
func Int16(key string, val int16) zap.Field { return zap.Int16(key, val) }
|
||||
func Int16p(key string, val *int16) zap.Field { return zap.Int16p(key, val) }
|
||||
func Int16s(key string, val []int16) zap.Field { return zap.Int16s(key, val) }
|
||||
|
||||
func Int8(key string, val int8) zap.Field { return zap.Int8(key, val) }
|
||||
func Int8p(key string, val *int8) zap.Field { return zap.Int8p(key, val) }
|
||||
func Int8s(key string, val []int8) zap.Field { return zap.Int8s(key, val) }
|
||||
|
||||
func Uint(key string, val uint) zap.Field { return zap.Uint(key, val) }
|
||||
func Uintp(key string, val *uint) zap.Field { return zap.Uintp(key, val) }
|
||||
func Uints(key string, val []uint) zap.Field { return zap.Uints(key, val) }
|
||||
|
||||
func Uint64(key string, val uint64) zap.Field { return zap.Uint64(key, val) }
|
||||
func Uint64p(key string, val *uint64) zap.Field { return zap.Uint64p(key, val) }
|
||||
func Uint64s(key string, val []uint64) zap.Field { return zap.Uint64s(key, val) }
|
||||
|
||||
func Uint32(key string, val uint32) zap.Field { return zap.Uint32(key, val) }
|
||||
func Uint32p(key string, val *uint32) zap.Field { return zap.Uint32p(key, val) }
|
||||
func Uint32s(key string, val []uint32) zap.Field { return zap.Uint32s(key, val) }
|
||||
|
||||
func Uint16(key string, val uint16) zap.Field { return zap.Uint16(key, val) }
|
||||
func Uint16p(key string, val *uint16) zap.Field { return zap.Uint16p(key, val) }
|
||||
func Uint16s(key string, val []uint16) zap.Field { return zap.Uint16s(key, val) }
|
||||
|
||||
func Uint8(key string, val uint8) zap.Field { return zap.Uint8(key, val) }
|
||||
func Uint8p(key string, val *uint8) zap.Field { return zap.Uint8p(key, val) }
|
||||
|
||||
func Uintptr(key string, val uintptr) zap.Field { return zap.Uintptr(key, val) }
|
||||
func Uintptrp(key string, val *uintptr) zap.Field { return zap.Uintptrp(key, val) }
|
||||
func Uintptrs(key string, val []uintptr) zap.Field { return zap.Uintptrs(key, val) }
|
||||
|
||||
func Float32(key string, val float32) zap.Field { return zap.Float32(key, val) }
|
||||
func Float32p(key string, val *float32) zap.Field { return zap.Float32p(key, val) }
|
||||
func Float32s(key string, val []float32) zap.Field { return zap.Float32s(key, val) }
|
||||
|
||||
func Float64(key string, val float64) zap.Field { return zap.Float64(key, val) }
|
||||
func Float64p(key string, val *float64) zap.Field { return zap.Float64p(key, val) }
|
||||
func Float64s(key string, val []float64) zap.Field { return zap.Float64s(key, val) }
|
||||
|
||||
func Complex64(key string, val complex64) zap.Field { return zap.Complex64(key, val) }
|
||||
func Complex64p(key string, val *complex64) zap.Field { return zap.Complex64p(key, val) }
|
||||
func Complex64s(key string, val []complex64) zap.Field { return zap.Complex64s(key, val) }
|
||||
|
||||
func Complex128(key string, val complex128) zap.Field { return zap.Complex128(key, val) }
|
||||
func Complex128p(key string, val *complex128) zap.Field { return zap.Complex128p(key, val) }
|
||||
func Complex128s(key string, val []complex128) zap.Field { return zap.Complex128s(key, val) }
|
||||
|
||||
func Binary(key string, val []byte) zap.Field { return zap.Binary(key, val) }
|
||||
|
||||
func Time(key string, val time.Time) zap.Field { return zap.Time(key, val) }
|
||||
func Timep(key string, val *time.Time) zap.Field { return zap.Timep(key, val) }
|
||||
func Times(key string, val []time.Time) zap.Field { return zap.Times(key, val) }
|
||||
|
||||
func Duration(key string, val time.Duration) zap.Field { return zap.Duration(key, val) }
|
||||
func Durationp(key string, val *time.Duration) zap.Field { return zap.Durationp(key, val) }
|
||||
func Durations(key string, val []time.Duration) zap.Field { return zap.Durations(key, val) }
|
||||
|
||||
func Any(key string, val any) zap.Field { return zap.Any(key, val) }
|
||||
@@ -0,0 +1,237 @@
|
||||
package logx
|
||||
|
||||
import (
|
||||
"base-framework/pkg/routinex"
|
||||
"base-framework/pkg/utils/strutil"
|
||||
"base-framework/pkg/utils/uid"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"base-framework/pkg/config"
|
||||
"base-framework/pkg/types"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
var (
|
||||
Logger *zap.Logger
|
||||
TrackID = "trackId"
|
||||
once sync.Once
|
||||
currentDate string
|
||||
mu sync.Mutex
|
||||
|
||||
infoFile *os.File
|
||||
warnFile *os.File
|
||||
errorFile *os.File
|
||||
|
||||
infoCore zapcore.Core
|
||||
warnCore zapcore.Core
|
||||
errorCore zapcore.Core
|
||||
)
|
||||
|
||||
const logTmFmtWithMS = "2006-01-02 15:04:05.000"
|
||||
|
||||
var levelColor = map[zapcore.Level]string{
|
||||
zapcore.DebugLevel: "\033[36mDEBUG\033[0m",
|
||||
zapcore.InfoLevel: "\033[32mINFO\033[0m",
|
||||
zapcore.WarnLevel: "\033[33mWARN\033[0m",
|
||||
zapcore.ErrorLevel: "\033[31mERROR\033[0m",
|
||||
zapcore.DPanicLevel: "\033[35mDPANIC\033[0m",
|
||||
zapcore.PanicLevel: "\033[35mPANIC\033[0m",
|
||||
zapcore.FatalLevel: "\033[35mFATAL\033[0m",
|
||||
}
|
||||
|
||||
// ----------------- trackCore -----------------
|
||||
// 在写入日志时自动从 routinex 获取 log_id 并加入字段
|
||||
type trackCore struct {
|
||||
zapcore.Core
|
||||
}
|
||||
|
||||
func (c *trackCore) With(fields []zapcore.Field) zapcore.Core {
|
||||
return &trackCore{Core: c.Core.With(fields)}
|
||||
}
|
||||
|
||||
func (c *trackCore) Check(entry zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
|
||||
if c.Enabled(entry.Level) {
|
||||
return ce.AddCore(entry, c)
|
||||
}
|
||||
return ce
|
||||
}
|
||||
|
||||
func (c *trackCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
|
||||
val := routinex.Get(TrackID)
|
||||
if val == nil {
|
||||
val = uid.NextID()
|
||||
routinex.Set(TrackID, val) // 保证同一请求复用同一 trackID
|
||||
}
|
||||
|
||||
fields = append(fields, zap.String(TrackID, strutil.ToString(val)))
|
||||
return c.Core.Write(entry, fields)
|
||||
}
|
||||
|
||||
// InitLogger ----------------- 初始化日志 -----------------
|
||||
func InitLogger() {
|
||||
once.Do(func() {
|
||||
if config.Log == nil {
|
||||
config.Log = defaultLogConfig()
|
||||
}
|
||||
createDirIfNotExist(config.Log.Dir)
|
||||
switchDate(time.Now().Format("2006-01-02"))
|
||||
})
|
||||
}
|
||||
|
||||
func defaultLogConfig() *types.Log {
|
||||
return &types.Log{
|
||||
Dir: "logs",
|
||||
Level: "debug",
|
||||
Format: "json",
|
||||
Daily: true,
|
||||
MaxDays: 30,
|
||||
Caller: true,
|
||||
LevelDirs: true,
|
||||
Console: true,
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------- 初始化核心 -----------------
|
||||
func switchDate(today string) {
|
||||
currentDate = today
|
||||
|
||||
if infoFile != nil {
|
||||
_ = infoFile.Close()
|
||||
}
|
||||
if warnFile != nil {
|
||||
_ = warnFile.Close()
|
||||
}
|
||||
if errorFile != nil {
|
||||
_ = errorFile.Close()
|
||||
}
|
||||
|
||||
infoPath, warnPath, errorPath := config.Log.Dir, config.Log.Dir, config.Log.Dir
|
||||
if config.Log.LevelDirs {
|
||||
infoPath = filepath.Join(config.Log.Dir, "info")
|
||||
warnPath = filepath.Join(config.Log.Dir, "warn")
|
||||
errorPath = filepath.Join(config.Log.Dir, "error")
|
||||
createDirIfNotExist(infoPath)
|
||||
createDirIfNotExist(warnPath)
|
||||
createDirIfNotExist(errorPath)
|
||||
} else {
|
||||
createDirIfNotExist(config.Log.Dir)
|
||||
}
|
||||
|
||||
infoFile = getOrCreateFile(filepath.Join(infoPath, fmt.Sprintf("info-%s.log", today)))
|
||||
warnFile = getOrCreateFile(filepath.Join(warnPath, fmt.Sprintf("warn-%s.log", today)))
|
||||
errorFile = getOrCreateFile(filepath.Join(errorPath, fmt.Sprintf("error-%s.log", today)))
|
||||
|
||||
var fileEncoder zapcore.Encoder
|
||||
if config.Log.Format == "console" {
|
||||
fileEncoder = newConsoleEncoder(false)
|
||||
} else {
|
||||
fileEncoder = newJSONEncoder()
|
||||
}
|
||||
|
||||
infoCore = &trackCore{zapcore.NewCore(fileEncoder, zapcore.AddSync(infoFile), zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
|
||||
return lvl <= zapcore.InfoLevel
|
||||
}))}
|
||||
|
||||
warnCore = &trackCore{zapcore.NewCore(fileEncoder, zapcore.AddSync(warnFile), zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
|
||||
return lvl == zapcore.WarnLevel
|
||||
}))}
|
||||
|
||||
errorCore = &trackCore{zapcore.NewCore(fileEncoder, zapcore.AddSync(errorFile), zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
|
||||
return lvl >= zapcore.ErrorLevel
|
||||
}))}
|
||||
|
||||
cores := []zapcore.Core{infoCore, warnCore, errorCore}
|
||||
|
||||
if config.Log.Console {
|
||||
consoleCore := &trackCore{zapcore.NewCore(newConsoleEncoder(true), zapcore.AddSync(os.Stdout), zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
|
||||
return lvl >= zapcore.DebugLevel
|
||||
}))}
|
||||
cores = append(cores, consoleCore)
|
||||
}
|
||||
|
||||
Logger = zap.New(zapcore.NewTee(cores...))
|
||||
|
||||
if config.Log.Caller {
|
||||
Logger = Logger.WithOptions(zap.AddCaller())
|
||||
} else {
|
||||
Logger = Logger.WithOptions(zap.AddCallerSkip(1))
|
||||
}
|
||||
|
||||
Logger = Logger.WithOptions(zap.Hooks(func(entry zapcore.Entry) error {
|
||||
if config.Log.Daily {
|
||||
checkDateSwitch()
|
||||
}
|
||||
return nil
|
||||
}))
|
||||
}
|
||||
|
||||
func newConsoleEncoder(enableColor bool) zapcore.Encoder {
|
||||
cfg := zapcore.EncoderConfig{
|
||||
TimeKey: "ts",
|
||||
LevelKey: "level",
|
||||
CallerKey: "caller",
|
||||
MessageKey: "msg",
|
||||
LineEnding: zapcore.DefaultLineEnding,
|
||||
EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
||||
enc.AppendString(t.Format(logTmFmtWithMS))
|
||||
},
|
||||
EncodeLevel: func(lvl zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
|
||||
if enableColor {
|
||||
color, ok := levelColor[lvl]
|
||||
if !ok {
|
||||
color = lvl.CapitalString()
|
||||
}
|
||||
enc.AppendString(color)
|
||||
} else {
|
||||
enc.AppendString(lvl.CapitalString())
|
||||
}
|
||||
},
|
||||
EncodeCaller: func(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
|
||||
pid := os.Getpid()
|
||||
enc.AppendString(fmt.Sprintf("[%d] [%d] %s", pid, routinex.CurGID(), caller.TrimmedPath()))
|
||||
},
|
||||
}
|
||||
return zapcore.NewConsoleEncoder(cfg)
|
||||
}
|
||||
|
||||
func newJSONEncoder() zapcore.Encoder {
|
||||
cfg := zap.NewProductionEncoderConfig()
|
||||
cfg.TimeKey = "ts"
|
||||
cfg.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
|
||||
enc.AppendString(t.Format(logTmFmtWithMS))
|
||||
}
|
||||
cfg.EncodeLevel = zapcore.CapitalLevelEncoder
|
||||
cfg.EncodeCaller = zapcore.ShortCallerEncoder
|
||||
return zapcore.NewJSONEncoder(cfg)
|
||||
}
|
||||
|
||||
func checkDateSwitch() {
|
||||
today := time.Now().Format("2006-01-02")
|
||||
if today != currentDate {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if today != currentDate {
|
||||
switchDate(today)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func createDirIfNotExist(dir string) {
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
_ = os.MkdirAll(dir, 0755)
|
||||
}
|
||||
}
|
||||
|
||||
func getOrCreateFile(file string) *os.File {
|
||||
f, err := os.OpenFile(file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return f
|
||||
}
|
||||
Reference in new issue
Block a user