如何将日志记录器作为参数传递给一系列中间件函数?

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

How to pass a logger as an argument to a chain of middleware functions?

问题

我是你的中文翻译助手,以下是翻译好的内容:

我刚开始学习Go语言,所以请多包涵。

我正在尝试使用Uber的Zap日志记录包。我已经仔细阅读了文档并查看了许多示例,但是我在如何最好地使用它方面遇到了困难。他们的常见问题解答部分建议避免将Zap用作全局记录器,因此我正在尝试将在server.go中初始化的内容传递给其他函数。

// 初始化日志记录器
logger, err := zap.NewProduction()
if err != nil {
	log.Fatalf("Failed to initialize zap logger: %v", err)
}
defer logger.Sync()
sugar := logger.Sugar()
sugar.Info("Server is starting...")

router := http.NewServeMux()

server := &http.Server{
	Addr:         addr,
	Handler:      middleware.Middleware{middleware.RequestIdentifier, middleware.RequestLogger}.Apply(router),
    // ...其他字段
}

其中,在另一个文件中定义了Middleware

type Middleware []func(http.Handler) http.Handler

// Apply() 将中间件数组构建成处理程序链
func (midware Middleware) Apply(handler http.Handler) http.Handler {
	if len(midware) == 0 {
		return handler
	}
	return midware[:len(midware)-1].Apply(midware[len(midware)-1](handler))
}

然后在另一个文件(request_identifier.go)中:

func RequestIdentifier(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        //
		// ...一些操作,并在这里使用Zap
        //
		next.ServeHTTP(w, r)
	})
}

其他中间件函数也是类似的。

我尝试过包装RequestIdentifier函数,并尝试调整Middleware的接受函数签名,但是我似乎无法找到如何在不让我的IDE报错的情况下传递sugar的方法。

我希望的是像下面这样的代码:

Handler: middleware.Middleware{middleware.RequestIdentifier(sugar), middleware.RequestLogger(sugar)}.Apply(router)

然后在我的中间件函数中,以某种方式访问可用的日志记录器,例如:

func RequestIdentifier(next http.Handler, s *zap.SugaredLogger) http.Handler { ... }
英文:

I'm new to Go, so please bear with me.

I'm trying to use Uber's Zap logging package. I've poured through the documentation and have looked through many examples, but am struggling to find how best to use it. Their FAQ section says to avoid using Zap as a global logger, so I'm trying to pass what has been initialized in server.go (immediately below) to other functions.

// Initialize logger
logger, err := zap.NewProduction()
if err != nil {
	log.Fatalf("Failed to initialize zap logger: %v", err)
}
defer logger.Sync()
sugar := logger.Sugar()
sugar.Info("Server is starting...")

router := http.NewServeMux()

server := &http.Server{
	Addr:         addr,
	Handler:      middleware.Middleware{middleware.RequestIdentifier, middleware.RequestLogger}.Apply(router),
    // ...other fields
}

Where Middleware is defined, in another file, as

type Middleware []func(http.Handler) http.Handler

// Apply() builds the middleware array into a handler chain
func (midware Middleware) Apply(handler http.Handler) http.Handler {
	if len(midware) == 0 {
		return handler
	}
	return midware[:len(midware)-1].Apply(midware[len(midware)-1](handler))
}

Then in another file (request_identifier.go).

func RequestIdentifier(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        //
		// ...stuff, and use Zap here
        //
		next.ServeHTTP(w, r)
	})
}

And similarly for the other middleware function.

I've tried wrapping RequestIdentifier and have tried toying with the accepted function signature of Middleware, but I can't seem to figure out how I can pass sugar without having my IDE yell at me.

What I would like would be something such as:

Handler: middleware.Middleware{middleware.RequestIdentifier(sugar), middleware.RequestLogger(sugar)}.Apply(router)

Then in my middleware functions, have access to the logger available in some fashion like so:

func RequestIdentifier(next http.Handler, s *zap.SugaredLogger) http.Handler { ... }

答案1

得分: 1

你需要再添加一层闭包:

func RequestIdentifier(s *zap.SugaredLogger) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			//
			// ...stuff, and use Zap here
			//
			next.ServeHTTP(w, r)
		})
	}
}
Handler: middleware.Middleware{middleware.RequestIdentifier(sugar), middleware.RequestLogger(sugar)}.Apply(router),

你需要将上述代码翻译为中文吗?

英文:

You need to add one more layer of closure:

func RequestIdentifier(s *zap.SugaredLogger) func(http.Handler) http.Handler {
	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			//
			// ...stuff, and use Zap here
			//
			next.ServeHTTP(w, r)
		})
	}
}

Handler: middleware.Middleware{middleware.RequestIdentifier(sugar), middleware.RequestLogger(sugar)}.Apply(router),

huangapple
  • 本文由 发表于 2021年12月3日 07:21:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/70207689.html
匿名

发表评论

匿名网友

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

确定