fix logger.

This commit is contained in:
Miroslav Šedivý 2021-09-17 00:58:50 +02:00
parent 8d0fcbde70
commit 5688be80ba
2 changed files with 48 additions and 37 deletions

View File

@ -7,6 +7,7 @@ import (
"time" "time"
"github.com/go-chi/chi/middleware" "github.com/go-chi/chi/middleware"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"demodesk/neko/internal/http/auth" "demodesk/neko/internal/http/auth"
@ -18,36 +19,43 @@ type logEntryKey int
const logEntryKeyCtx logEntryKey = iota const logEntryKeyCtx logEntryKey = iota
func setLogEntry(r *http.Request, data logEntry) *http.Request { func setLogEntry(r *http.Request, data *logEntry) *http.Request {
ctx := context.WithValue(r.Context(), logEntryKeyCtx, data) ctx := context.WithValue(r.Context(), logEntryKeyCtx, data)
return r.WithContext(ctx) return r.WithContext(ctx)
} }
func getLogEntry(r *http.Request) logEntry { func getLogEntry(r *http.Request) *logEntry {
return r.Context().Value(logEntryKeyCtx).(logEntry) return r.Context().Value(logEntryKeyCtx).(*logEntry)
} }
func LoggerMiddleware(next http.Handler) http.Handler { func LoggerMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, setLogEntry(r, newLogEntry(w, r))) ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor)
logEntry := newLogEntry(w, r)
defer func() {
logEntry.Write(ww.Status(), ww.BytesWritten())
}()
next.ServeHTTP(ww, setLogEntry(r, logEntry))
}) })
} }
type logEntry struct { type logEntry struct {
req struct { req struct {
time time.Time Time time.Time
id string Id string
scheme string Scheme string
proto string Proto string
method string Method string
remote string Remote string
agent string Agent string
uri string Uri string
} }
res struct { res struct {
time time.Time Time time.Time
code int Code int
bytes int Bytes int
} }
err error err error
elapsed time.Duration elapsed time.Duration
@ -55,12 +63,12 @@ type logEntry struct {
session types.Session session types.Session
} }
func newLogEntry(w http.ResponseWriter, r *http.Request) logEntry { func newLogEntry(w http.ResponseWriter, r *http.Request) *logEntry {
e := logEntry{} e := logEntry{}
e.req.time = time.Now() e.req.Time = time.Now()
if reqID := middleware.GetReqID(r.Context()); reqID != "" { if reqID := middleware.GetReqID(r.Context()); reqID != "" {
e.req.id = reqID e.req.Id = reqID
} }
scheme := "http" scheme := "http"
@ -68,22 +76,19 @@ func newLogEntry(w http.ResponseWriter, r *http.Request) logEntry {
scheme = "https" scheme = "https"
} }
e.req.scheme = scheme e.req.Scheme = scheme
e.req.proto = r.Proto e.req.Proto = r.Proto
e.req.method = r.Method e.req.Method = r.Method
e.req.remote = r.RemoteAddr e.req.Remote = r.RemoteAddr
e.req.agent = r.UserAgent() e.req.Agent = r.UserAgent()
e.req.uri = fmt.Sprintf("%s://%s%s", scheme, r.Host, r.RequestURI) e.req.Uri = fmt.Sprintf("%s://%s%s", scheme, r.Host, r.RequestURI)
return e return &e
} }
func (e *logEntry) SetResponse(w http.ResponseWriter, r *http.Request) { func (e *logEntry) SetResponse(w http.ResponseWriter, r *http.Request) {
ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) e.res.Time = time.Now()
e.res.time = time.Now()
e.res.code = ww.Status()
e.res.bytes = ww.BytesWritten()
e.elapsed = e.res.time.Sub(e.req.time) e.elapsed = e.res.Time.Sub(e.req.Time)
e.session, e.hasSession = auth.GetSession(r) e.session, e.hasSession = auth.GetSession(r)
} }
@ -91,7 +96,10 @@ func (e *logEntry) SetError(err error) {
e.err = err e.err = err
} }
func (e *logEntry) Write() { func (e *logEntry) Write(status, bytes int) {
e.res.Code = status
e.res.Bytes = bytes
logger := log.With(). logger := log.With().
Str("module", "http"). Str("module", "http").
Float64("elapsed", float64(e.elapsed.Nanoseconds())/1000000.0). Float64("elapsed", float64(e.elapsed.Nanoseconds())/1000000.0).
@ -106,7 +114,7 @@ func (e *logEntry) Write() {
if e.err != nil { if e.err != nil {
httpErr, ok := e.err.(*utils.HTTPError) httpErr, ok := e.err.(*utils.HTTPError)
if !ok { if !ok {
logger.Err(e.err).Msgf("request failed (%d)", e.res.code) logger.Err(e.err).Msgf("request failed (%d)", e.res.Code)
return return
} }
@ -114,16 +122,21 @@ func (e *logEntry) Write() {
httpErr.Message = http.StatusText(httpErr.Code) httpErr.Message = http.StatusText(httpErr.Code)
} }
logger := logger.Error().Err(httpErr.InternalErr) var logEvent *zerolog.Event
if httpErr.Code < 500 {
logEvent = logger.Warn()
} else {
logEvent = logger.Error()
}
message := httpErr.Message message := httpErr.Message
if httpErr.InternalMsg != "" { if httpErr.InternalMsg != "" {
message = httpErr.InternalMsg message = httpErr.InternalMsg
} }
logger.Msgf("request failed (%d): %s", e.res.code, message) logEvent.Err(httpErr.InternalErr).Msgf("request failed (%d): %s", e.res.Code, message)
return return
} }
logger.Debug().Msgf("request complete (%d)", e.res.code) logger.Debug().Msgf("request complete (%d)", e.res.Code)
} }

View File

@ -86,7 +86,6 @@ func routeHandler(fn types.RouterHandler) http.HandlerFunc {
} }
logEntry.SetResponse(w, r) logEntry.SetResponse(w, r)
logEntry.Write()
} }
} }
@ -100,7 +99,6 @@ func middlewareHandler(fn types.MiddlewareHandler) func(http.Handler) http.Handl
logEntry.SetError(err) logEntry.SetError(err)
errorHandler(err, w, r) errorHandler(err, w, r)
logEntry.SetResponse(w, r) logEntry.SetResponse(w, r)
logEntry.Write()
return return
} }
if ctx != nil { if ctx != nil {