Что такое метрики в контексте 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)
}

Ответ 18+ 🔞

А, вот и метрики подъехали, блядь! Ну, слушай, сейчас объясню, что это за зверь такой, чтоб ты не думал, что это какая-то высшая математика, нахуй.

Метрика — это, по сути, просто цифра, которая показывает, как там твоя система пыхтит в данный конкретный момент. Жива ли она ещё или уже накрылась медным тазом. Собираешь эти циферки, смотришь на них — вот тебе и мониторинг, и эта ваша обсервабильность, ёпта.

А нахуя это вообще нужно?

  • Чтоб не гадать на кофейной гуще: Вместо «вроде лагает» ты видишь: CPU грузится на 150%, память кончилась, и 10 тысяч соединений висят. Пиздец, а не система.
  • Понять, кто тут тормоз: Измерить, сколько времени запрос ползает по твоим сервисам, или сколько их в секунду прилетает. Если RPS упал в ноль — значит, что-то сломалось, а если латенси под 10 секунд — пора оптимизировать, а не в танчики играть.
  • Поймать за руку, когда всё ебнулось: Внезапно полезли вверх ошибки «500 Internal Server Error» или «503 Service Unavailable»? Вот это и есть сигнал, что пора бежать и тушить пожар, а не пить чай.
  • Не просрать все деньги на облако: Глядишь на графики, видишь тренд — нагрузка растёт. Значит, скоро серваки захлебнутся. Можно заранее докупить ресурсов, а не в панике ночью масштабировать, когда всё уже легло.

Какие они бывают, эти метрики? (На примере Прометея, конечно же):

  • Counter (Счётчик): Тупо растёт вверх. Раз — запрос, два — запрос. Используется, чтобы посчитать, сколько всего запросов было, например. Уменьшить его нельзя, только обнулить.
  • Gauge (Измеритель): А вот эта штука может и вверх, и вниз. Как температура или давление. Сколько сейчас горутин бегает, какая очередь накопилась.
  • Histogram (Гистограмма): О, это для крутых перформанс-инженеров! Раскидывает значения по корзиночкам. Позволяет посмотреть: «99% запросов выполняются быстрее 150 мс, а оставшийся 1% — ну, ебать его в сраку, они там по 5 секунд ползают».
  • Summary (Сводка): Похоже на гистограмму, но квантили считает на своей стороне, не загружая сервер.

В Го, само собой, для этого используют библиотечку prometheus/client_golang. Без неё никуда.

Смотри, как это выглядит в коде, чтоб ты не обосрался:

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

var (
    // Счётчик всех HTTP-запросов. Будем считать, кто и куда стучится.
    httpRequestsTotal = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "http_requests_total", // Имя метрики
            Help: "Total number of HTTP requests", // Подсказка для тех, кто забыл
        },
        []string{"method", "path"}, // Метки! Чтобы отдельно считать GET /api от POST /login
    )
)

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)
    // А это волшебный эндпоинт, по которому Прометей будет приходить и собирать все наши метрики.
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":8080", nil)
}

Вот и всё, гений. Запустил — и у тебя уже есть базовый мониторинг. А дальше только сложнее и интереснее, блядь. Главное — начать.