Implement structured logging and enhance middleware with context-aware logging
This commit is contained in:
@ -1,9 +1,11 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.coopcloud.tech/wiki-cafe/member-console/internal/logging"
|
||||
)
|
||||
|
||||
type wrappedWriter struct {
|
||||
@ -16,21 +18,48 @@ func (w *wrappedWriter) WriteHeader(statusCode int) {
|
||||
w.statusCode = statusCode
|
||||
}
|
||||
|
||||
// Logging is a middleware function that logs the request method, URL path, and status code
|
||||
// Logging is a middleware function that logs requests with structured logging
|
||||
func Logging(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
|
||||
// Prepare wrapped writer to capture status code
|
||||
wrapped := &wrappedWriter{
|
||||
ResponseWriter: w,
|
||||
statusCode: http.StatusOK,
|
||||
}
|
||||
|
||||
// Get request ID from header (set by RequestID middleware)
|
||||
requestID := r.Header.Get(RequestIDHeader)
|
||||
|
||||
// Get request ID from context
|
||||
requestID := GetRequestID(r.Context())
|
||||
|
||||
// Get logger from the application and add request information
|
||||
logger := logging.FromContext(r.Context())
|
||||
reqLogger := logging.WithValues(logger,
|
||||
slog.String("request_id", requestID),
|
||||
slog.String("method", r.Method),
|
||||
slog.String("path", r.URL.Path),
|
||||
slog.String("remote_ip", r.RemoteAddr),
|
||||
slog.String("user_agent", r.UserAgent()),
|
||||
)
|
||||
|
||||
// Store the request-specific logger in context
|
||||
ctx := logging.WithContext(r.Context(), reqLogger)
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
// Log request start if in debug mode
|
||||
reqLogger.Debug("request started")
|
||||
|
||||
// Process the request with updated context
|
||||
next.ServeHTTP(wrapped, r)
|
||||
|
||||
log.Printf("[%s] %d %s %s %v", requestID, wrapped.statusCode, r.Method, r.URL.Path, time.Since(start))
|
||||
// Calculate duration
|
||||
duration := time.Since(start)
|
||||
|
||||
// Log request completion with status and duration
|
||||
reqLogger.Info("request completed",
|
||||
slog.Int("status", wrapped.statusCode),
|
||||
slog.Duration("duration", duration),
|
||||
slog.String("duration_human", duration.String()),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user