Gymterview
junior

Что такое метрики и какие типы метрик существуют?

Метрика — числовое значение, измеряемое в определённый момент времени, которое агрегируется и хранится как временной ряд (time series). Каждый временной ряд идентифицируется именем и набором лейблов (меток).

Пример
http_server_requests_seconds_count{method="GET", uri="/api/orders", status="200"} 1523
│                                  │                                                │
│ имя метрики                      │ лейблы (dimensions)                            │ значение

Основные типы метрик

Тип Описание Примеры Функции PromQL
Counter Монотонно возрастающее значение (сбрасывается в 0 при перезапуске) Количество HTTP-запросов, число ошибок rate(), increase()
Gauge Значение, которое может увеличиваться и уменьшаться Активные подключения, размер очереди, heap usage avg(), min(), max()
Histogram Распределение значений по бакетам Время ответа, размер запроса histogram_quantile()
Timer Counter + Histogram для измерения длительности Время обработки заказа rate(), histogram_quantile()
Примеры кода для каждого типа
// Counter
Counter orderCounter = Counter.builder("orders.created")
    .description("Total number of created orders")
    .tag("region", "eu")
    .register(meterRegistry);
orderCounter.increment();

// Gauge
Gauge.builder("queue.size", queue, Queue::size)
    .description("Current queue size")
    .register(meterRegistry);

// Histogram (DistributionSummary)
DistributionSummary summary = DistributionSummary.builder("order.amount")
    .description("Order amounts distribution")
    .baseUnit("rubles")
    .publishPercentiles(0.5, 0.95, 0.99)
    .publishPercentileHistogram()
    .register(meterRegistry);
summary.record(orderAmount);

// Timer
Timer timer = Timer.builder("order.processing.time")
    .description("Time to process an order")
    .publishPercentiles(0.5, 0.95, 0.99)
    .register(meterRegistry);
timer.record(() -> processOrder(order));

Методологии выбора метрик

RED-метод — для сервисов (запрос-ответ):

  • Rate — количество запросов в секунду
  • Errors — количество неудачных запросов в секунду
  • Duration — распределение времени ответа (гистограмма)

USE-метод — для ресурсов (CPU, память, диск, сеть):

  • Utilization — процент использования ресурса
  • Saturation — степень перегрузки (очередь ожидания)
  • Errors — количество ошибок ресурса

Бизнес-метрики vs Технические метрики

Бизнес-метрики Технические метрики
Количество заказов в минуту CPU utilization
Конверсия корзины JVM heap usage
Среднее время доставки HTTP response time
Выручка в реальном времени Connection pool utilization
Количество активных пользователей GC pause duration
Пример бизнес-метрики
@Service
public class PaymentService {
    private final Counter successPayments;
    private final Counter failedPayments;
    private final DistributionSummary paymentAmount;

    public PaymentService(MeterRegistry registry) {
        this.successPayments = Counter.builder("payments.success")
            .tag("provider", "stripe")
            .register(registry);
        this.failedPayments = Counter.builder("payments.failed")
            .tag("provider", "stripe")
            .register(registry);
        this.paymentAmount = DistributionSummary.builder("payments.amount")
            .baseUnit("kopecks")
            .publishPercentiles(0.5, 0.95)
            .register(registry);
    }

    public PaymentResult pay(PaymentRequest request) {
        try {
            PaymentResult result = processPayment(request);
            successPayments.increment();
            paymentAmount.record(request.getAmount());
            return result;
        } catch (PaymentException e) {
            failedPayments.increment();
            throw e;
        }
    }
}

Важное

  • Counter нельзя использовать для значений, которые уменьшаются (например, количество активных сессий — это Gauge).
  • При работе с Counter в Prometheus всегда используйте функцию rate() или increase(), а не абсолютное значение.
  • Перцентили нельзя агрегировать между инстансами: p99 от 5 инстансов — это не p99 системы. Для агрегации используйте гистограммы.
  • Лейблы с высокой кардинальностью (userId, requestId) убивают производительность Prometheus. Используйте лейблы с ограниченным набором значений.

Частые ошибки

  • Использование Gauge вместо Counter для подсчёта событий: при перезапуске теряется контекст, а rate() не работает корректно.
  • Высокая кардинальность лейблов: добавление userId или orderId как лейбла создаёт миллионы time series и перегружает хранилище.
  • Отсутствие бизнес-метрик: техническая команда мониторит только инфраструктуру, но не понимает, влияет ли деградация на бизнес.
  • Неправильный выбор бакетов гистограммы: дефолтные бакеты могут не подходить для конкретного SLA. Настраивайте serviceLevelObjectives().

Как используется в 2026

  • Micrometer 1.13+/2.x — стандарт для метрик в Spring-экосистеме, с нативной поддержкой OpenTelemetry.
  • Exemplars — связь метрик с трейсами. Prometheus поддерживает exemplars, позволяя «кликнуть» на spike в графике и перейти к конкретному трейсу.
  • Prometheus Native Histograms — новый формат гистограмм с автоматическим выбором бакетов и экономией места.
  • PromQL остаётся основным языком запросов; Grafana поддерживает визуальный query builder.

На собеседовании: важно не просто перечислить Counter/Gauge/Histogram, а объяснить, когда какой тип применять. Покажите знание RED/USE-методологий и упомяните, что бизнес-метрики часто важнее технических. Классическая ловушка — забыть про ограничение кардинальности лейблов.