Metrics & Monitoring
Definition

Metric Types
// COUNTER: Cumulative value that only goes up
// Use for: Total requests, errors, bytes sent
Counter requestsTotal = Counter.builder("http_requests_total")
.tag("method", "POST")
.tag("path", "/orders")
.register(registry);
requestsTotal.increment();
// GAUGE: Value that can go up or down
// Use for: Current connections, queue size, temperature
Gauge.builder("active_connections", connectionPool, Pool::getActiveCount)
.register(registry);
// HISTOGRAM: Distribution of values
// Use for: Request latency, response size
Timer requestLatency = Timer.builder("http_request_duration_seconds")
.publishPercentiles(0.5, 0.95, 0.99)
.register(registry);
requestLatency.record(() -> {
handleRequest();
});
// SUMMARY: Similar to histogram, calculated client-side
// Pre-computed percentiles, less server work
// METRIC NAMING CONVENTIONS (Prometheus style)
// - snake_case
// - Include unit: _seconds, _bytes, _total
// - Use _total suffix for counters
// Good names:
http_requests_total
http_request_duration_seconds
db_connections_active
queue_messages_pending
// Bad names:
requestCount
latency
connections
Common Metrics
// APPLICATION METRICS
// HTTP Requests
@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public Object measureEndpoint(ProceedingJoinPoint pjp) throws Throwable {
Timer.Sample sample = Timer.start(registry);
String outcome = "success";
try {
return pjp.proceed();
} catch (Exception e) {
outcome = "error";
throw e;
} finally {
sample.stop(Timer.builder("http_request_duration_seconds")
.tag("method", getMethod(pjp))
.tag("path", getPath(pjp))
.tag("outcome", outcome)
.register(registry));
}
}
// Database Queries
Timer.builder("db_query_duration_seconds")
.tag("query", "findUserById")
.register(registry)
.record(() -> userRepository.findById(id));
// External Service Calls
Timer.builder("external_service_duration_seconds")
.tag("service", "payment-gateway")
.tag("operation", "charge")
.register(registry);
// Business Metrics
Counter.builder("orders_created_total")
.tag("product_type", productType)
.register(registry).increment();
Gauge.builder("inventory_level", inventory, Inventory::getCount)
.tag("product_id", productId)
.register(registry);
// JVM METRICS (usually auto-collected)
// - jvm_memory_used_bytes
// - jvm_gc_pause_seconds
// - jvm_threads_current
// - process_cpu_usage
Dashboards & Alerting

Monitoring Architecture

Tips & Tricks
