我使用github.com/sirupsen/logrus和github.com/pkg/错误。当我提交一个由pkg/错误包装或创建的错误时,我在注销中看到的只是错误消息。我想看看堆栈追踪。
从这个问题,https://github.com/sirupsen/logrus/issues/506,我推断logrus有一些处理pkg/错误的本地方法。
我该怎么做?
发布于 2019-01-25 16:31:44
这个推论是错误的。Logrus实际上不知道如何处理错误。Update Logrus官员说,这不是一个受支持的特性,https://github.com/sirupsen/logrus/issues/895#issuecomment-457656556。
-ish响应为了以这种方式通用地处理错误处理程序,我编写了一个新版本的条目,它来自Logrus。如示例所示,创建一个新条目,其中包含您想要的任何公共字段(下面是一个在处理程序中设置的记录器,用于跟踪调用者id。在处理条目时,通过您的层传递PgkError。当您需要记录特定的错误时,比如遇到错误的调用变量,请从PkgError.WithError(.)开始那就加上你的细节。
这是一个起点。如果您想要一般地使用它,请在PkgErrorEntry上实现所有的实体接口。继续委托给内部条目,但返回一个新的PkgErrorEntry。这样的改变将使输入替换值真正下降。
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")
}A Gopher-ish way查看洛格鲁斯/以获得更多细节。
Ben Johnson 写关于将错误作为域的一部分。缩写的版本是,您应该将跟踪器属性放在自定义错误上。当代码直接在您控制的错误下,或者当发生来自第三方库的错误时,立即处理错误的代码应该将一个唯一的值放入自定义错误中。此值将作为自定义错误的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可实现代码中遇到的一个问题是,该值很容易偏离原始上下文。例如,假设函数的名称从attachRole更改为其他函数,并且函数的长度更长。op值可能与函数名称不同。无论如何,这似乎满足了追踪问题的一般需要,同时将错误处理为头等公民。
Go2可能会在这一点上抛出一条曲线到更多的Java响应中。敬请关注。https://go.googlesource.com/proposal/+/refs/changes/97/159497/3/design/XXXXX-error-values.md
发布于 2019-01-27 10:47:39
关于你的Logrus问题的评论是不正确的(顺便说一句,似乎是来自与Logrus没有关系的人,他没有对Logrus做出任何贡献,所以实际上不是来自“Logrus团队”)。
在pkg/errors错误( 如文件所示 )中很容易提取堆栈跟踪
type stackTracer interface {
StackTrace() errors.StackTrace
}这意味着用logrus记录堆栈跟踪的最简单方法是:
if stackErr, ok := err.(stackTracer); ok {
log.WithField("stacktrace", fmt.Sprintf("%+v", stackErr.StackTrace()))
}从今天开始,当使用pkg/errors时,如果您使用JSON日志记录,现在就更容易了:
if stackErr, ok := err.(stackTracer); ok {
log.WithField("stacktrace", stackErr.StackTrace())
}这将产生一种类似于"%+v“的日志格式,但是没有换行符或制表符,每个字符串有一个日志条目,这样就可以轻松地封送到JSON数组中。
当然,这两个选项都迫使您使用pkg/errors定义的格式,而这种格式并不总是理想的。因此,您可以迭代堆栈跟踪,并生成自己的格式,可能会生成一种很容易被JSON封送的格式。
if err, ok := err.(stackTracer); ok {
for _, f := range err.StackTrace() {
fmt.Printf("%+s:%d\n", f, f) // Or your own formatting
}
}与其打印每一帧,你可以强迫它成任何你喜欢的格式。
https://stackoverflow.com/questions/54369295
复制相似问题