205 lines
5.2 KiB
Go
205 lines
5.2 KiB
Go
package logger
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"runtime"
|
||
"strings"
|
||
"time"
|
||
|
||
"go.uber.org/zap"
|
||
"go.uber.org/zap/zapcore"
|
||
"gopkg.in/natefinch/lumberjack.v2"
|
||
)
|
||
|
||
var (
|
||
zlog *zap.SugaredLogger
|
||
)
|
||
|
||
type LoggerConfig struct {
|
||
Filename string `mapstructure:"filename" json:"filename" yaml:"filename"`
|
||
Level string `mapstructure:"level" json:"level" yaml:"level"`
|
||
Format string `mapstructure:"format" json:"format" yaml:"format"`
|
||
Prefix string `mapstructure:"prefix" json:"prefix" yaml:"prefix"`
|
||
Director string `mapstructure:"director" json:"director" yaml:"director"`
|
||
ShowLine bool `mapstructure:"show-line" json:"show-line" yaml:"show-line"`
|
||
EncodeLevel string `mapstructure:"encode-level" json:"encode-level" yaml:"encode-level"`
|
||
StacktraceKey string `mapstructure:"stacktrace-key" json:"stacktrace-key" yaml:"stacktrace-key"`
|
||
LogInConsole bool `mapstructure:"log-in-console" json:"log-in-console" yaml:"log-in-console"`
|
||
}
|
||
|
||
func Init(conf *LoggerConfig) {
|
||
if conf.Filename == "/dev/stdout" {
|
||
ecf := zap.NewProductionEncoderConfig()
|
||
ecf.FunctionKey = "func"
|
||
ecf.EncodeTime = zapcore.ISO8601TimeEncoder
|
||
ecf.ConsoleSeparator = " "
|
||
ecf.EncodeCaller = zapcore.ShortCallerEncoder
|
||
|
||
core := zapcore.NewCore(
|
||
zapcore.NewConsoleEncoder(ecf),
|
||
zapcore.AddSync(os.Stdout),
|
||
zap.DebugLevel,
|
||
)
|
||
zl := zap.New(core, zap.AddCallerSkip(1), zap.AddCaller())
|
||
zlog = zl.Sugar()
|
||
return
|
||
}
|
||
|
||
_, err := os.Stat(conf.Filename)
|
||
if err != nil {
|
||
if os.IsNotExist(err) {
|
||
err = os.MkdirAll(conf.Filename, os.ModePerm)
|
||
if err != nil {
|
||
panic(err)
|
||
}
|
||
} else {
|
||
fmt.Println("logger init error:", err)
|
||
}
|
||
}
|
||
if strings.LastIndex(conf.Filename, "/") != 0 {
|
||
conf.Filename = conf.Filename + "/"
|
||
}
|
||
|
||
encoder := zapcore.NewConsoleEncoder(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"))
|
||
},
|
||
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() 在下方实现
|
||
|
||
now := time.Now()
|
||
fileTime := now.Format("20060102") + "-" + now.Format("150405")
|
||
fileFormat := "%s%s-%s.log"
|
||
infoWriter := getWriter(fmt.Sprintf(fileFormat, conf.Filename, "info", fileTime))
|
||
errorWriter := getWriter(fmt.Sprintf(fileFormat, conf.Filename, "error", fileTime))
|
||
|
||
// 最后创建具体的Logger
|
||
core := zapcore.NewTee(
|
||
zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), infoLevel), //打印到控制台
|
||
zapcore.NewCore(encoder, infoWriter, infoLevel),
|
||
zapcore.NewCore(encoder, errorWriter, errorLevel),
|
||
)
|
||
|
||
zl := zap.New(core, zap.AddCallerSkip(1), zap.AddCaller())
|
||
zlog = zl.Sugar()
|
||
}
|
||
|
||
func GetDefault() *zap.SugaredLogger {
|
||
return zlog
|
||
}
|
||
|
||
func InitDefault() {
|
||
Init(&LoggerConfig{
|
||
Filename: "/dev/stdout",
|
||
})
|
||
}
|
||
|
||
func Sync() {
|
||
_ = zlog.Sync()
|
||
}
|
||
|
||
func getWriter(filename string) zapcore.WriteSyncer {
|
||
lumberJackLogger := &lumberjack.Logger{
|
||
Filename: filename, // 文件位置
|
||
MaxSize: 100, // 进行切割之前,日志文件的最大大小(MB为单位)
|
||
MaxAge: 10, // 保留旧文件的最大天数
|
||
MaxBackups: 3, // 保留旧文件的最大个数
|
||
Compress: false, // 是否压缩/归档旧文件
|
||
}
|
||
// AddSync 将 io.Writer 转换为 WriteSyncer。
|
||
// 它试图变得智能:如果 io.Writer 的具体类型实现了 WriteSyncer,我们将使用现有的 Sync 方法。
|
||
// 如果没有,我们将添加一个无操作同步。
|
||
|
||
return zapcore.AddSync(lumberJackLogger)
|
||
}
|
||
|
||
func Debug(args ...interface{}) {
|
||
zlog.Debug(args...)
|
||
}
|
||
|
||
func Debugf(template string, args ...interface{}) {
|
||
zlog.Debugf(template, args...)
|
||
}
|
||
|
||
func Info(args ...interface{}) {
|
||
zlog.Info(args...)
|
||
}
|
||
|
||
func Infof(template string, args ...interface{}) {
|
||
zlog.Infof(template, args...)
|
||
}
|
||
|
||
func Warn(args ...interface{}) {
|
||
zlog.Warn(args...)
|
||
}
|
||
|
||
func Warnf(template string, args ...interface{}) {
|
||
zlog.Warnf(template, args...)
|
||
}
|
||
|
||
func Error(args ...interface{}) {
|
||
zlog.Error(args...)
|
||
}
|
||
|
||
func Errorf(template string, args ...interface{}) {
|
||
zlog.Errorf(template, args...)
|
||
}
|
||
|
||
func DPanic(args ...interface{}) {
|
||
zlog.DPanic(args...)
|
||
}
|
||
|
||
func DPanicf(template string, args ...interface{}) {
|
||
zlog.DPanicf(template, args...)
|
||
}
|
||
|
||
func Panic(args ...interface{}) {
|
||
zlog.Panic(args...)
|
||
}
|
||
|
||
func Panicf(template string, args ...interface{}) {
|
||
zlog.Panicf(template, args...)
|
||
}
|
||
|
||
func Fatal(args ...interface{}) {
|
||
zlog.Fatal(args...)
|
||
}
|
||
|
||
func Fatalf(template string, args ...interface{}) {
|
||
zlog.Fatalf(template, args...)
|
||
}
|
||
|
||
func SafeGoroutine(fn func()) {
|
||
go func() {
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
buf := make([]byte, 1<<16) // 64KB
|
||
stackSize := runtime.Stack(buf, false)
|
||
msg := fmt.Sprintf("panic: %v\n%s\n", r, buf[:stackSize])
|
||
Errorf(msg)
|
||
}
|
||
}()
|
||
fn()
|
||
}()
|
||
}
|