| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- package core
- import (
- "app/commons/config"
- "fmt"
- rotateLogs "github.com/lestrrat-go/file-rotatelogs"
- "github.com/spf13/viper"
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
- "io"
- "os"
- "strings"
- "time"
- )
- const (
- DefaultLog LogTagName = "app"
- JobLogName LogTagName = "job"
- )
- var loggerConfer *config.Zap
- func loggerConf() *config.Zap {
- if loggerConfer == nil {
- loggerInit()
- }
- return loggerConfer
- }
- var (
- errorLoggerMap = make(map[LogTagName]*zap.Logger)
- Log *zap.SugaredLogger
- JobLog *zap.SugaredLogger
- )
- func init() {
- tags := []LogTagName{DefaultLog, JobLogName}
- for _, lg := range tags {
- errorLoggerMap[lg] = newLogger(lg)
- }
- Log = errorLoggerMap[DefaultLog].Sugar()
- JobLog = errorLoggerMap[JobLogName].Sugar()
- }
- func loggerInit() {
- if config.EnvConf().Zap != nil {
- loggerConfer = config.EnvConf().Zap
- return
- }
- v := viper.New()
- v.SetDefault("prefix", "AppServer-")
- v.SetDefault("level", "LowercaseColorLevelEncoder")
- v.SetDefault("format", "_json")
- v.SetDefault("director", "logs")
- v.SetDefault("encode_level", "LowercaseLevelEncoder")
- v.SetDefault("stacktrace_key", "error")
- v.SetDefault("max_age", 3)
- v.SetDefault("rotation_size", 100)
- v.SetDefault("rotation_count", 3)
- v.SetDefault("show_line", true)
- v.SetDefault("log_in_console", true)
- v.SetDefault("log_output_file", true)
- if err := v.Unmarshal(&loggerConfer); err != nil {
- panic(fmt.Errorf("Fatal error config file: %s \n", err))
- }
- }
- type LogTagName string
- type logConfTags struct {
- Tag LogTagName `json:"tag" yaml:"tag"`
- FileName string `json:"filename" yaml:"filename"`
- ErrFileName string `json:"errFileName" yaml:"errFileName"`
- }
- func getWriter(filename string) io.Writer {
- // 生成 rotate_logs 的Logger 实际生成的文件名 demo.log.YY mm dd HH
- hook, err := rotateLogs.New(
- strings.Replace(filename, ".log", "", -1)+".%Y%m%d%H.log",
- rotateLogs.WithLinkName(filename),
- // 根据文件大小切割日志
- rotateLogs.WithRotationSize(1024*1024*loggerConf().LogSignSize()), // 每个日志文件大小设置:100M
- rotateLogs.WithRotationTime(time.Hour*24), // 日志轮询周期 默认1分钟:60秒
- rotateLogs.WithRotationCount(loggerConf().LogSaveCount()), // 日志保留份数
- // 根据时间分割日志
- // rotateLogs.WithMaxAge(time.Hour*24*2), // 保存2天日志
- )
- if err != nil {
- panic(err)
- }
- return hook
- }
- // 设置日志格式 非json可进行堆栈跟踪
- func getEncoder() zapcore.Encoder {
- if loggerConf().Format == "json" || loggerConf().Format == "" {
- return zapcore.NewJSONEncoder(getEncoderConfig())
- }
- return zapcore.NewConsoleEncoder(getEncoderConfig())
- }
- func getEncoderConfig() zapcore.EncoderConfig {
- return zapcore.EncoderConfig{
- MessageKey: "message",
- LevelKey: "level",
- EncodeLevel: loggerConf().ZapEncodeLevel(),
- TimeKey: "time",
- NameKey: "logger",
- CallerKey: "caller",
- StacktraceKey: loggerConf().StacktraceKey, // "error"
- LineEnding: zapcore.DefaultLineEnding,
- EncodeTime: customTimeEncoder,
- EncodeDuration: zapcore.SecondsDurationEncoder,
- EncodeCaller: zapcore.ShortCallerEncoder,
- }
- }
- func customTimeEncoder(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {
- encoder.AppendString(t.Format("2006/01/02-15:04:05.000"))
- }
- func NewLogger(tag LogTagName, args ...interface{}) *zap.Logger {
- if errorLoggerMap[tag] != nil {
- return errorLoggerMap[tag]
- }
- return newLogger(tag, args...)
- }
- func newLogger(tag LogTagName, args ...interface{}) *zap.Logger {
- savePath := fmt.Sprintf("./%s/", loggerConf().Director)
- if len(args) > 0 {
- savePath = fmt.Sprintf("./%s/", args[0])
- }
- tagConf := logConfTags{Tag: tag, FileName: fmt.Sprintf("%s.log", tag), ErrFileName: fmt.Sprintf("%s_err.log", tag)}
- encoder := getEncoder()
- infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
- return lvl >= loggerConf().TransportLevel()
- })
- errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
- return lvl >= zapcore.ErrorLevel
- })
- // 获取 info、error日志文件的io.Writer 抽象 getWriter() 在下方实现
- infoWriter := getWriter(savePath + tagConf.FileName)
- errorWriter := getWriter(savePath + tagConf.ErrFileName)
- cores := make([]zapcore.Core, 0)
- if loggerConf().LogOutputFile {
- cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel))
- cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(errorWriter), errorLevel))
- }
- if loggerConf().LogInConsole {
- cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), infoLevel))
- }
- // 最后创建具体的Logger
- core := zapcore.NewTee(cores...)
- // 开启开发模式,堆栈跟踪
- caller := zap.AddCaller()
- development := zap.Development()
- filed := zap.Fields(zap.String("Tag", string(tagConf.Tag)))
- stackTrace := zap.AddStacktrace(zap.ErrorLevel) // 当错误等级error时 触发堆栈跟踪
- log := zap.New(core, caller, stackTrace, development, filed)
- if loggerConf().ShowLine {
- log = log.WithOptions(zap.AddCaller())
- }
- errorLoggerMap[tagConf.Tag] = log
- return errorLoggerMap[tagConf.Tag]
- }
|