Agent skill
python-micrometer-cardinality-control
Prevent OutOfMemoryError from unbounded metric tags by implementing cardinality limits. Use when adding tags to Micrometer metrics, normalizing URIs or IDs to bounded categories, monitoring metric explosion, or avoiding high-cardinality fields like user IDs and request IDs. Critical for production microservices in GKE with cost-sensitive monitoring backends.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/python-micrometer-cardinality-control
SKILL.md
Micrometer Cardinality Control
Quick Start
For any metric with dynamic tags, apply this pattern:
// ❌ Dangerous: unbounded cardinality
.tag("supplier.id", supplierId) // 10,000+ unique values
// ✅ Safe: normalized to bounded categories
.tag("supplier.category", normalizeSupplier(supplier)) // 5-10 values
private String normalizeSupplier(Supplier s) {
if (s.isTopTier()) return "tier1";
if (s.isDirectSupplier()) return "direct";
return "standard";
}
When to Use
- Add tags to metrics (ensure bounded cardinality)
- Normalize high-cardinality data (URIs, IDs)
- Prevent OutOfMemoryError from metric explosion
- Control monitoring costs
- Debug metric growth
When NOT to use:
- Truly unbounded data (use distributed tracing)
- Per-request details (use structured logging)
Cardinality Rules
Safe Tags (Low Cardinality)
// ✅ HTTP method (4-10 values)
.tag("method", "GET")
// ✅ Status class (5 values)
.tag("status.class", "2xx")
// ✅ Environment (3-5 values)
.tag("env", "production")
Dangerous Tags (High Cardinality)
// ❌ User ID (millions) → Use tracing
.tag("user.id", userId)
// ❌ Request ID (infinite) → Use tracing
.tag("request.id", requestId)
// ❌ Full URI → Normalize!
.tag("uri", "/api/charges?supplier=123")
Rule of Thumb:
- Safe per metric: < 1,000 combinations
- Safe application-wide: < 10,000 active metrics
Normalization Patterns
URI Normalization
@Bean
public MeterFilter uriNormalization() {
return MeterFilter.replaceTagValues("uri", uri -> {
// Strip query parameters
int queryIndex = uri.indexOf('?');
if (queryIndex > 0) uri = uri.substring(0, queryIndex);
// Replace IDs: /charges/123 → /charges/{id}
return uri.replaceAll("/\\d+", "/{id}")
.replaceAll("/[a-f0-9-]{36}", "/{uuid}");
});
}
Business Category Normalization
private String normalizeSupplier(String supplierId) {
Supplier supplier = supplierRepository.findById(supplierId);
if (supplier.getAnnualVolume() > 1_000_000) return "enterprise";
if (supplier.getAnnualVolume() > 100_000) return "mid-market";
if (supplier.isDirect()) return "direct";
return "standard";
}
Cardinality Limits
@Bean
public MeterFilter cardinalityLimiter() {
// Limit unique URIs to 100
return MeterFilter.maximumAllowableTags(
"http.server.requests",
"uri",
100,
MeterFilter.deny() // Deny new meters after limit
);
}
Monitor Cardinality
@Component
public class CardinalityMonitor {
private final MeterRegistry registry;
@Scheduled(fixedRate = 60_000)
public void monitorMetricCount() {
int meterCount = registry.getMeters().size();
if (meterCount > 8000) {
log.error("CRITICAL: {} metrics (threshold 8000)", meterCount);
}
Gauge.builder("micrometer.meter.count", () -> meterCount)
.register(registry);
}
}
Alternatives to High-Cardinality Tags
Use Distributed Tracing
// Store user ID in span, NOT metrics
span.setAttribute("user.id", userId);
// Metrics use only bounded tags
Timer.builder("charge.processing")
.tag("status", "processing") // bounded
.register(registry);
Use Structured Logging
// Add to MDC for logging, NOT metrics
MDC.put("user.id", userId);
Requirements
- Spring Boot 2.1+
- spring-boot-starter-actuator
- Java 11+
- For tracing: micrometer-tracing-bridge-otel
Anti-Patterns
// ❌ NEVER add unbounded tags
.tag("user.id", userId)
.tag("request.id", requestId)
.tag("timestamp", Instant.now())
// ✅ DO normalize to bounded categories
.tag("customer.tier", normalizeCustomer(customer))
.tag("request.type", normalizeRequest(request))
See Also
- python-micrometer-core - Meter types
- python-micrometer-business-metrics - Business KPIs
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?