Стандартные метрики Spring Boot (JVM, HTTP, datasource) — это база. Бизнес-метрики и метрики производительности конкретных операций пишутся вручную.
🔹 Решение
▪️ Базовые типы метрик
@Service
public class OrderMetrics {
private final Counter ordersCreated;
private final Counter ordersFailed;
private final Timer orderProcessingTime;
private final DistributionSummary orderAmountSummary;
private final AtomicInteger activeOrders;
public OrderMetrics(MeterRegistry registry) {
this.ordersCreated = Counter.builder("orders.created")
.description("Total orders created")
.tag("environment", "production")
.register(registry);
this.ordersFailed = Counter.builder("orders.failed")
.description("Total failed orders")
.register(registry);
this.orderProcessingTime = Timer.builder("orders.processing.time")
.description("Order processing duration")
.publishPercentiles(0.5, 0.95, 0.99)
.publishPercentileHistogram()
.sla(Duration.ofMillis(200), Duration.ofSeconds(1))
.register(registry);
this.orderAmountSummary = DistributionSummary.builder("orders.amount")
.description("Order amounts distribution")
.baseUnit("USD")
.publishPercentiles(0.5, 0.95)
.register(registry);
this.activeOrders = registry.gauge("orders.active",
new AtomicInteger(0));
}
public Order processOrder(OrderRequest request) {
activeOrders.incrementAndGet();
return orderProcessingTime.record(() -> {
try {
Order order = doProcess(request);
ordersCreated.increment();
orderAmountSummary.record(order.getAmount().doubleValue());
return order;
} catch (Exception e) {
ordersFailed.increment();
throw e;
} finally {
activeOrders.decrementAndGet();
}
});
}
}
▪️ Тег-стратегия для разрезания метрик
Timer.builder("external.api.calls")
.tag("service", "payment-gateway")
.tag("operation", "charge")
.tag("status", result.isSuccess() ? "success" : "failure")
.register(registry)
.record(duration);В Grafana это даёт возможность делать rate(external_api_calls_total{status="failure"}[5m]) и смотреть ошибки по сервисам отдельно.
▪️ application.yml для Prometheus
management:
endpoints:
web:
exposure:
include: health,info,prometheus,metrics
metrics:
distribution:
percentiles-histogram:
http.server.requests: true
slo:
http.server.requests: 50ms,200ms,500ms,1s
tags:
application: ${spring.application.name}
environment: ${APP_ENV:local}
publishPercentileHistogram() — ключевая настройка для Timer. Без неё Prometheus получает только count/sum и заранее вычисленные перцентили. С ней — полную гистограмму, из которой Prometheus сам считает перцентили через histogram_quantile().
Это важно при агрегации метрик с нескольких инстансов: заранее вычисленные перцентили нельзя корректно агрегировать, гистограммы — можно.
⚠️ Каждая уникальная комбинация тегов создаёт отдельный time series в Prometheus. Теги с высокой кардинальностью (userId, orderId, IP-адрес) убивают Prometheus. Теги должны иметь конечное и небольшое множество значений.
══════ Навигация ══════
Вакансии • Задачи • Собесы
🐸 Библиотека джависта
#Enterprise