Какие подходы и инструменты используются в Go для сбора и экспорта метрик приложения?

Ответ

В Go для сбора и экспорта метрик приложения существуют два основных подхода: использование стандартной библиотеки expvar и интеграция с системой мониторинга Prometheus, которая является индустриальным стандартом.

1. Стандартная библиотека: expvar

Пакет expvar предоставляет простой способ для экспорта переменных в формате JSON через HTTP. Он хорошо подходит для быстрой отладки и простых случаев.

  • Плюсы: Встроен в стандартную библиотеку, очень прост в использовании.
  • Минусы: Ограниченный функционал, нет типов метрик (только числа и строки), нет поддержки лейблов, что затрудняет агрегацию.

Пример использования:

import (
    "expvar"
    "fmt"
    "net/http"
)

var (
    // Создаем счетчик запросов
    requests = expvar.NewInt("http_requests_total")
)

func handler(w http.ResponseWriter, r *http.Request) {
    requests.Add(1) // Увеличиваем счетчик при каждом запросе
    fmt.Fprintln(w, "Hello, world!")
}

func main() {
    http.HandleFunc("/", handler)
    // Метрики автоматически становятся доступны по эндпоинту /debug/vars
    http.ListenAndServe(":8080", nil)
}

После запуска метрики можно посмотреть, перейдя по адресу http://localhost:8080/debug/vars.

2. Индустриальный стандарт: Prometheus

Для production-систем предпочтительным является использование библиотеки prometheus/client_golang. Она предоставляет мощную модель данных с поддержкой различных типов метрик и лейблов.

  • Плюсы: Мощная модель данных (лейблы), стандартизированные типы метрик, интеграция с экосистемой Prometheus (Grafana, Alertmanager).
  • Минусы: Требует подключения сторонней зависимости.

Ключевые типы метрик:

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

Пример использования:

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

var (
    // Создаем счетчик с лейблом для HTTP-метода
    httpRequestsTotal = promauto.NewCounterVec(prometheus.CounterOpts{
        Name: "http_requests_total",
        Help: "Total number of http requests",
    }, []string{"method"})
)

func handler(w http.ResponseWriter, r *http.Request) {
    httpRequestsTotal.With(prometheus.Labels{"method": r.Method}).Inc()
    w.Write([]byte("OK"))
}

func main() {
    http.HandleFunc("/", handler)
    // Экспортируем метрики через стандартный эндпоинт /metrics
    http.Handle("/metrics", promhttp.Handler())

    http.ListenAndServe(":8080", nil)
}

Метрики будут доступны в текстовом формате Prometheus по адресу http://localhost:8080/metrics.