Что такое метрики в контексте backend-разработки?

Ответ

Метрика — это измеримая числовая величина, которая характеризует состояние, производительность или работоспособность системы в определённый момент времени. Сбор и анализ метрик является основой для мониторинга и observability.

Зачем нужны метрики?

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

Основные типы метрик (на примере Prometheus):

  • Counter: Монотонно растущий счётчик. Используется для подсчёта событий, например, общего числа HTTP-запросов.
  • Gauge: Значение, которое может как увеличиваться, так и уменьшаться. Например, текущее количество активных горутин или размер очереди.
  • Histogram: Распределение значений по бакетам (корзинам). Идеально для измерения времени ответа, позволяет вычислять перцентили (например, 99% запросов выполняются быстрее X мс).
  • Summary: Похоже на гистограмму, но вычисляет квантили на стороне клиента.

В Go для сбора метрик чаще всего используют библиотеку prometheus/client_golang для интеграции с системой мониторинга Prometheus.

Пример с Prometheus:

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

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

func init() {
    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)
}