170 lines
4.5 KiB
Go
Raw Normal View History

2023-06-04 22:54:54 +08:00
package utils
import (
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"io"
"os"
"strings"
"sync"
"time"
)
var zapOnce sync.Once
var innerSugarLogger *zap.SugaredLogger
func InitNomadGlobalLog() {
zapOnce.Do(func() {
pwdDir, _ := os.Getwd()
infoLogFilePath := pwdDir + "/alloc/logs/demo-log-main-task.stdout.0"
errLogFilePath := pwdDir + "/alloc/logs/demo-log-main-task.stderr.0"
serverName := "demo-log"
if v := os.Getenv("APP_NAME"); v != "" {
serverName = v
}
branchName := "main"
if v := os.Getenv("CI_COMMIT_BRANCH"); v != "" {
branchName = v
} else {
branchName = "main"
}
infoLogFilePath = strings.ReplaceAll(infoLogFilePath, "/app", "")
errLogFilePath = strings.ReplaceAll(errLogFilePath, "/app", "")
// 替换 serverName
infoLogFilePath = strings.ReplaceAll(infoLogFilePath, "demo-log", serverName)
errLogFilePath = strings.ReplaceAll(errLogFilePath, "demo-log", serverName)
// 替换 branchName
infoLogFilePath = strings.ReplaceAll(infoLogFilePath, "main", branchName)
errLogFilePath = strings.ReplaceAll(errLogFilePath, "main", branchName)
// 设置一些基本日志格式 具体含义还比较好理解直接看zap源码也不难懂
encoder := zapcore.NewJSONEncoder(zapcore.EncoderConfig{
MessageKey: "msg",
LevelKey: "level",
EncodeLevel: zapcore.CapitalLevelEncoder,
TimeKey: "ts",
EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("2006-01-02 15:04:05"))
},
EncodeName: zapcore.FullNameEncoder,
CallerKey: "file",
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendInt64(int64(d) / 1000000)
},
})
// 实现两个判断日志等级的interface
infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl == zapcore.InfoLevel
})
errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl == zapcore.ErrorLevel
})
// 获取 info、error日志文件的io.Writer 抽象 getWriter() 在下方实现
infoWriter := getWriter(infoLogFilePath)
errorWriter := getWriter(errLogFilePath)
// 最后创建具体的Logger
core := zapcore.NewTee(
zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel),
zapcore.NewCore(encoder, zapcore.AddSync(errorWriter), errorLevel),
)
logger := zap.New(core, zap.AddCaller()) // 需要传入 zap.AddCaller() 才会显示打日志点的文件名和行数, 有点小坑
innerSugarLogger = logger.Sugar().With("appName", serverName)
})
}
type logger struct {
log *zap.SugaredLogger
traceId string
}
func NewLog(traceId string) *logger {
if innerSugarLogger == nil {
InitNomadGlobalLog()
}
return &logger{
log: innerSugarLogger.With(zap.String("trace_id", traceId)),
traceId: traceId,
}
}
func getWriter(filename string) io.Writer {
// 生成rotatelogs的Logger 实际生成的文件名 demo.log.YYmmddHH
// demo.log是指向最新日志的链接
// 保存7天内的日志每1小时(整点)分割一次日志
hook, err := rotatelogs.New(
strings.Replace(filename, ".0", "", -1)+".%Y%m%d%H", // 没有使用go风格反人类的format格式
rotatelogs.WithLinkName(filename),
rotatelogs.WithMaxAge(time.Hour*24),
rotatelogs.WithRotationTime(time.Hour),
)
if err != nil {
panic(err)
}
return hook
}
func (l logger) Debug(args ...interface{}) {
l.log.Debug(args...)
}
func (l logger) Debugf(template string, args ...interface{}) {
l.log.Debugf(template, args...)
}
func (l logger) Info(args ...interface{}) {
l.log.Info(args...)
}
func (l logger) Infof(template string, args ...interface{}) {
l.log.Infof(template, args...)
}
func (l logger) Warn(args ...interface{}) {
l.log.Warn(args...)
}
func (l logger) Warnf(template string, args ...interface{}) {
l.log.Warnf(template, args...)
}
func (l logger) Error(args ...interface{}) {
l.log.Error(args...)
}
func (l logger) Errorf(template string, args ...interface{}) {
l.log.Errorf(template, args...)
}
func (l logger) DPanic(args ...interface{}) {
l.log.DPanic(args...)
}
func (l logger) DPanicf(template string, args ...interface{}) {
l.log.DPanicf(template, args...)
}
func (l logger) Panic(args ...interface{}) {
l.log.Panic(args...)
}
func (l logger) Panicf(template string, args ...interface{}) {
l.log.Panicf(template, args...)
}
func (l logger) Fatal(args ...interface{}) {
l.log.Fatal(args...)
}
func (l logger) Fatalf(template string, args ...interface{}) {
l.log.Fatalf(template, args...)
}