Skip to main content

Overview

The requestlog middleware provides detailed structured logging of HTTP requests with configurable fields and formats. Use it when you need:
  • Structured request logs
  • Detailed debugging info
  • Log aggregation integration

Installation

import "github.com/go-mizu/mizu/middlewares/requestlog"

Quick Start

app := mizu.New()

app.Use(requestlog.New())

Configuration

Options

OptionTypeDefaultDescription
Logger*slog.LoggerDefaultStructured logger
Levelslog.LevelInfoLog level
Fields[]stringStandardFields to log
Skipfunc(*mizu.Ctx) boolnilSkip logging

Examples

Default Logging

app.Use(requestlog.New())

With slog

logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))

app.Use(requestlog.WithLogger(logger))

Custom Fields

app.Use(requestlog.WithOptions(requestlog.Options{
    Fields: []string{
        "method",
        "path",
        "status",
        "latency",
        "ip",
        "user_agent",
    },
}))

Skip Health Checks

app.Use(requestlog.WithOptions(requestlog.Options{
    Skip: func(c *mizu.Ctx) bool {
        return c.Request().URL.Path == "/health"
    },
}))

Error Level for Errors

app.Use(requestlog.WithOptions(requestlog.Options{
    LevelFunc: func(status int) slog.Level {
        if status >= 500 {
            return slog.LevelError
        }
        if status >= 400 {
            return slog.LevelWarn
        }
        return slog.LevelInfo
    },
}))

Log Output

{
    "time": "2024-01-15T10:30:00Z",
    "level": "INFO",
    "msg": "request",
    "method": "GET",
    "path": "/api/users",
    "status": 200,
    "latency": "1.234ms",
    "ip": "192.168.1.1",
    "user_agent": "Mozilla/5.0..."
}

API Reference

Functions

// New creates request log middleware
func New() mizu.Middleware

// WithLogger creates with custom logger
func WithLogger(logger *slog.Logger) mizu.Middleware

// WithOptions creates with configuration
func WithOptions(opts Options) mizu.Middleware

Technical Details

Implementation

The requestlog middleware is built on Go’s log/slog package and provides structured logging with the following key features:
  • Timing: Uses time.Now() and time.Since() to measure request duration with nanosecond precision
  • Skip Logic: Pre-computes skip paths and methods into maps for O(1) lookup performance
  • Body Preservation: Reads request body using io.LimitReader and restores it with io.NopCloser(bytes.NewReader(body)) to allow downstream handlers to access it
  • Header Redaction: Maintains a map of sensitive header names for constant-time redaction checks
  • Default Values: Automatically sets default logger (text handler to stdout), max body size (4KB), and sensitive headers (Authorization, Cookie, X-API-Key)

Logged Fields

The middleware logs the following fields for each request:
  • method: HTTP method (GET, POST, etc.)
  • path: Request URL path
  • remote_addr: Client remote address
  • query: Raw query string (only if present)
  • headers: Request headers (only if LogHeaders: true)
  • body: Request body up to MaxBodySize (only if LogBody: true)
  • duration: Request processing duration
  • error: Error message (only if request returns an error)

Error Handling

When a request handler returns an error:
  • The error is logged at ERROR level with all request attributes
  • The error is propagated to the next middleware (not swallowed)
  • Request duration is still calculated and logged

Security Considerations

Sensitive Data Protection

The middleware automatically redacts sensitive headers to prevent credential leakage:
  • Default sensitive headers: Authorization, Cookie, X-API-Key
  • Custom sensitive headers can be configured via SensitiveHeaders option
  • Redacted headers show [REDACTED] in logs

Body Logging Risks

When LogBody: true:
  • Request bodies may contain passwords, tokens, or PII
  • Body size is limited by MaxBodySize (default 4KB) to prevent memory exhaustion
  • Consider using skip logic for authentication endpoints
  • Review compliance requirements (GDPR, HIPAA, etc.) before enabling

Best Practices

  • Use structured logging for aggregation
  • Skip noisy endpoints
  • Include request IDs for correlation
  • Set appropriate log levels
  • Be cautious with LogBody on production systems
  • Configure SensitiveHeaders for your application’s needs
  • Use SkipPaths for health checks and metrics endpoints
  • Set reasonable MaxBodySize limits to prevent memory issues

Testing

The requestlog middleware includes comprehensive test coverage:
Test CaseDescriptionExpected Behavior
TestNewTests basic middleware creation and loggingLogs method and path for standard requests
TestWithOptions_LogHeadersTests header logging functionalityIncludes headers in log output when LogHeaders: true
TestWithOptions_LogBodyTests body logging functionalityIncludes request body in log output when LogBody: true
TestWithOptions_SkipPathsTests path-based skip logicSkips logging for configured paths (e.g., /health)
TestWithOptions_SkipMethodsTests method-based skip logicSkips logging for configured HTTP methods (e.g., OPTIONS)
TestWithOptions_SensitiveHeadersTests header redactionRedacts sensitive headers showing [REDACTED] instead of actual values
TestFullTests full logging modeLogs both headers and body when both options are enabled
TestQueryParamsTests query parameter loggingIncludes query parameters in log output when present
TestBodyPreservedTests body preservation for downstream handlersEnsures request body remains readable by handlers after logging