推理是错误的。 Logrus 实际上并不知道如何处理该错误。
更新 Logrus 团队官员表示,这不是一个受支持的功能,https://github.com/sirupsen/logrus/issues/895#issuecomment-457656556。
Java 风格的响应
为了以这种方式普遍使用错误处理程序,我编写了一个新版本的 Entry,它来自 Logrus。如示例所示,使用您想要的任何常见字段创建一个新条目(下面的示例是在处理程序中设置的记录器,用于跟踪调用者 ID。在您处理条目时通过您的层传递 PgkError。当您需要记录特定错误,例如调用变量遇到错误,从 PkgError.WithError(...) 开始,然后添加您的详细信息。
这是一个起点。如果您想普遍使用它,请在 PkgErrorEntry 上实现所有 Entity 接口。继续委托给内部条目,但返回一个新的 PkgErrorEntry。这样的更改会使值 true 下降以替代 Entry。
package main
import (
"fmt"
"github.com/sirupsen/logrus"
"strings"
unwrappedErrors "errors"
"github.com/pkg/errors"
)
// PkgErrorEntry enables stack frame extraction directly into the log fields.
type PkgErrorEntry struct {
*logrus.Entry
// Depth defines how much of the stacktrace you want.
Depth int
}
// This is dirty pkg/errors.
type stackTracer interface {
StackTrace() errors.StackTrace
}
func (e *PkgErrorEntry) WithError(err error) *logrus.Entry {
out := e.Entry
common := func(pError stackTracer) {
st := pError.StackTrace()
depth := 3
if e.Depth != 0 {
depth = e.Depth
}
valued := fmt.Sprintf("%+v", st[0:depth])
valued = strings.Replace(valued, "\t", "", -1)
stack := strings.Split(valued, "\n")
out = out.WithField("stack", stack[2:])
}
if err2, ok := err.(stackTracer); ok {
common(err2)
}
if err2, ok := errors.Cause(err).(stackTracer); ok {
common(err2)
}
return out.WithError(err)
}
func someWhereElse() error {
return unwrappedErrors.New("Ouch")
}
func level1() error {
return level2()
}
func level2() error {
return errors.WithStack(unwrappedErrors.New("All wrapped up"))
}
func main() {
baseLog := logrus.New()
baseLog.SetFormatter(&logrus.JSONFormatter{})
errorHandling := PkgErrorEntry{Entry: baseLog.WithField("callerid", "1000")}
errorHandling.Info("Hello")
err := errors.New("Hi")
errorHandling.WithError(err).Error("That should have a stack.")
err = someWhereElse()
errorHandling.WithError(err).Info("Less painful error")
err = level1()
errorHandling.WithError(err).Warn("Should have multiple layers of stack")
}
类似 Gopher 的方式
详情请参阅https://www.reddit.com/r/golang/comments/ajby88/how_to_get_stack_traces_in_logrus/。
Ben Johnson wrote 关于让错误成为您域的一部分。一个缩写版本是您应该将跟踪器属性放在自定义错误上。当您直接控制的代码发生错误或发生来自 3rd 方库的错误时,立即处理错误的代码应将唯一值放入自定义错误中。该值将作为自定义错误的Error() string 实现的一部分打印出来。
当开发人员获得日志文件时,他们将能够 grep 代码库以获取该唯一值。 Ben 说:“最后,我们需要能够向我们的操作员提供所有这些信息以及逻辑堆栈跟踪,以便他们可以调试问题。Go 已经提供了一个简单的方法 error.Error() 来打印错误信息,以便我们可以利用那个。”
这是本的例子
// attachRole inserts a role record for a user in the database
func (s *UserService) attachRole(ctx context.Context, id int, role string) error {
const op = "attachRole"
if _, err := s.db.Exec(`INSERT roles...`); err != nil {
return &myapp.Error{Op: op, Err: err}
}
return nil
}
我对 grep-able 代码的一个问题是值很容易偏离原始上下文。例如,假设函数的名称从 attachRole 更改为其他名称,并且函数更长。操作值可能与函数名称不同。无论如何,这似乎满足了追踪问题的一般需求,同时将错误视为一等公民。
Go2 可能会在这方面引发更多的 Java 风格响应。敬请关注。
https://go.googlesource.com/proposal/+/refs/changes/97/159497/3/design/XXXXX-error-values.md