Files
pad/internal/server/middleware_logging.go
T
xarmian e7f4448028 feat: add readiness probe and structured logging (TASK-161)
- Add /health/live (liveness) and /health/ready (readiness with DB check) endpoints
- Add Store.Ping() for database connectivity verification
- Create internal/logging package using stdlib log/slog
- Support PAD_LOG_LEVEL (debug/info/warn/error) and PAD_LOG_FORMAT (text/json) env vars
- Add structured request logging middleware replacing chi's default Logger
- Migrate all log.Printf calls to slog with proper levels and key-value attrs
- Exempt health probe endpoints from auth middleware
2026-04-05 15:02:54 +00:00

49 lines
1.2 KiB
Go

package server
import (
"log/slog"
"net/http"
"time"
chimiddleware "github.com/go-chi/chi/v5/middleware"
)
// StructuredLogger is a chi-compatible request logger that writes structured
// log entries via slog. It replaces chi's default Logger middleware.
func StructuredLogger(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
ww := chimiddleware.NewWrapResponseWriter(w, r.ProtoMajor)
next.ServeHTTP(ww, r)
duration := time.Since(start)
status := ww.Status()
level := slog.LevelInfo
if status >= 500 {
level = slog.LevelError
} else if status >= 400 {
level = slog.LevelWarn
}
attrs := []slog.Attr{
slog.String("method", r.Method),
slog.String("path", r.URL.Path),
slog.Int("status", status),
slog.Duration("duration", duration),
slog.Int("bytes", ww.BytesWritten()),
}
if reqID := chimiddleware.GetReqID(r.Context()); reqID != "" {
attrs = append(attrs, slog.String("request_id", reqID))
}
if r.URL.RawQuery != "" {
attrs = append(attrs, slog.String("query", r.URL.RawQuery))
}
slog.LogAttrs(r.Context(), level, "http request", attrs...)
})
}