给每个路由器添加日志记录

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

Go : add logging to each router

问题

Go:为每个路由添加日志记录

我想在Go Web应用程序中记录所有的网络请求。

类似于negroni的方式:

  1. // https://github.com/codegangsta/negroni/blob/master/logger.go
  2. // NewLogger返回一个新的Logger实例
  3. func NewLogger() *Logger {
  4. return &Logger{log.New(os.Stdout, "[negroni] ", 0)}
  5. }
  6. func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
  7. start := time.Now()
  8. l.Printf("Started %s %s", r.Method, r.URL.Path)
  9. next(rw, r)
  10. res := rw.(ResponseWriter)
  11. l.Printf("Completed %v %s in %v", res.Status(), http.StatusText(res.Status()), time.Since(start))
  12. }

所以这是我的代码:

  1. router := httprouter.New()
  2. handler := func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
  3. type Page struct {
  4. Title string
  5. }
  6. tp := template.Must(template.ParseFiles("templates/main.html", "templates/base.html"))
  7. err := tp.ExecuteTemplate(w, "base", &Page{Title: "AAA"})
  8. if err != nil {
  9. log.Fatal(err)
  10. }
  11. router.Handle("GET", "/", handler)
  12. l := log.New(os.Stdout, "[AAA] ", 0)
  13. l.Printf("Listening 0.0.0.0%s", PORT)
  14. l.Fatal(http.ListenAndServe(PORT, router))

如果我想要实现这个功能,我必须在我的代码中手动添加start := time.Now()time.Since(start)到每个路由中。

我认为我应该封装它并使用接口,但不知道如何入手。

如何实现一个简单的日志记录接口,并将其应用于所有的路由处理程序,以便我可以通过所有的日志记录进行调试...

negroni的做法如下:

  1. router := mux.NewRouter()
  2. router.HandleFunc("/", HomeHandler)
  3. n := negroni.New(Middleware1, Middleware2)
  4. // 或者使用Use()函数使用中间件
  5. n.Use(Middleware3)
  6. // router放在最后
  7. n.UseHandler(router)
  8. n.Run(":3000")
英文:

Go : add logging to each router

I want to log all my network request in Go web app.

Something like negroni:

  1. // https://github.com/codegangsta/negroni/blob/master/logger.go
  2. // NewLogger returns a new Logger instance
  3. func NewLogger() *Logger {
  4. return &Logger{log.New(os.Stdout, "[negroni] ", 0)}
  5. }
  6. func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
  7. start := time.Now()
  8. l.Printf("Started %s %s", r.Method, r.URL.Path)
  9. next(rw, r)
  10. res := rw.(ResponseWriter)
  11. l.Printf("Completed %v %s in %v", res.Status(), http.StatusText(res.Status()), time.Since(start))
  12. }

So here's my code:

  1. router := httprouter.New()
  2. handler := func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
  3. type Page struct {
  4. Title string
  5. }
  6. tp := template.Must(template.ParseFiles("templates/main.html", "templates/base.html"))
  7. err := tp.ExecuteTemplate(w, "base", &Page{Title: "AAA"})
  8. if err != nil {
  9. log.Fatal(err)
  10. }
  11. router.Handle("GET", "/", handler)
  12. l := log.New(os.Stdout, "[AAA] ", 0)
  13. l.Printf("Listening 0.0.0.0%s", PORT)
  14. l.Fatal(http.ListenAndServe(PORT, router))

If I want to do this, I have to add start := time.Now() and time.Since(start) manually to each router in my code.package main

I think I should wrap it and use interface but don't know how to get started.

How do I implement one simple logging interface and apply all the routed handlers so that I can debug with all the loggings...

Negroni does like:

  1. router := mux.NewRouter()
  2. router.HandleFunc("/", HomeHandler)
  3. n := negroni.New(Middleware1, Middleware2)
  4. // Or use a middleware with the Use() function
  5. n.Use(Middleware3)
  6. // router goes last
  7. n.UseHandler(router)
  8. n.Run(":3000")

答案1

得分: 1

