首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使logrus打印pkg/错误的堆栈

如何使logrus打印pkg/错误的堆栈
EN

Stack Overflow用户
提问于 2019-01-25 16:31:44
回答 2查看 8.6K关注 0票数 2

我使用github.com/sirupsen/logrus和github.com/pkg/错误。当我提交一个由pkg/错误包装或创建的错误时,我在注销中看到的只是错误消息。我想看看堆栈追踪。

从这个问题,https://github.com/sirupsen/logrus/issues/506,我推断logrus有一些处理pkg/错误的本地方法。

我该怎么做?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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。这样的改变将使输入替换值真正下降。

代码语言:javascript
复制
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()来打印错误信息,这样我们就可以利用它了。”

以下是本的例子

代码语言:javascript
复制
// 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

票数 2
EN

Stack Overflow用户

发布于 2019-01-27 10:47:39

关于你的Logrus问题的评论是不正确的(顺便说一句,似乎是来自与Logrus没有关系的人,他没有对Logrus做出任何贡献,所以实际上不是来自“Logrus团队”)。

pkg/errors错误( 如文件所示 )中很容易提取堆栈跟踪

代码语言:javascript
复制
type stackTracer interface {
        StackTrace() errors.StackTrace
}

这意味着用logrus记录堆栈跟踪的最简单方法是:

代码语言:javascript
复制
if stackErr, ok := err.(stackTracer); ok {
    log.WithField("stacktrace", fmt.Sprintf("%+v", stackErr.StackTrace()))
}

从今天开始,当使用pkg/errors时,如果您使用JSON日志记录,现在就更容易了:

代码语言:javascript
复制
if stackErr, ok := err.(stackTracer); ok {
    log.WithField("stacktrace", stackErr.StackTrace())
}

这将产生一种类似于"%+v“的日志格式,但是没有换行符或制表符,每个字符串有一个日志条目,这样就可以轻松地封送到JSON数组中。

当然,这两个选项都迫使您使用pkg/errors定义的格式,而这种格式并不总是理想的。因此,您可以迭代堆栈跟踪,并生成自己的格式,可能会生成一种很容易被JSON封送的格式。

代码语言:javascript
复制
if err, ok := err.(stackTracer); ok {
        for _, f := range err.StackTrace() {
                fmt.Printf("%+s:%d\n", f, f) // Or your own formatting
        }
}

与其打印每一帧,你可以强迫它成任何你喜欢的格式。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54369295

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档