Home > Back-end >  How to log only errors like 404 with chi in go?
How to log only errors like 404 with chi in go?

Time:12-10

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, "            
  • Related