Middleware Options
5 minute read
Complete reference for MiddlewareOption functions used to configure the HTTP metrics middleware.
Overview
Middleware options configure which paths to exclude from metrics collection and which headers to record.
handler := metrics.Middleware(recorder,
metrics.WithExcludePaths("/health", "/metrics"),
metrics.WithExcludePrefixes("/debug/"),
metrics.WithExcludePatterns(`^/admin/.*`),
metrics.WithHeaders("X-Request-ID"),
)(httpHandler)
Path Exclusion Options
WithExcludePaths
func WithExcludePaths(paths ...string) MiddlewareOption
Excludes exact paths from metrics collection.
Parameters:
paths ...string- Exact paths to exclude
Example:
handler := metrics.Middleware(recorder,
metrics.WithExcludePaths("/health", "/metrics", "/ready"),
)(mux)
Use Cases:
- Health check endpoints.
- Metrics endpoints.
- Readiness and liveness probes.
Behavior:
- Matches exact path only.
- Case-sensitive.
- Does not match path prefixes.
Examples:
// Excluded paths
/health ✓ excluded
/metrics ✓ excluded
/ready ✓ excluded
// Not excluded (not exact matches)
/health/status ✗ not excluded
/healthz ✗ not excluded
/api/metrics ✗ not excluded
WithExcludePrefixes
func WithExcludePrefixes(prefixes ...string) MiddlewareOption
Excludes all paths with specific prefixes from metrics collection.
Parameters:
prefixes ...string- Path prefixes to exclude
Example:
handler := metrics.Middleware(recorder,
metrics.WithExcludePrefixes("/debug/", "/internal/", "/_/"),
)(mux)
Use Cases:
- Debug endpoints (
/debug/pprof/,/debug/vars/) - Internal APIs (
/internal/) - Administrative paths (
/_/)
Behavior:
- Matches any path starting with prefix
- Case-sensitive
- Include trailing slash for directory prefixes
Examples:
// With prefix "/debug/"
/debug/pprof/heap ✓ excluded
/debug/vars ✓ excluded
/debug/ ✓ excluded
// Not excluded
/debuginfo ✗ not excluded (no slash)
/api/debug ✗ not excluded (doesn't start with prefix)
WithExcludePatterns
func WithExcludePatterns(patterns ...string) MiddlewareOption
Excludes paths matching regex patterns from metrics collection.
Parameters:
patterns ...string- Regular expression patterns
Example:
handler := metrics.Middleware(recorder,
metrics.WithExcludePatterns(
`^/v[0-9]+/internal/.*`, // /v1/internal/*, /v2/internal/*
`^/api/[0-9]+$`, // /api/123, /api/456
`^/admin/.*`, // /admin/*
),
)(mux)
Use Cases:
- Version-specific internal paths
- High-cardinality routes (IDs in path)
- Pattern-based exclusions
Behavior:
- Uses Go’s
regexppackage - Matches full path
- Case-sensitive (use
(?i)for case-insensitive)
Examples:
// Pattern: `^/v[0-9]+/internal/.*`
/v1/internal/metrics ✓ excluded
/v2/internal/debug ✓ excluded
// Not excluded
/internal/api ✗ not excluded (no version)
/api/v1/internal ✗ not excluded (doesn't start with /v)
// Pattern: `^/api/[0-9]+$`
/api/123 ✓ excluded
/api/456 ✓ excluded
// Not excluded
/api/users ✗ not excluded (not numeric)
/api/123/details ✗ not excluded (has suffix)
Pattern Tips:
// Anchors
^ // Start of path
$ // End of path
// Character classes
[0-9] // Any digit
[a-z] // Any lowercase letter
. // Any character
\d // Any digit
// Quantifiers
* // Zero or more
+ // One or more
? // Zero or one
{n} // Exactly n
// Grouping
(...) // Group
// Case-insensitive
(?i)pattern // Case-insensitive match
Combining Exclusions
Use multiple exclusion options together:
handler := metrics.Middleware(recorder,
// Exact paths
metrics.WithExcludePaths("/health", "/metrics", "/ready"),
// Prefixes
metrics.WithExcludePrefixes("/debug/", "/internal/", "/_/"),
// Patterns
metrics.WithExcludePatterns(
`^/v[0-9]+/internal/.*`,
`^/api/users/[0-9]+$`, // User IDs in path
),
)(mux)
Evaluation Order:
- Exact paths (
WithExcludePaths) - Prefixes (
WithExcludePrefixes) - Patterns (
WithExcludePatterns)
If any exclusion matches, the path is excluded.
Header Recording Options
WithHeaders
func WithHeaders(headers ...string) MiddlewareOption
Records specific HTTP headers as metric attributes.
Parameters:
headers ...string- Header names to record
Example:
handler := metrics.Middleware(recorder,
metrics.WithHeaders("X-Request-ID", "X-Correlation-ID", "X-Client-Version"),
)(mux)
Behavior:
- Headers recorded as metric attributes
- Header names normalized (lowercase, hyphens to underscores)
- Sensitive headers automatically filtered
Header Normalization:
// Original header → Metric attribute
X-Request-ID → x_request_id
X-Correlation-ID → x_correlation_id
Content-Type → content_type
User-Agent → user_agent
Example Metric:
http_requests_total{
method="GET",
path="/api/users",
status="200",
x_request_id="abc123",
x_correlation_id="def456"
} 1
Sensitive Header Filtering
The middleware automatically filters sensitive headers, even if explicitly requested.
Always Filtered Headers:
AuthorizationCookieSet-CookieX-API-KeyX-Auth-TokenProxy-AuthorizationWWW-Authenticate
Example:
// Only X-Request-ID will be recorded
// Authorization and Cookie are automatically filtered
handler := metrics.Middleware(recorder,
metrics.WithHeaders(
"Authorization", // ✗ Filtered (sensitive)
"X-Request-ID", // ✓ Recorded
"Cookie", // ✗ Filtered (sensitive)
"X-Correlation-ID", // ✓ Recorded
),
)(mux)
Why Filter?
- Prevent credential leaks in metrics
- Avoid exposing API keys
- Comply with security policies
- Prevent compliance violations
Configuration Examples
Basic Health Check Exclusion
handler := metrics.Middleware(recorder,
metrics.WithExcludePaths("/health", "/ready"),
)(mux)
Development/Debug Exclusion
handler := metrics.Middleware(recorder,
metrics.WithExcludePaths("/health", "/metrics"),
metrics.WithExcludePrefixes("/debug/", "/_/"),
)(mux)
High-Cardinality Path Exclusion
handler := metrics.Middleware(recorder,
// Exclude paths with IDs to avoid high cardinality
metrics.WithExcludePatterns(
`^/api/users/[0-9]+$`, // /api/users/123
`^/api/orders/[a-z0-9-]+$`, // /api/orders/abc-123
`^/files/[^/]+$`, // /files/{id}
),
)(mux)
Request Tracing
handler := metrics.Middleware(recorder,
metrics.WithExcludePaths("/health"),
metrics.WithHeaders("X-Request-ID", "X-Correlation-ID", "X-Trace-ID"),
)(mux)
Production Configuration
handler := metrics.Middleware(recorder,
// Exclude operational endpoints
metrics.WithExcludePaths(
"/health",
"/ready",
"/metrics",
"/favicon.ico",
),
// Exclude administrative paths
metrics.WithExcludePrefixes(
"/debug/",
"/internal/",
"/_/",
),
// Exclude high-cardinality routes
metrics.WithExcludePatterns(
`^/api/v[0-9]+/internal/.*`,
`^/api/users/[0-9]+$`,
`^/api/orders/[a-z0-9-]+$`,
),
// Record tracing headers
metrics.WithHeaders(
"X-Request-ID",
"X-Correlation-ID",
"X-Client-Version",
),
)(mux)
Best Practices
Path Exclusions
DO:
- Exclude health and readiness checks
- Exclude metrics endpoints
- Exclude high-cardinality paths (IDs)
- Exclude debug and administrative paths
DON’T:
- Over-exclude (you need some metrics!)
- Exclude business-critical endpoints
- Use overly broad patterns
Header Recording
DO:
- Record low-cardinality headers only
- Use headers for request tracing
- Consider privacy implications
DON’T:
- Record sensitive headers (automatically filtered)
- Record high-cardinality headers (user IDs, timestamps)
- Record excessive headers (increases metric cardinality)
Cardinality Management
High cardinality leads to:
- Excessive memory usage
- Slow query performance
- Storage bloat
Low Cardinality (Good):
// Headers with limited values
X-Client-Version: v1.0, v1.1, v2.0 (3 values)
X-Region: us-east-1, eu-west-1 (2 values)
High Cardinality (Bad):
// Headers with unbounded values
X-Request-ID: abc123, def456, ... (millions of values)
X-Timestamp: 2025-01-18T10:30:00Z (always unique)
X-User-ID: user123, user456, ... (millions of values)
Performance Considerations
Path Evaluation Overhead
- Exact paths: O(1) hash lookup
- Prefixes: O(n) prefix checks (n = number of prefixes)
- Patterns: O(n) regex matches (n = number of patterns)
Recommendation: Use exact paths when possible for best performance.
Header Recording Impact
Each header adds:
- Additional metric attribute
- Increased metric cardinality
- Higher memory usage
Recommendation: Only record necessary headers.
Troubleshooting
Path Not Excluded
Check:
- Path is exact match (use
WithExcludePaths) - Prefix includes trailing slash
- Pattern uses correct regex syntax
- Pattern is anchored (
^and$)
Header Not Recorded
Check:
- Header name is correct (case-insensitive)
- Header is not in sensitive list
- Header is present in request
High Memory Usage
Check:
- Too many unique paths (exclude high-cardinality routes)
- Too many header combinations
- Recording high-cardinality headers
Next Steps
- See API Reference for middleware function
- Read Middleware Guide for detailed examples
- Check Configuration for histogram tuning
- Review Troubleshooting for common issues
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.