记录未处理的 Golang 恐慌
Logging unhandled Golang panics
我的 Golang 应用程序中有一个 logrus 日志处理程序。日志使用 JSONFormatter 格式化并作为单行提交给 Datadog,Datadog 聚合它们并很好地显示它们。然而,我最近发现了一个未处理的恐慌的案例,这是 not 用 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)])
}
这会产生以下输出。可以看到,前两个日志使用了logrus,unhandled panic却没有。
{"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
是否可以使用 logrus 记录最后几行?
尝试recover
捕捉所有恐慌并记录下来。否则,它会将恐慌消息写入标准错误:
func main() {
defer func() {
if r := recover(); r != nil {
logger.Errorf("Panic: %v", r)
os.Exit(1)
}
}()
// rest of main here
}
我的 Golang 应用程序中有一个 logrus 日志处理程序。日志使用 JSONFormatter 格式化并作为单行提交给 Datadog,Datadog 聚合它们并很好地显示它们。然而,我最近发现了一个未处理的恐慌的案例,这是 not 用 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)])
}
这会产生以下输出。可以看到,前两个日志使用了logrus,unhandled panic却没有。
{"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
是否可以使用 logrus 记录最后几行?
尝试recover
捕捉所有恐慌并记录下来。否则,它会将恐慌消息写入标准错误:
func main() {
defer func() {
if r := recover(); r != nil {
logger.Errorf("Panic: %v", r)
os.Exit(1)
}
}()
// rest of main here
}