第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機(jī)立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何讓 logrus 打印 pkg/errors 堆棧

如何讓 logrus 打印 pkg/errors 堆棧

Go
喵喵時光機(jī) 2023-06-01 18:19:46
我正在使用 github.com/sirupsen/logrus 和 github.com/pkg/errors。當(dāng)我提交一個從 pkg/errors 包裝或創(chuàng)建的錯誤時,我在注銷中看到的只是錯誤消息。我想查看堆棧跟蹤。我推斷 logrus 有一些處理 pkg/errors 的本機(jī)方法。我怎樣才能做到這一點(diǎn)?
查看完整描述

3 回答

?
繁華開滿天機(jī)

TA貢獻(xiàn)1816條經(jīng)驗(yàn) 獲得超4個贊

(順便說一句,似乎來自與 Logrus 沒有任何關(guān)系且對 Logrus 沒有做出任何貢獻(xiàn)的人,因此實(shí)際上不是來自“Logrus 團(tuán)隊(duì)”)。


如記錄的那樣pkg/errors,很容易在錯誤中提取堆棧跟蹤:


type stackTracer interface {

? ? ? ? StackTrace() errors.StackTrace

}

這意味著使用 logrus 記錄堆棧跟蹤的最簡單方法就是:


if stackErr, ok := err.(stackTracer); ok {

? ? log.WithField("stacktrace", fmt.Sprintf("%+v", stackErr.StackTrace()))

}

從今天開始,當(dāng)我的一個拉取請求與 合并pkg/errors時,如果您使用的是 JSON 日志記錄,現(xiàn)在就更容易了:


if stackErr, ok := err.(stackTracer); ok {

? ? log.WithField("stacktrace", stackErr.StackTrace())

}

這將生成類似于“%+v”的日志格式,但沒有換行符或制表符,每個字符串有一個日志條目,以便于編組到 JSON 數(shù)組中。


當(dāng)然,這兩個選項(xiàng)都會強(qiáng)制您使用 定義的格式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

? ? ? ? }

}

您可以將其強(qiáng)制轉(zhuǎn)換為您喜歡的任何格式,而不是打印每一幀。


查看完整回答
反對 回復(fù) 2023-06-01
?
DIEA

TA貢獻(xiàn)1820條經(jīng)驗(yàn) 獲得超2個贊

推論是錯誤的。Logrus 實(shí)際上并不知道如何處理錯誤。?

類似 Java 的響應(yīng)?為了以這種方式普遍使用錯誤處理程序,我編寫了一個新版本的 Entry,它來自 Logrus。如示例所示,使用您想要的任何常用字段創(chuàng)建一個新條目(示例下方是在處理程序中設(shè)置的記錄器,用于跟蹤調(diào)用者 ID。在處理?xiàng)l目時通過層傳遞 PgkError。當(dāng)您需要時記錄特定的錯誤,比如遇到錯誤的調(diào)用變量,從 PkgError.WithError(...) 開始,然后添加您的詳細(xì)信息。

這是一個起點(diǎn)。如果您想普遍使用它,請?jiān)?PkgErrorEntry 上實(shí)現(xiàn)所有 Entity 接口。繼續(xù)委托給內(nèi)部入口,但返回一個新的 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-ish 方式 請參閱https://www.reddit.com/r/golang/comments/ajby88/how_to_get_stack_traces_in_logrus/了解更多詳情。


Ben Johnson寫過關(guān)于讓錯誤成為你領(lǐng)域的一部分。一個簡化版本是您應(yīng)該將跟蹤器屬性放在自定義錯誤上。當(dāng)直接受您控制的代碼出錯或發(fā)生來自第 3 方庫的錯誤時,立即處理錯誤的代碼應(yīng)將唯一值放入自定義錯誤中。該值將作為自定義錯誤Error() string實(shí)現(xiàn)的一部分打印。


當(dāng)開發(fā)人員獲得日志文件時,他們將能夠 grep 代碼庫以獲取該唯一值。Ben 說:“最后,我們需要能夠向我們的操作員提供所有這些信息以及邏輯堆棧跟蹤,以便他們可以調(diào)試問題。Go 已經(jīng)提供了一個簡單的方法 error.Error() 來打印錯誤信息,因此我們可以利用那?!?/p>


這是本的例子


// 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 代碼的一個問題是值很容易偏離原始上下文。例如,假設(shè)函數(shù)的名稱從 attachRole 更改為其他名稱并且函數(shù)更長。op 值可能與函數(shù)名稱不同。無論如何,這似乎滿足了跟蹤問題的一般需要,同時將錯誤視為一等公民。


Go2 可能會在這方面投入更多的 Java-ish 響應(yīng)。


查看完整回答
反對 回復(fù) 2023-06-01
?
忽然笑

TA貢獻(xiàn)1806條經(jīng)驗(yàn) 獲得超5個贊

使用自定義鉤子提取堆棧跟蹤


import (

    "fmt"

    "github.com/pkg/errors"

    "github.com/sirupsen/logrus"

)


type StacktraceHook struct {

}


func (h *StacktraceHook) Levels() []logrus.Level {

    return logrus.AllLevels

}


func (h *StacktraceHook) Fire(e *logrus.Entry) error {

    if v, found := e.Data[logrus.ErrorKey]; found {

        if err, iserr := v.(error); iserr {

            type stackTracer interface {

                StackTrace() errors.StackTrace

            }

            if st, isst := err.(stackTracer); isst {

                stack := fmt.Sprintf("%+v", st.StackTrace())

                e.Data["stacktrace"] = stack

            }

        }

    }

    return nil

}


func main() {

    logrus.SetFormatter(&logrus.TextFormatter{DisableQuote: true})

    logrus.AddHook(&StacktraceHook{})


    logrus.WithError(errors.New("Foo")).Error("Wrong")

}

輸出


time=2009-11-10T23:00:00Z level=error msg=Wrong error=Foo stacktrace=

main.main

    /tmp/sandbox1710078453/prog.go:36

runtime.main

    /usr/local/go-faketime/src/runtime/proc.go:250

runtime.goexit

    /usr/local/go-faketime/src/runtime/asm_amd64.s:1594


查看完整回答
反對 回復(fù) 2023-06-01
  • 3 回答
  • 0 關(guān)注
  • 530 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號