Files
go-common/middleware/logging.go

67 lines
1.4 KiB
Go

package middleware
import (
"net/http"
"time"
"git.toowon.com/jimmy/go-common/logger"
)
// responseWriter 包装 ResponseWriter 以捕获状态码
type responseWriter struct {
http.ResponseWriter
statusCode int
}
func (rw *responseWriter) WriteHeader(statusCode int) {
rw.statusCode = statusCode
rw.ResponseWriter.WriteHeader(statusCode)
}
// LoggingConfig 日志中间件配置
type LoggingConfig struct {
Logger *logger.Logger
SkipPaths []string
}
// Logging HTTP 访问日志(固定 Info 级别)
func Logging(config *LoggingConfig) func(http.Handler) http.Handler {
if config == nil {
config = &LoggingConfig{}
}
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if shouldSkipPath(r.URL.Path, config.SkipPaths) {
next.ServeHTTP(w, r)
return
}
start := time.Now()
rw := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK}
next.ServeHTTP(rw, r)
fields := map[string]any{
"method": r.Method,
"path": r.URL.Path,
"duration": time.Since(start).Milliseconds(),
}
log := logger.FromContext(r.Context())
if config.Logger != nil {
log = logger.FromContextWithLogger(r.Context(), config.Logger)
}
log.Info("HTTP Request", fields)
})
}
}
func shouldSkipPath(path string, skipPaths []string) bool {
for _, skip := range skipPaths {
if path == skip {
return true
}
}
return false
}