记录未处理的 Golang 恐慌

Nat*_*ren 7 logging go datadog

我的 Golang 应用程序中有一个 logrus 日志处理程序。日志使用 JSONFormatter 进行格式化,并作为单行提交给 Datadog,Datadog 会聚合它们并很好地显示它们。然而,我最近发现了一种情况,其中存在未处理的恐慌,并且logrus 记录器没有捕获到这种情况。这导致实际的恐慌和堆栈跟踪分布在多个输出行上,Datadog 单独收集这些输出行。这会花费我们金钱并且使日志很难阅读。

我将解决这个问题,但如果发生任何进一步的未处理的恐慌,我希望能够使用 logrus JSONFormatter 捕获它们。

像这样的东西:

package main

import (
    "os"
    "sync"

    "github.com/sirupsen/logrus"
)

var (
    loggerInstance *logrus.Entry
    once           sync.Once
    logger  = GetLogger()
)

// GetLogger initializes and returns a reference to a CustomLogger object.
func GetLogger() *logrus.Entry {
    once.Do(func() {
        logrus.SetFormatter(&logrus.JSONFormatter{})

        // We'll just pipe everything to stdout. It's json so Datadog will parse the level regardless
        logrus.SetOutput(os.Stdout)
        logrus.SetLevel(logrus.TraceLevel)                            // We'll leave this as trace and just filter out logs when we index them
        loggerInstance = logrus.WithFields(logrus.Fields{"env": "local"}) // Add env tag for easy log parsing
    })
    return loggerInstance
}

func main() {
    logger.Info("Logrus using json logging")
    logger.Warn("We are about to panic")

    var things = []string{
        "hi",
        "yes",
        "thing"}

    print("%s", things[len(things)])
}
Run Code Online (Sandbox Code Playgroud)

这会产生以下输出。正如您所看到的,前两个日志使用 logrus,但未处理的恐慌则没有。

{"env":"local","level":"info","msg":"Logrus using json logging","time":"2020-03-03T15:12:30-08:00"}
{"env":"local","level":"warning","msg":"We are about to panic","time":"2020-03-03T15:12:30-08:00"}
panic: runtime error: index out of range

goroutine 1 [running]:
main.main()
        /Users/nathan.deren/Library/Preferences/GoLand2019.3/scratches/scratch.go:38 +0xbe

Process finished with exit code 2
Run Code Online (Sandbox Code Playgroud)

是否可以使用 logrus 来记录最后几行?

Bur*_*dar 9

尝试recover捕获所有恐慌并记录它们。如果没有它,它会将恐慌消息写入 stderr:

func main() {
   defer func() {
        if r := recover(); r != nil {
            logger.Errorf("Panic: %v", r)
            os.Exit(1)
        }
    }()
    // rest of main here
}
Run Code Online (Sandbox Code Playgroud)

  • 这有效;谢谢你!对于其他阅读的人,我稍微调整了一下以包含堆栈跟踪: `logger.Errorf("Panic: %v,\n%s", r, debug.Stack())` (4认同)
  • 如果另一个 go 例程惊慌失措,则这不起作用,例如 https://go.dev/play/p/TrS_KjEaiV6 (4认同)