← Назад к вопросам

Как собирать метрики с помощью Prometheus?

2.0 Middle🔥 232 комментариев
#Observability

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Сбор метрик с помощью Prometheus

Prometheus — это мониторинговая система с открытым исходным кодом, которая собирает метрики по модели pull-based (запрос данных агентом). Для сбора метрик из Go-приложений используется клиентская библиотека prometheus/client_golang.

Основные шаги настройки

1. Установка и импорт библиотеки

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

2. Определение метрик Существует четыре основных типа метрик:

  • Counter — монотонно возрастающий счетчик
  • Gauge — значение, которое может увеличиваться и уменьшаться
  • Histogram — выборки наблюдений (обычно длительности запросов или размеры ответов)
  • Summary — аналогичен гистограмме, но вычисляет квантили
var (
    // Создаем метрику типа Counter
    requestsTotal = prometheus.NewCounter(
        prometheus.CounterOpts{
            Name: "http_requests_total",
            Help: "Total number of HTTP requests",
        },
    )
    
    // Создаем метрику типа Gauge
    activeUsers = prometheus.NewGauge(
        prometheus.GaugeOpts{
            Name: "active_users",
            Help: "Number of active users",
        },
    )
    
    // Создаем метрику типа Histogram
    requestDuration = prometheus.NewHistogram(
        prometheus.HistogramOpts{
            Name:    "http_request_duration_seconds",
            Help:    "Duration of HTTP requests",
            Buckets: prometheus.DefBuckets, // стандартные bucket'ы
        },
    )
)

3. Регистрация метрик в реестре

func init() {
    // Регистрируем метрики в дефолтном реестре
    prometheus.MustRegister(requestsTotal)
    prometheus.MustRegister(activeUsers)
    prometheus.MustRegister(requestDuration)
    
    // Можно регистрировать сразу несколько метрик
    prometheus.MustRegister(prometheus.NewBuildInfoCollector())
}

4. Экспозиция метрик через HTTP endpoint

func main() {
    // Создаем endpoint для сбора метрик Prometheus
    http.Handle("/metrics", promhttp.Handler())
    
    // Пример обновления метрик
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // Увеличиваем счетчик запросов
        requestsTotal.Inc()
        
        // Измеряем длительность запроса
        timer := prometheus.NewTimer(requestDuration)
        defer timer.ObserveDuration()
        
        // Обновляем gauge
        activeUsers.Set(42)
        
        w.Write([]byte("Hello, Prometheus!"))
    })
    
    // Запускаем сервер
    http.ListenAndServe(":8080", nil)
}

Продвинутые техники

1. Метрики с labels (лейблами)

var (
    requestsByMethod = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "http_requests_by_method_total",
            Help: "Total HTTP requests by method",
        },
        []string{"method", "endpoint"}, // лейблы
    )
)

// Использование
requestsByMethod.WithLabelValues("GET", "/api/users").Inc()
requestsByMethod.WithLabelValues("POST", "/api/users").Add(2)

2. Кастомные коллекторы

type CustomCollector struct {
    customMetric prometheus.Gauge
}

func NewCustomCollector() *CustomCollector {
    return &CustomCollector{
        customMetric: prometheus.NewGauge(
            prometheus.GaugeOpts{
                Name: "custom_metric",
                Help: "A custom metric",
            },
        ),
    }
}

func (c *CustomCollector) Describe(ch chan<- *prometheus.Desc) {
    c.customMetric.Describe(ch)
}

func (c *CustomCollector) Collect(ch chan<- prometheus.Metric) {
    // Логика обновления метрики
    c.customMetric.Set(calculateValue())
    c.customMetric.Collect(ch)
}

3. Middleware для сбора метрик HTTP

func prometheusMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Создаем wrapped response writer для отслеживания статуса
        rw := NewResponseWriter(w)
        
        // Замеряем длительность
        timer := prometheus.NewTimer(requestDuration)
        defer timer.ObserveDuration()
        
        // Увеличиваем счетчики
        requestsTotal.Inc()
        requestsByMethod.WithLabelValues(r.Method, r.URL.Path).Inc()
        
        next.ServeHTTP(rw, r)
        
        // Метрика по кодам ответа
        statusCode := strconv.Itoa(rw.statusCode)
        requestsByStatus.WithLabelValues(statusCode, r.Method).Inc()
    })
}

Конфигурация Prometheus

prometheus.yml:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'go_application'
    static_configs:
      - targets: ['localhost:8080']
    metrics_path: '/metrics'

Практические рекомендации

  • Именование метрик: используйте snake_case, суффиксы _total, _seconds, _bytes
  • Лейблы: не создавайте кардинальность (высокую уникальность) лейблов
  • Производительность: используйте promauto для автоматической регистрации
var (
    metric = promauto.NewCounter(
        prometheus.CounterOpts{
            Name: "metric_name",
            Help: "Metric help",
        },
    )
)
  • Инструментация: используйте готовые инструменты для популярных библиотек
  • Pushgateway: для кратковременных задач используйте Pushgateway
import "github.com/prometheus/client_golang/prometheus/push"
pusher := push.New("http://pushgateway:9091", "job_name")
pusher.Collector(requestsTotal)
pusher.Push()

Сбор метрик с Prometheus в Go — это мощный и гибкий инструмент для мониторинга приложений, который при правильной настройке предоставляет глубокую видимость в работу системы и помогает быстро обнаруживать и диагностировать проблемы.