将根处理程序包装在一个记录并委托给另一个处理程序的处理程序中:

  1. type RequestLogger struct {
  2. h http.Handler
  3. l *Logger
  4. }
  5. func (rl RequestLogger) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  6. start := time.Now()
  7. rl.l.Printf("Started %s %s", r.Method, r.URL.Path)
  8. rl.h.ServeHTTP(w, r)
  9. rl.l.Printf("Completed %s %s in %v", r.Method, r.URL.Path, time.Since(start))
  10. }

  1. l := log.New(os.Stdout, "[AAA] ", 0)
  2. l.Printf("Listening 0.0.0.0%s", PORT)
  3. l.Fatal(http.ListenAndServe(PORT, RequestLogger{h:router, l:l}))
英文:

Wrap the root handler with a handler that logs and delegates to another handler:

  1. type RequestLogger struct {
  2. h http.Handler
  3. l *Logger
  4. }
  5. func (rl RequestLogger) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  6. start := time.Now()
  7. rl.l.Printf("Started %s %s", r.Method, r.URL.Path)
  8. rl.h.ServeHTTP(w, r)
  9. rl.l.Printf("Completed %s %s in %v", r.Method, r.URL.Path, time.Since(start))
  10. }
  11. ---
  12. l := log.New(os.Stdout, "[AAA] ", 0)
  13. l.Printf("Listening 0.0.0.0%s", PORT)
  14. l.Fatal(http.ListenAndServe(PORT, RequestLogger{h:router, l:l}))

答案2

得分: 1

一个简单的中间件拦截器可能是正确的方法。如果你想要一个例子,可以在这里看到一个简单的例子:https://github.com/jadekler/git-go-websiteskeleton/blob/master/main.go#L49。这个例子可以缩小为一个更小的函数,但效果可能有所不同。

以下是相关的代码:

在你的handlefuncs的顶部:

  1. http.HandleFunc("/", httpInterceptor)

在你的中间件中:

  1. func httpInterceptor(w http.ResponseWriter, req *http.Request) {
  2. router.ServeHTTP(w, req)
  3. logAccess(w, req)
  4. }

其中logAccess是一个记录你想要的任何内容的函数。例如,可以参考这里

英文:

A simple middleware interceptor is probably the right approach. If you'd like an example, see a simple one here: https://github.com/jadekler/git-go-websiteskeleton/blob/master/main.go#L49. This can be contracted down to a smaller function, but YMMV.

Here is the relevant code:

At the top of your handlefuncs:

  1. http.HandleFunc("/", httpInterceptor)

In your middleware:

  1. func httpInterceptor(w http.ResponseWriter, req *http.Request) {
  2. router.ServeHTTP(w, req)
  3. logAccess(w, req)
  4. }

Where logAccess is a function that logs whatever you'd like it to. For an example, see here.

答案3

得分: 0

在Go语言中实现自己的中间件相当容易,一种方法是这样的:

  1. var logger = log.New(os.Stdout, "[something shiny] ", 0)
  2. func httpLogger(fn func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
  3. return func(w http.ResponseWriter, r *http.Request) {
  4. start := time.Now()
  5. logger.Printf("Started %s %s", r.Method, r.URL.Path)
  6. fn(w, r)
  7. logger.Printf("Completed in %v", time.Since(start))
  8. }
  9. }
  10. ....
  11. router.Handle("GET", "/", httpLogger(handler))

以上代码是一个示例,通过定义httpLogger函数作为中间件,可以在处理HTTP请求之前和之后记录日志。在这个示例中,httpLogger函数接受一个处理HTTP请求的函数作为参数,并返回一个新的函数作为中间件。这个中间件函数在处理请求之前记录请求的起始时间和请求方法、路径等信息,然后调用传入的处理函数处理请求,最后记录请求的完成时间。通过将中间件应用到路由处理函数上,可以实现在处理请求前后添加额外的逻辑,比如记录日志。

英文:

It's rather easy to implement your own middleware in Go, one approach is something like:

  1. var logger = log.New(os.Stdout, "[something shiny] ", 0)
  2. func httpLogger(fn func(w http.ResponseWriter, r *http.Request)) func(w http.ResponseWriter, r *http.Request) {
  3. return func(w http.ResponseWriter, r *http.Request) {
  4. start := time.Now()
  5. logger.Printf("Started %s %s", r.Method, r.URL.Path)
  6. fn(w, r)
  7. logger.Printf("Completed in %v", time.Since(start))
  8. }
  9. }
  10. ....
  11. router.Handle("GET", "/", httpLogger(handler))

huangapple
  • 本文由 发表于 2014年10月4日 02:15:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/26184465.html
匿名

发表评论

匿名网友

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

确定