Logging middleware
- Go course
- Advanced
- Lesson 34/68
- 4 min
Learn to write a middleware that logs requests.
Logging middleware
The request method, path and duration are easy to log; but the status code requires wrapping the ResponseWriter, because the standard interface doesn't say which code the handler wrote:
type kayitci struct {
http.ResponseWriter
kod int
}
func (k *kayitci) WriteHeader(c int) {
k.kod = c
k.ResponseWriter.WriteHeader(c)
}Structured logging with slog
With Go 1.21's log/slog package fields are logged separately, and log search tools can query them:
k := &kayitci{ResponseWriter: w, kod: 200}
bas := time.Now()
next.ServeHTTP(k, r)
slog.Info("istek", "yol", r.URL.Path, "kod", k.kod, "sure", time.Since(bas))Practice Record the status code
Write the kayitci type (embedded http.ResponseWriter and kod int) and its WriteHeader method. The handler calls w.WriteHeader(404); run it with k := &kayitci{ResponseWriter: rec, kod: 200} and print k.kod.
Starter code
package main
import (
"fmt"
"net/http"
"net/http/httptest"
)
func main() {
// buraya yaz
}Sample solution
package main
import (
"fmt"
"net/http"
"net/http/httptest"
)
type kayitci struct {
http.ResponseWriter
kod int
}
func (k *kayitci) WriteHeader(c int) {
k.kod = c
k.ResponseWriter.WriteHeader(c)
}
func main() {
rec := httptest.NewRecorder()
k := &kayitci{ResponseWriter: rec, kod: 200}
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(404) })
h.ServeHTTP(k, httptest.NewRequest("GET", "/yok", nil))
fmt.Println(k.kod)
}Expected output
404
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 If the handler never calls <code>WriteHeader</code>, what is the status code?
- 200 Correct answer
- 0
- 404
- 500
Explanation: The first Write implicitly writes 200; that's why the recorder starts its code field at 200.
2 Capture the code
func (k *kayitci) ____(c int) {
k.kod = c
k.ResponseWriter.WriteHeader(c)
}
func (k *kayitci) WriteHeader(c int) {
k.kod = c
k.ResponseWriter.WriteHeader(c)
}
Explanation: Redefining WriteHeader captures the status code the handler writes.
3 Log fields
| Term | Meaning |
|---|---|
r.Method |
GET, POST... |
r.URL.Path |
Request path |
k.kod |
Status code |
time.Since |
Duration |