如何在Go语言中使用chi仅记录错误(如404)?

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

How to log only errors like 404 with chi in go?

问题

我正在使用chi和我们的Go Web服务。

如何配置日志记录器(middleware),使其仅记录以错误结束的请求(如404),但不记录成功的请求(状态码为200)?

以下是我们当前的实现(没有任何日志记录):

r := chi.NewRouter()

if DEBUG_LOGS {
    r.Use(middleware.Logger)
} else {

}

请注意,这只是一个示例代码,你可能需要根据你的实际需求进行适当的修改。

英文:

I'm using chi with our Go webservices.

How to configure the logger (middleware) so it only logs requests that ended up with errors (like 404) but it doesn't log successful requests (with status code 200)?

Here's our current implementation (with no logging at all)

r := chi.NewRouter()

if DEBUG_LOGS {
	r.Use(middleware.Logger)
} else {

}

答案1

得分: 1

最简单的方法是使用chi包的示例自己实现日志记录功能(为简单起见,我删除了颜色)。

package main

import (
	"bytes"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
)

const DEBUG_LOGS = true

func main() {
	api := &http.Server{Addr: ":8000"}

	r := chi.NewRouter()

	if DEBUG_LOGS {
		// 创建默认的日志记录器/zerolog/logrus
		logger := log.New(os.Stdout, "", log.LstdFlags)
		r.Use(middleware.RequestLogger(&StructuredLogger{logger}))
	}

	r.Get("/tea", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusTeapot) })
	r.Get("/ok", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })

	api.Handler = r

	err := api.ListenAndServe()
	if err != nil {
		log.Fatal(err)
	}
}

// 下面是自定义日志记录器的实现。

type StructuredLogger struct {
	Logger middleware.LoggerInterface
}

type LogEntry struct {
	*StructuredLogger
	request  *http.Request
	buf      *bytes.Buffer
	useColor bool
}

func (l *StructuredLogger) NewLogEntry(r *http.Request) middleware.LogEntry {
	entry := &LogEntry{
		StructuredLogger: l,
		request:          r,
		buf:              &bytes.Buffer{},
		useColor:         false,
	}

	reqID := middleware.GetReqID(r.Context())
	if reqID != "" {
		fmt.Fprintf(entry.buf, "[%s] ", reqID)
	}

	fmt.Fprintf(entry.buf, "\"")
	fmt.Fprintf(entry.buf, "%s ", r.Method)

	scheme := "http"
	if r.TLS != nil {
		scheme = "https"
	}
	fmt.Fprintf(entry.buf, "%s://%s%s %s\" ", scheme, r.Host, r.RequestURI, r.Proto)

	entry.buf.WriteString("from ")
	entry.buf.WriteString(r.RemoteAddr)
	entry.buf.WriteString(" - ")

	return entry
}

func (l *LogEntry) Write(status, bytes int, header http.Header, elapsed time.Duration, extra interface{}) {
	// 如果状态码是200/201/等,则不执行任何操作
	if status < 300 {
		return
	}

	fmt.Fprintf(l.buf, "%03d", status)
	fmt.Fprintf(l.buf, " %dB", bytes)

	l.buf.WriteString(" in ")
	if elapsed < 500*time.Millisecond {
		fmt.Fprintf(l.buf, "%s", elapsed)
	} else if elapsed < 5*time.Second {
		fmt.Fprintf(l.buf, "%s", elapsed)
	} else {
		fmt.Fprintf(l.buf, "%s", elapsed)
	}

	l.Logger.Print(l.buf.String())
}

func (l *LogEntry) Panic(v interface{}, stack []byte) {
	middleware.PrintPrettyStack(v)
}

英文:

The easiest way is to implement the logging function by yourself using the example from the chi package (for simplicity, I removed the colors).

package main

import (
	&quot;bytes&quot;
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;os&quot;
	&quot;time&quot;

	&quot;github.com/go-chi/chi/v5&quot;
	&quot;github.com/go-chi/chi/v5/middleware&quot;
)

const DEBUG_LOGS = true

func main() {
	api := &amp;http.Server{Addr: &quot;:8000&quot;}

	r := chi.NewRouter()

    if DEBUG_LOGS {
	    // create default logger/zerolog/logrus
	    logger := log.New(os.Stdout, &quot;&quot;, log.LstdFlags)
	    r.Use(middleware.RequestLogger(&amp;StructuredLogger{logger}))
    }

	r.Get(&quot;/tea&quot;, func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusTeapot) })
	r.Get(&quot;/ok&quot;, func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) })

	api.Handler = r

	err := api.ListenAndServe()
	if err != nil {
		log.Fatal(err)
	}
}

// below is the implementation of the custom logger.

type StructuredLogger struct {
	Logger middleware.LoggerInterface
}

type LogEntry struct {
	*StructuredLogger
	request  *http.Request
	buf      *bytes.Buffer
	useColor bool
}

func (l *StructuredLogger) NewLogEntry(r *http.Request) middleware.LogEntry {
	entry := &amp;LogEntry{
		StructuredLogger: l,
		request:          r,
		buf:              &amp;bytes.Buffer{},
		useColor:         false,
	}

	reqID := middleware.GetReqID(r.Context())
	if reqID != &quot;&quot; {
		fmt.Fprintf(entry.buf, &quot;[%s] &quot;, reqID)
	}

	fmt.Fprintf(entry.buf, &quot;\&quot;&quot;)
	fmt.Fprintf(entry.buf, &quot;%s &quot;, r.Method)

	scheme := &quot;http&quot;
	if r.TLS != nil {
		scheme = &quot;https&quot;
	}
	fmt.Fprintf(entry.buf, &quot;%s://%s%s %s\&quot; &quot;, scheme, r.Host, r.RequestURI, r.Proto)

	entry.buf.WriteString(&quot;from &quot;)
	entry.buf.WriteString(r.RemoteAddr)
	entry.buf.WriteString(&quot; - &quot;)

	return entry
}

func (l *LogEntry) Write(status, bytes int, header http.Header, elapsed time.Duration, extra interface{}) {
	// Do nothing if status code is 200/201/eg
	if status &lt; 300 {
		return
	}

	fmt.Fprintf(l.buf, &quot;%03d&quot;, status)
	fmt.Fprintf(l.buf, &quot; %dB&quot;, bytes)

	l.buf.WriteString(&quot; in &quot;)
	if elapsed &lt; 500*time.Millisecond {
		fmt.Fprintf(l.buf, &quot;%s&quot;, elapsed)
	} else if elapsed &lt; 5*time.Second {
		fmt.Fprintf(l.buf, &quot;%s&quot;, elapsed)
	} else {
		fmt.Fprintf(l.buf, &quot;%s&quot;, elapsed)
	}

	l.Logger.Print(l.buf.String())
}

func (l *LogEntry) Panic(v interface{}, stack []byte) {
	middleware.PrintPrettyStack(v)
}

huangapple
  • 本文由 发表于 2022年12月9日 18:59:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/74742169.html
匿名

发表评论

匿名网友

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

确定