Какие знаешь Metric у Spring Boot?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Метрики в Spring Boot (Micrometer и Actuator)
Метрики — это количественные измерения поведения приложения (throughput, latency, error rates), необходимые для мониторинга, алертинга и отладки production систем. Spring Boot предоставляет встроенную поддержку через Micrometer и Actuator.
Основные компоненты
Micrometer — фасад для различных систем мониторинга (Prometheus, Grafana, Datadog, InfluxDB и др.). Spring Boot Actuator — встроенный модуль для сбора и предоставления метрик через HTTP endpoints.
Подключение
// pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
// Для Prometheus
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
Встроенные метрики Actuator
Spring Boot автоматически собирает следующие метрики:
JVM метрики:
jvm.memory.used— использование памяти (Heap/Non-Heap)jvm.gc.memory.allocated— выделено памяти для GCjvm.gc.max.data.size— максимум памяти для GCjvm.gc.pause— время пауз garbage collectionjvm.threads.live— количество активных потоковjvm.threads.peak— пик активных потоковjvm.classes.loaded— загруженные классы
HTTP метрики (Servlet):
http.server.requests— счетчик HTTP запросов с labels (method, uri, status)http.server.requests.max— максимальное время обработкиhttp.server.requests.active— активные запросы
Бизнес-метрики приложения:
process.uptime— время работы приложенияprocess.cpu.usage— использование CPUsystem.cpu.usage— CPU системы в целомsystem.memory.usage— использование системной памяти
Типы метрик Micrometer
1. Counter — монотонно растущий счетчик:
@Service
public class OrderService {
private final MeterRegistry meterRegistry;
private final AtomicInteger ordersCreated;
public OrderService(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
this.ordersCreated = meterRegistry.counter(
"orders.created",
"status", "total"
).count();
}
public void createOrder(Order order) {
// Бизнес-логика
meterRegistry.counter("orders.created", "status", "success").increment();
}
}
2. Gauge — текущее значение (не монотонный):
@Service
public class QueueService {
private final Queue<Task> taskQueue = new ConcurrentLinkedQueue<>();
private final MeterRegistry meterRegistry;
public QueueService(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
// Регистрируем gauge — текущий размер очереди
meterRegistry.gaugeCollectionSize(
"queue.size",
Tags.empty(),
taskQueue
);
}
}
3. Timer — измерение времени выполнения операции:
@Service
public class PaymentService {
private final MeterRegistry meterRegistry;
public void processPayment(Payment payment) {
// Способ 1: старый способ с Timer.Sample
Timer.Sample sample = Timer.start(meterRegistry);
try {
// Обработка платежа
callPaymentGateway(payment);
} finally {
sample.stop(Timer.builder("payment.processing.time")
.description("Время обработки платежа")
.publishPercentiles(0.5, 0.95, 0.99)
.register(meterRegistry));
}
// Способ 2: через аннотацию
}
// Способ 2: декоратор через аннотацию @Timed
@Timed(value = "payment.processing.time",
description = "Время обработки платежа")
public void processPaymentAnnotated(Payment payment) {
// Обработка платежа
}
}
4. Distribution Summary — распределение значений (без привязки ко времени):
@Service
public class FileUploadService {
private final MeterRegistry meterRegistry;
private final DistributionSummary uploadSize;
public FileUploadService(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
this.uploadSize = DistributionSummary.builder("file.upload.size")
.description("Размер загруженного файла в байтах")
.baseUnit("bytes")
.scale(1024.0) // переводим в KB
.register(meterRegistry);
}
public void uploadFile(byte[] content) {
uploadSize.record(content.length);
}
}
Собственные метрики через аннотацию
@Service
public class UserService {
// @Timed выполняет метрику автоматически
@Timed(value = "user.fetch",
description = "Время получения пользователя по ID")
public User getUserById(Long id) {
// Время выполнения метода автоматически записывается
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException(id));
}
}
Tags (теги/labels) для группировки
Метрики могут иметь теги для более детального анализа:
@Service
public class ApiService {
private final MeterRegistry meterRegistry;
public void handleRequest(String endpoint, int statusCode) {
meterRegistry.counter(
"api.requests",
"endpoint", endpoint, // group by endpoint
"status", String.valueOf(statusCode) // group by status
).increment();
}
}
// Результат в Prometheus:
// api_requests{endpoint="/users",status="200"} 150
// api_requests{endpoint="/users",status="404"} 5
// api_requests{endpoint="/orders",status="200"} 320
Endpoints Actuator
# Все доступные endpoints
GET /actuator
# Метрики (JSON)
GET /actuator/metrics
# Конкретная метрика
GET /actuator/metrics/jvm.memory.used
# Для Prometheus (текстовый формат)
GET /actuator/prometheus
# Здоровье приложения
GET /actuator/health
# Информация о приложении
GET /actuator/info
# Логирование
GET /actuator/loggers
POST /actuator/loggers/com.example
Конфигурация в application.yml
management:
endpoints:
web:
exposure:
include: prometheus,health,info,metrics
metrics:
distribution:
percentiles-histogram:
http.server.requests: true
slo:
http.server.requests: 100ms,500ms,1s
endpoint:
health:
show-details: when-authorized
Практический пример с Dashboard
@Service
public class AnalyticsService {
private final MeterRegistry meterRegistry;
public AnalyticsService(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
// Active users gauge
meterRegistry.gauge("users.active",
() -> userRepository.countActiveUsers());
// Revenue counter
meterRegistry.counter("revenue.total",
"currency", "USD");
// API latency timer
Timer.builder("api.latency")
.publishPercentiles(0.5, 0.95, 0.99)
.minimumExpectedValue(Duration.ofMillis(1))
.maximumExpectedValue(Duration.ofSeconds(10))
.register(meterRegistry);
}
public void recordPayment(BigDecimal amount) {
meterRegistry.counter("revenue.total",
"currency", "USD").increment(amount.doubleValue());
}
}
Интеграция с Prometheus и Grafana
- Prometheus скрейпит
/actuator/prometheusкаждые 15 секунд - Grafana создает дашборды на основе метрик
- Alerting правила срабатывают при превышении пороговых значений
Метрики в Spring Boot — это основа наблюдаемости (observability) современных приложений, позволяющая быстро обнаруживать проблемы и оптимизировать систему.