backend-service/internal/middleware/logging.go

98 lines
2.0 KiB
Go
Raw Normal View History

package middleware
import (
"fmt"
"log"
"time"
"github.com/gin-gonic/gin"
)
// LoggingMiddleware creates a custom logging middleware with detailed request information
func LoggingMiddleware() gin.HandlerFunc {
return gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
// Custom log format with more details
return fmt.Sprintf("[%s] %s %s %s %d %s \"%s\" %s \"%s\" %s\n",
param.TimeStamp.Format("2006-01-02 15:04:05"),
param.ClientIP,
param.Method,
param.Path,
param.StatusCode,
param.Latency,
param.Request.UserAgent(),
param.ErrorMessage,
param.Request.Referer(),
formatBodySize(param.BodySize),
)
})
}
// StructuredLoggingMiddleware creates a structured logging middleware for better log parsing
func StructuredLoggingMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// Start timer
start := time.Now()
path := c.Request.URL.Path
raw := c.Request.URL.RawQuery
// Process request
c.Next()
// Calculate latency
latency := time.Since(start)
// Get client IP
clientIP := c.ClientIP()
// Get method
method := c.Request.Method
// Get status code
statusCode := c.Writer.Status()
// Get body size
bodySize := c.Writer.Size()
// Build full path with query string
if raw != "" {
path = path + "?" + raw
}
// Log structured information
log.Printf("REQUEST: method=%s path=%s status=%d latency=%v client_ip=%s body_size=%d user_agent=\"%s\"",
method,
path,
statusCode,
latency,
clientIP,
bodySize,
c.Request.UserAgent(),
)
// Log errors if any
if len(c.Errors) > 0 {
log.Printf("ERRORS: %v", c.Errors.String())
}
}
}
// formatBodySize formats body size in human readable format
func formatBodySize(size int) string {
if size == 0 {
return "0B"
}
const unit = 1024
if size < unit {
return fmt.Sprintf("%dB", size)
}
div, exp := int64(unit), 0
for n := size / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f%cB", float64(size)/float64(div), "KMGTPE"[exp])
}