在gRPC中使用Uber/Zap日志记录获取实际的错误源

huangapple go评论83阅读模式
英文:

Getting the Actual Error Source in Go with Uber/Zap Logging in gRPC Middleware

问题

我正在使用uber/zap包进行日志记录。
在我的设计中,我在grpc包的中间件中记录任何错误。
我想记录错误来自哪个文件和行号。
然而,目前我只能获取当前中间件的文件名和行号。
有没有办法获取实际错误的源代码?

func RegisterLogger(c config.Config) *zap.SugaredLogger {

	var logger *zap.Logger
	var err error
	if c.IsDebug {
		logger, err = zap.NewDevelopment()
	} else {
		logger, err = zap.NewProduction()
	}

	if err != nil {
		panic(err)
	}
	defer logger.Sync()

	return logger.Sugar()
}



func (s *ProviderServer) Pay(ctx context.Context, in *payment.PayRequest) (string, error) {
	resp, err := ctx.Value(in.Provider).(provider.IPayment).Exec(ctx, in)

	if err != nil {
			pc, file, line, ok := runtime.Caller(2)
			if ok {
				file = filepath.Base(file)
				nowTime := time.Now().Format("2006/01/02 15:04:05")
				funcName := runtime.FuncForPC(pc).Name()
				funcName = filepath.Ext(funcName)
				funcName = strings.TrimPrefix(funcName, ".")
				s.log.Info("Times:", i, " nowTime:", nowTime, " file:", file, " line:", line, " funcName:", funcName, " err:", err)
			}
		
//记录错误信息,包括错误来自哪个文件。

		return resp.Result, err
	} else {
		s.log.Info("resp:", resp)
	}

}
英文:

I am using the uber/zap package for logging.
In my design, I log any errors in the middleware of the grpc package.
I want to record which file and line number the error comes from.
However, currently, I can only get the filename and line number of the current middleware.
Is there any way to get the actual source of the error?

func RegisterLogger(c config.Config) *zap.SugaredLogger {

	var logger *zap.Logger
	var err error
	if c.IsDebug {
		logger, err = zap.NewDevelopment()
	} else {
		logger, err = zap.NewProduction()
	}

	if err != nil {
		panic(err)
	}
	defer logger.Sync()

	return logger.Sugar()
}



func (s *ProviderServer) Pay(ctx context.Context, in *payment.PayRequest) (string, error) {
	resp, err := ctx.Value(in.Provider).(provider.IPayment).Exec(ctx, in)

	if err != nil {
			pc, file, line, ok := runtime.Caller(2)
			if ok {
				file = filepath.Base(file)
				nowTime := time.Now().Format("2006/01/02 15:04:05")
				funcName := runtime.FuncForPC(pc).Name()
				funcName = filepath.Ext(funcName)
				funcName = strings.TrimPrefix(funcName, ".")
				s.log.Info("Times:", i, " nowTime:", nowTime, " file:", file, " line:", line, " funcName:", funcName, " err:", err)
			}
		
//Log the error information, including which file the error comes from.

		return resp.Result, err
	} else {
		s.log.Info("resp:", resp)
	}

}

答案1

得分: 0

在你当前的实现中,你试图记录错误发生的文件和行号。然而,你得到的信息是当前中间件的信息,而不是错误的实际源头。

为了获取实际错误源头的文件和行号信息,你可以使用pkg/errors包。该包提供了一种包装错误并保留文件和行号信息的方法。下面是一个修改你的代码以实现这一点的示例:

import (
	"github.com/pkg/errors"
)

// ...

func (s *ProviderServer) Pay(ctx context.Context, in *payment.PayRequest) (string, error) {
	resp, err := ctx.Value(in.Provider).(provider.IPayment).Exec(ctx, in)

	if err != nil {
		// 使用文件和行号信息包装错误
		err = errors.Wrap(err, "pay error")

		// 记录包装后的错误
		s.log.Errorw("Error occurred", "error", err)

		return resp.Result, err
	} else {
		s.log.Infow("Request processed successfully", "response", resp)
		return resp.Result, nil
	}
}

通过使用errors.Wrap函数包装错误,你可以将文件和行号信息添加到错误中。然后,当使用s.log.Errorw记录错误时,日志消息将包含完整的堆栈跟踪,包括错误发生的文件和行号信息。

这样,你就可以使用errors包提供的信息追踪错误的实际源头。

英文:

In your current implementation, you are trying to log the file and line number where an error occurs. However, the information you are getting is for the current middleware, not the actual source of the error.

To get the file and line information of the actual source of the error, you can make use of the pkg/errors package. This package provides a way to wrap errors and preserve the file and line information. Here's an example of how you can modify your code to achieve this:

import (
	"github.com/pkg/errors"
)

// ...

func (s *ProviderServer) Pay(ctx context.Context, in *payment.PayRequest) (string, error) {
	resp, err := ctx.Value(in.Provider).(provider.IPayment).Exec(ctx, in)

	if err != nil {
		// Wrap the error with file and line information
		err = errors.Wrap(err, "pay error")

		// Log the wrapped error
		s.log.Errorw("Error occurred", "error", err)

		return resp.Result, err
	} else {
		s.log.Infow("Request processed successfully", "response", resp)
		return resp.Result, nil
	}
}

By wrapping the error with the errors.Wrap function, you add the file and line information to the error. Then, when logging the error using s.log.Errorw, the log message will contain the complete stack trace including the file and line information where the error originated.

This way, you can trace the actual source of the error using the information provided by the errors package.

huangapple
  • 本文由 发表于 2023年7月24日 17:04:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76752902.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定