Какова роль метрик в приложении и для чего они используются?

Ответ

Метрики — это числовые данные, которые собираются в реальном времени для оценки производительности, надежности и общего состояния приложения. Они являются ключевым элементом для мониторинга и observability (наблюдаемости) системы.

Основные цели использования метрик:

  • Мониторинг производительности: Отслеживание ключевых показателей, таких как время ответа (latency), использование CPU и памяти, пропускная способность (RPS).
  • Обнаружение ошибок и аномалий: Быстрое выявление роста числа ошибок (например, HTTP 5xx), сбоев, утечек памяти.
  • Принятие бизнес-решений: Анализ поведения пользователей и популярности функций для дальнейшего развития продукта.
  • Планирование масштабирования: Понимание текущей нагрузки и трендов для своевременного добавления ресурсов.
  • Алертинг (Оповещения): Настройка пороговых значений, при превышении которых система автоматически уведомляет команду о проблемах.

Часто выделяют «Четыре золотых сигнала» (Google SRE), которые необходимо отслеживать в первую очередь:

  1. Latency (Задержка): Время, необходимое для обработки запроса.
  2. Traffic (Трафик): Нагрузка на систему (например, запросы в секунду).
  3. Errors (Ошибки): Частота возникновения ошибок.
  4. Saturation (Насыщенность): Насколько «загружен» сервис (например, утилизация CPU или заполненность очереди).

Пример сбора метрики в Go с помощью Prometheus:

import (
    "net/http"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
    // Определяем метрику типа Counter
    httpRequestsTotal = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "http_requests_total",
            Help: "Total number of HTTP requests",
        },
        []string{"method", "path"}, // Метки для детализации
    )
)

// init() вызывается автоматически при инициализации пакета
func init() {
    // Регистрируем метрику в Prometheus
    prometheus.MustRegister(httpRequestsTotal)
}

func myHandler(w http.ResponseWriter, r *http.Request) {
    // Увеличиваем счетчик для текущего метода и пути
    httpRequestsTotal.WithLabelValues(r.Method, r.URL.Path).Inc()
    w.Write([]byte("Hello, World!"))
}

func main() {
    http.HandleFunc("/hello", myHandler)
    // Отдаем метрики по эндпоинту /metrics
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":8080", nil)
}