zap + log classification and file splitting + log cutting by time integration demo

Realization function

       info debug level log output to / path/log/demo.log
Log output to / path / log / demo error.log
                    

Third party package github address dependent

    https://github.com/uber-go/zap

    https://github.com/lestrrat-go/file-rotatelogs

                              https://github.com/natefinch/lumberjack It also provides similar functions, but it is based on the file size. It feels that unless other tools are used, the experience may not be so friendly when looking for the log at a certain time point.

demo code

package demo

import (
    rotatelogs "github.com/lestrrat-go/file-rotatelogs"
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
)

var Logger *zap.Logger

func init() {
    // It's easy to understand the specific meaning of setting some basic log formats, and it's not difficult to understand the zap source code directly
    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)
        },  
    })
    
    // Two interface s for judging log level
    infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
        return lvl < zapcore.WarnLevel
    })
    
    warnLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
        return lvl >= zapcore.WarnLevel
    })
    
    // Get io.Writer Abstract getWriter() of info and warn log files and implement it below
    infoWriter := getWriter("/path/log/demo.log")
    warnWriter := getWriter("/path/log/demo_error.log")
    
    // Finally, create a specific Logger
    core := zapcore.NewTee(
        zapcore.NewCore(*encoder, zapcore.AddSync(infoHook), infoLevel),
        zapcore.NewCore(*encoder, zapcore.AddSync(warnHook), warnLevel),
    )
    
    Logger = zap.New(core)
}

func getWriter(filename string) io.Writer {
    // The actual file name generated by the Logger generating rotatelogs is demo.log.YYmmddHH
    // demo.log is a link to the latest log
    // Save the logs within 7 days, and split the logs every 1 hour (whole point)
    hook, err := rotatelogs.New(
        filename+".%Y%m%d%H", // No go style anti human format
        rotatelogs.WithLinkName(filename),
        rotatelogs.WithMaxAge(time.Hour*24*7),
        rotatelogs.WithRotationTime(time.Hour),
    )   

    if err != nil {
        panic(err)
    }   
    return hook
}

The parameter received by zap.NewCore is io.Writer rather than struct of its own package. It's good that developers can pass in io.Writer as needed.

Tags: Java github

Posted on Tue, 05 Nov 2019 07:28:53 -0800 by shainh