是否可以包装logrus.Logger函数而不会丢失行号前缀?

问题描述

使用包装的logrus函数/记录器时,记录器会在所有日志行之前添加记录函数调用文件名和行号,例如:

INFO[0000]logging.go:39 myfolder/logging.Info()

例如,如果我像这样包装日志函数: 包记录

import (
    "fmt"
    "github.com/sirupsen/logrus"
    "os"
    "path"
    "runtime"
)

var (
    log *logrus.Logger
)

func init() {

    log = logrus.New()
    log.SetReportCaller(true)
    log.Formatter = &logrus.textformatter{
        CallerPrettyfier: func(f *runtime.Frame) (string,string) {
            filename := path.Base(f.File)
            return fmt.Sprintf("%s()",f.Function),fmt.Sprintf("%s:%d",filename,f.Line)
        },}
}

func Info(args ...interface{}) {
        log.Info(args...)
}

函数发出的每一行都将以logging function调用的行号作为前缀。正如预期的那样,但是所需的行为是为每行加上调用Info的行的行号。

所需的输出应为:

INFO[0000]myfile.go:39 myfolder/myfile.myfunction()

有什么办法解决吗?

解决方法

不可能在对数中进行。我有类似的要求,最后做了对我们有用的以下事情。

package mylog

import (
    "fmt"
    "github.com/Sirupsen/logrus"
    "runtime"
    "strings"
)

var logger = logrus.New()

func SetLogFormatter(formatter logrus.Formatter) {
    logger.Formatter = formatter
}

// Info logs a message at level Info on the standard logger.
func Info(args ...interface{}) {
    if logger.Level >= logrus.InfoLevel {
        entry := logger.WithFields(logrus.Fields{})
        entry.Data["file"] = fileInfo(2)
        entry.Info(args...)
    }
}

func fileInfo(skip int) string {
    _,file,line,ok := runtime.Caller(skip)
    if !ok {
        file = "<???>"
        line = 1
    } else {
        slash := strings.LastIndex(file,"/")
        if slash >= 0 {
            file = file[slash+1:]
        }
    }
    return fmt.Sprintf("%s:%d",line)
}

查看此版本或此版本的某些变型是否适用于您的用例。我已从上面的代码片段中删除了特定于应用程序的代码。

,

希望我没有误会,所以您需要调用记录器的“实际”路径和行号。下面的代码(以 json格式为例)应该可以为您提供所需的信息。如果要添加更多信息,例如函数名等,只需修改caller()方法。

logrus.SetReportCaller(true)
// ...

logrus.SetFormatter(&logrus.JSONFormatter{
    CallerPrettyfier:  caller(),FieldMap: logrus.FieldMap{
        logrus.FieldKeyFile: "caller",},})
// caller returns string presentation of log caller which is formatted as
// `/path/to/file.go:line_number`. e.g. `/internal/app/api.go:25`
func caller() func(*runtime.Frame) (function string,file string) {
    return func(f *runtime.Frame) (function string,file string) {
        p,_ := os.Getwd()

        return "",fmt.Sprintf("%s:%d",strings.TrimPrefix(f.File,p),f.Line)
    }
}
{
  "caller": "/internal/controller/create.go:21","level": "info","msg": "i am a dummy log","time": "2020-08-30T19:17:48+01:00"
}