170 lines
4.5 KiB
Go
170 lines
4.5 KiB
Go
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...)
|
||
}
|