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 {
}
CodePudding user response:
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 (
"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 {
// create default logger/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)
}
}
// 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 := &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{}) {
// Do nothing if status code is 200/201/eg
if status < 300 {
return
}
fmt.Fprintf(l.buf, "d", status)
fmt.Fprintf(l.buf, "