美文网首页
logrus中输出文件名、行号及函数名

logrus中输出文件名、行号及函数名

作者: 跑马溜溜的球 | 来源:发表于2021-05-11 15:23 被阅读0次

    日志中输出文件名,行号及函数名是个比较有用的功能,那么在logrus中如何作到呢?

    1. 在自带Formatter中输出

    logrus有两个自带的Formatter,分别是:TextFormatter和JSONFormatter。要在这两个Formatter中输出文件名,行号和函数名,只需要设置

    logrus.SetReportCaller(true)
    

    1.1 在TextFormatter中输出

    func Demo(){
        logrus.Info("i'm demo")
    
    }
    
    func main(){
        logrus.SetReportCaller(true)
        logrus.SetFormatter(&logrus.TextFormatter{
            //以下设置只是为了使输出更美观
            DisableColors:true,
            TimestampFormat:"2006-01-02 15:03:04",
        })
    
        Demo()
    }
    
    //输出
    time="2021-05-11 14:02:45" level=info msg="i'm demo" func=main.Demo file="/home/ballqiu/go/log/demo.go:30"
    

    说明:

    • func为函数名
    • file格式为文件名:行号
    • JsonFormatter中的使用类似

    1.2 定制文件名和函数名的输出

    上例中的文件名因为包含了路径信息,因此特别长。如果我们只要想文件名,不想输出路径,以便使得日志更简短,怎么做呢?可以设置Formatter中的CallerPrettyfier,它的函数原型是:

    func(*runtime.Frame) (function string, file string)
    

    返回值中的function是函数名, file是文件名。

    例:

    func Demo(){
        logrus.Info("i'm demo")
    
    }
    
    func main(){
        logrus.SetReportCaller(true)
    
        logrus.SetFormatter(&logrus.JSONFormatter{
            TimestampFormat:"2006-01-02 15:03:04",
    
            CallerPrettyfier: func(frame *runtime.Frame) (function string, file string) {
                //处理文件名
                fileName := path.Base(frame.File)
                return frame.Function, fileName
            },
        })
    
        Demo()
    }
    
    //输出
    {"file":"demo.go","func":"main.Demo","level":"info","msg":"i'm demo","time":"2021-05-11 14:02:57"}
    

    说明:

    • 参数frame中包含了文件名,函数名,行号,等一系列信息。
    • path.Base(frame.File)去掉了文件名中的路径部分。
    • TextFormatter中的使用与JSONFormatter完全一致

    2.在自定义Formatter中输出

    如果你还不了解如何自定义Formatter,可以参看logrus自定义日志输出格式

    方法:

    1. 设置logrus.SetReportCaller(true)
    2. 通过entry.Caller拿到相应的信息进行输出

    例:

    type MyFormatter struct {}
    func (m *MyFormatter) Format(entry *logrus.Entry) ([]byte, error){
        var b *bytes.Buffer
        if entry.Buffer != nil {
            b = entry.Buffer
        } else {
            b = &bytes.Buffer{}
        }
        
        timestamp := entry.Time.Format("2006-01-02 15:04:05")
        var newLog string
        
        //HasCaller()为true才会有调用信息
        if entry.HasCaller() {
            fName := filepath.Base(entry.Caller.File)
            newLog = fmt.Sprintf("[%s] [%s] [%s:%d %s] %s\n",
                timestamp, entry.Level, fName, entry.Caller.Line, entry.Caller.Function, entry.Message)
        } else{
            newLog = fmt.Sprintf("[%s] [%s] %s\n", timestamp, entry.Level, entry.Message)
        }
    
        b.WriteString(newLog)
        return b.Bytes(), nil
    }
    
    func Demo(){
        logrus.Info("i'm demo")
    }
    
    func main(){
        logrus.SetReportCaller(true)
    
        logrus.SetFormatter(&MyFormatter{})
    
        Demo()
    }
    
    //输出
    [2021-05-11 15:08:46] [info] [demo.go:38 main.Demo] i'm demo
    

    说明:

    • entry.Caller.File:文件名
    • entry.Caller.Line: 行号
    • entry.Caller.Function:函数名
    • entry.Caller中还有调用栈相关信息,有需要可以在日志中加入
    • entry.HasCaller() 的判断是必须的,否则如果外部没有设置logrus.SetReportCaller(true),entry.Caller.*的调用会引发Panic

    相关文章

      网友评论

          本文标题:logrus中输出文件名、行号及函数名

          本文链接:https://www.haomeiwen.com/subject/mopgdltx.html