Files
goplt/internal/logger/middleware.go
0x1d 0bfdb2c2d7
Some checks failed
CI / Test (pull_request) Successful in 1m43s
CI / Lint (pull_request) Failing after 27s
CI / Build (pull_request) Failing after 13s
CI / Format Check (pull_request) Successful in 2s
Add comprehensive test suite for current implementation
- Add tests for internal/config package (90.9% coverage)
  - Test all viperConfig getter methods
  - Test LoadConfig with default and environment-specific configs
  - Test error handling for missing config files

- Add tests for internal/di package (88.1% coverage)
  - Test Container lifecycle (NewContainer, Start, Stop)
  - Test providers (ProvideConfig, ProvideLogger, CoreModule)
  - Test lifecycle hooks registration
  - Include mock implementations for testing

- Add tests for internal/logger package (96.5% coverage)
  - Test zapLogger with JSON and console formats
  - Test all logging levels and methods
  - Test middleware (RequestIDMiddleware, LoggingMiddleware)
  - Test context helper functions
  - Include benchmark tests

- Update CI workflow to skip tests when no test files exist
  - Add conditional test execution based on test file presence
  - Add timeout for test execution
  - Verify build when no tests are present

All tests follow Go best practices with table-driven patterns,
parallel execution where safe, and comprehensive coverage.
2025-11-05 12:45:37 +01:00

93 lines
2.5 KiB
Go

package logger
import (
"context"
"git.dcentral.systems/toolz/goplt/pkg/logger"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
const (
// RequestIDHeader is the HTTP header name for request ID.
RequestIDHeader = "X-Request-ID"
)
// RequestIDMiddleware creates a Gin middleware that:
// 1. Generates a unique request ID for each request (or uses existing one from header)
// 2. Adds the request ID to the request context
// 3. Adds the request ID to the response headers
// 4. Makes the request ID available for logging
func RequestIDMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// Check if request ID already exists in header
requestID := c.GetHeader(RequestIDHeader)
// Generate new request ID if not present
if requestID == "" {
requestID = uuid.New().String()
}
// Add request ID to context
ctx := context.WithValue(c.Request.Context(), RequestIDKey(), requestID)
c.Request = c.Request.WithContext(ctx)
// Add request ID to response header
c.Header(RequestIDHeader, requestID)
// Continue processing
c.Next()
}
}
// RequestIDFromContext extracts the request ID from the context.
func RequestIDFromContext(ctx context.Context) string {
if requestID, ok := ctx.Value(RequestIDKey()).(string); ok {
return requestID
}
return ""
}
// SetRequestID sets the request ID in the context.
func SetRequestID(ctx context.Context, requestID string) context.Context {
return context.WithValue(ctx, RequestIDKey(), requestID)
}
// SetUserID sets the user ID in the context.
func SetUserID(ctx context.Context, userID string) context.Context {
return context.WithValue(ctx, UserIDKey(), userID)
}
// UserIDFromContext extracts the user ID from the context.
func UserIDFromContext(ctx context.Context) string {
if userID, ok := ctx.Value(UserIDKey()).(string); ok {
return userID
}
return ""
}
// LoggingMiddleware creates a Gin middleware that logs HTTP requests.
// It uses the logger from the context and includes request ID.
func LoggingMiddleware(l logger.Logger) gin.HandlerFunc {
return func(c *gin.Context) {
// Get logger with context
log := l.WithContext(c.Request.Context())
// Log request
log.Info("HTTP request",
logger.String("method", c.Request.Method),
logger.String("path", c.Request.URL.Path),
logger.String("remote_addr", c.ClientIP()),
)
// Process request
c.Next()
// Log response
log.Info("HTTP response",
logger.Int("status", c.Writer.Status()),
logger.Int("size", c.Writer.Size()),
)
}
}