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

web*_*ket 5 logging callstack go

当使用包装的 logrus 函数/记录器时,记录器会使用记录器函数调用的文件名和行号作为所有日志行的前缀,例如:

INFO[0000]logging.go:39 myfolder/logging.Info()
Run Code Online (Sandbox Code Playgroud)

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

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...)
}
Run Code Online (Sandbox Code Playgroud)

该函数发出的每一行都将以调用的行号为前缀logging function。这符合预期,但所需的行为是每行都以调用的行的行号作为前缀Info

期望的输出应该是:

INFO[0000]myfile.go:39 myfolder/myfile.myfunction()
Run Code Online (Sandbox Code Playgroud)

有什么办法解决吗?

May*_*tel 6

在 logrus 中不可能做到这一点。我有类似的要求,最终做了以下对我们有用的事情。

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", file, line)
}
Run Code Online (Sandbox Code Playgroud)

看看这个或它的某些变体是否适合您的用例。我已从上面的代码片段中删除了特定于应用程序的代码。