prometheus/client_golang для Go: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

prometheus/client_golang для Go: полное руководство

1. Что это и зачем нужна

Библиотека prometheus/client_golang — это официальный клиент для системы мониторинга Prometheus, написанный на языке Go. Она предоставляет разработчикам мощный и гибкий инструментарий для сбора, агрегации и экспорта метрик из Go-приложений. Prometheus, в свою очередь, является одной из самых популярных систем сбора метрик и мониторинга в мире DevOps и облачных технологий, особенно в экосистеме Kubernetes.

Зачем она нужна? В современной микросервисной архитектуре критически важно понимать, как работает ваше приложение: сколько запросов оно обрабатывает, какова задержка ответов, сколько памяти потребляет, как часто возникают ошибки. prometheus/client_golang позволяет легко инструментировать ваш код, добавляя эти метрики. Библиотека автоматически предоставляет эндпоинт (обычно /metrics), который Prometheus может "скрейпить" (опрашивать) по расписанию. Это дает вам возможность строить дашборды в Grafana, настраивать алерты и получать полную картину здоровья вашего сервиса.

Ключевые возможности библиотеки включают поддержку четырех основных типов метрик Prometheus: Counter (счетчик, который только увеличивается), Gauge (измеритель, который может как увеличиваться, так и уменьшаться), Histogram (гистограмма для измерения распределения значений, например, времени ответа) и Summary (аналогично гистограмме, но вычисляет квантили на стороне клиента). Кроме того, библиотека предоставляет удобные "коллекторы" для стандартных метрик Go (память, горутины, GC) и HTTP-сервера.

2. Установка

Установка библиотеки производится стандартной командой go get. Убедитесь, что у вас установлен Go версии 1.16 или выше (рекомендуется последняя стабильная версия).

go get github.com/prometheus/client_golang/prometheus
go get github.com/prometheus/client_golang/prometheus/promhttp

После выполнения этих команд в вашем go.mod появится зависимость. Пакет prometheus содержит ядро библиотеки (типы метрик, регистрацию), а promhttp предоставляет HTTP-обработчик для экспорта метрик.

3. Быстрый старт — минимальный рабочий пример

Давайте создадим минимальное приложение, которое будет экспортировать одну метрику — количество обработанных HTTP-запросов.

package main

import (
    "fmt"
    "net/http"

    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
    // Определяем счетчик запросов с меткой "path"
    requestsTotal = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "http_requests_total",
            Help: "Total number of HTTP requests.",
        },
        []string{"path"},
    )
)

func init() {
    // Регистрируем метрику в глобальном реестре
    prometheus.MustRegister(requestsTotal)
}

func main() {
    // Обработчик для основного пути
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // Инкрементируем счетчик для пути "/"
        requestsTotal.WithLabelValues("/").Inc()
        fmt.Fprintf(w, "Hello, World!")
    })

    // Обработчик для эндпоинта метрик Prometheus
    http.Handle("/metrics", promhttp.Handler())

    fmt.Println("Server started on :8080")
    http.ListenAndServe(":8080", nil)
}

Запустите этот код (go run main.go), откройте в браузере http://localhost:8080/metrics. Вы увидите множество метрик, включая нашу http_requests_total. Каждый раз, когда вы переходите на http://localhost:8080/, значение счетчика будет увеличиваться.

4. Основные методы/функции/классы

4.1. prometheus.NewCounter / prometheus.NewCounterVec

Сигнатура:

func NewCounter(opts CounterOpts) Counter
func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec

Что делает: Создает метрику типа Counter (счетчик). Counter — это монотонно возрастающее значение, которое сбрасывается только при перезапуске приложения. Используется для подсчета событий (запросы, ошибки, задачи). NewCounterVec создает семейство счетчиков, различающихся по меткам (labels).

Пример:

// Простой счетчик
var myCounter = prometheus.NewCounter(prometheus.CounterOpts{
    Name: "my_custom_counter",
    Help: "A simple counter that never decreases.",
})

// Счетчик с метками
var httpErrors = prometheus.NewCounterVec(
    prometheus.CounterOpts{
        Name: "http_errors_total",
        Help: "Total number of HTTP errors by status code.",
    },
    []string{"status_code"},
)

func handleRequest() {
    // Инкрементируем простой счетчик
    myCounter.Inc()
    // Инкрементируем счетчик с меткой "500"
    httpErrors.WithLabelValues("500").Inc()
}

4.2. prometheus.NewGauge / prometheus.NewGaugeVec

Сигнатура:

func NewGauge(opts GaugeOpts) Gauge
func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec

Что делает: Создает метрику типа Gauge (измеритель). Gauge представляет собой числовое значение, которое может произвольно увеличиваться и уменьшаться. Идеально подходит для измерения текущих значений, таких как температура, использование памяти, количество активных соединений.

Пример:

var currentConnections = prometheus.NewGauge(prometheus.GaugeOpts{
    Name: "active_connections",
    Help: "Current number of active connections.",
})

var memoryUsage = prometheus.NewGaugeVec(
    prometheus.GaugeOpts{
        Name: "memory_usage_bytes",
        Help: "Memory usage in bytes by type.",
    },
    []string{"type"},
)

func updateMetrics() {
    // Устанавливаем значение
    currentConnections.Set(42)
    // Увеличиваем на 1
    currentConnections.Inc()
    // Уменьшаем на 5
    currentConnections.Sub(5)
    // Устанавливаем значение для метки "heap"
    memoryUsage.WithLabelValues("heap").Set(1024 * 1024 * 50) // 50 MB
}

4.3. prometheus.NewHistogram / prometheus.NewHistogramVec

Сигнатура:

func NewHistogram(opts HistogramOpts) Histogram
func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec

Что делает: Создает метрику типа Histogram (гистограмма). Гистограмма используется для измерения распределения значений (например, времени ответа, размера запроса). Она подсчитывает количество наблюдений в предопределенных "ведрах" (buckets). Prometheus на основе гистограммы может вычислять квантили (p50, p99).

Пример:

var requestDuration = prometheus.NewHistogram(prometheus.HistogramOpts{
    Name:    "http_request_duration_seconds",
    Help:    "Histogram of HTTP request durations.",
    Buckets: prometheus.DefBuckets, // Стандартные ведра: .005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10
})

var requestDurationByPath = prometheus.NewHistogramVec(
    prometheus.HistogramOpts{
        Name:    "http_request_duration_seconds_by_path",
        Help:    "Histogram of HTTP request durations by path.",
        Buckets: []float64{.01, .05, .1, .5, 1, 5}, // Пользовательские ведра
    },
    []string{"path"},
)

func recordRequest(path string, duration float64) {
    requestDuration.Observe(duration)
    requestDurationByPath.WithLabelValues(path).Observe(duration)
}

4.4. prometheus.NewSummary / prometheus.NewSummaryVec

Сигнатура:

func NewSummary(opts SummaryOpts) Summary
func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec

Что делает: Создает метрику типа Summary (сводка). Summary очень похожа на Histogram, но вычисляет квантили (p50, p90, p99) на стороне клиента (в вашем приложении), а не на стороне сервера Prometheus. Это может быть полезно, если вы не хотите настраивать квантили в PromQL. Однако это менее гибко, чем Histogram.

Пример:

var requestLatency = prometheus.NewSummary(prometheus.SummaryOpts{
    Name:       "http_request_latency_seconds",
    Help:       "A summary of HTTP request latencies.",
    Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001}, // Целевые квантили с допустимой ошибкой
})

func recordLatency(duration float64) {
    requestLatency.Observe(duration)
}

4.5. prometheus.MustRegister

Сигнатура:

func MustRegister(cs ...Collector)

Что делает: Регистрирует один или несколько коллекторов (метрик) в глобальном реестре Prometheus. Если регистрация не удалась (например, метрика с таким именем уже существует), функция вызывает панику (panic). Обычно используется в init() функциях. Для безопасной регистрации без паники используйте prometheus.Register().

Пример:

func init() {
    prometheus.MustRegister(myCounter)
    prometheus.MustRegister(httpErrors, requestDuration) // Можно передать несколько
}

4.6. prometheus.NewRegistry

Сигнатура:

func NewRegistry() *Registry

Что делает: Создает новый, изолированный реестр метрик. Это полезно, если вы не хотите использовать глобальный реестр, например, в тестах или при создании библиотек, которые не должны конфликтовать с метриками основного приложения. Вы можете зарегистрировать метрики в этом реестре и передать его в promhttp.HandlerFor().

Пример:

func main() {
    registry := prometheus.NewRegistry()
    registry.MustRegister(myCounter)

    http.Handle("/metrics", promhttp.HandlerFor(registry, promhttp.HandlerOpts{}))
    http.ListenAndServe(":8080", nil)
}

4.7. promhttp.Handler() / promhttp.HandlerFor()

Сигнатура:

func Handler() http.Handler
func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler

Что делает: Создает HTTP-обработчик, который сериализует метрики из реестра в формат, понятный Prometheus (text/plain). Handler() использует глобальный реестр (prometheus.DefaultGatherer). HandlerFor() позволяет указать конкретный реестр (например, созданный через NewRegistry()). HandlerOpts позволяет настроить, например, включение сжатия или обработку ошибок.

Пример:

// Использование глобального реестра
http.Handle("/metrics", promhttp.Handler())

// Использование своего реестра
myRegistry := prometheus.NewRegistry()
// ... регистрация метрик ...
http.Handle("/metrics", promhttp.HandlerFor(myRegistry, promhttp.HandlerOpts{
    EnableOpenMetrics: true, // Включить формат OpenMetrics
}))

4.8. prometheus.NewProcessCollector / prometheus.NewGoCollector

Сигнатура:

func NewProcessCollector(opts ProcessCollectorOpts) Collector
func NewGoCollector() Collector

Что делает: Эти функции создают стандартные коллекторы, которые автоматически собирают метрики процесса ОС (использование CPU, памяти, файловых дескрипторов) и метрики рантайма Go (количество горутин, статистика сборщика мусора, размер кучи). Они предоставляют бесценную информацию о здоровье вашего приложения "из коробки".

Пример:

func init() {
    // Регистрируем коллектор метрик Go
    prometheus.MustRegister(prometheus.NewGoCollector())
    // Регистрируем коллектор метрик процесса
    prometheus.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}))
}

5. Реальный практический пример (100-200 строк кода)

Давайте создадим полноценный HTTP-сервис, который будет отслеживать количество запросов, их длительность и количество ошибок для разных эндпоинтов. Мы также добавим метрики Go и процесса.

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"

    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promauto"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

// Определяем метрики с помощью promauto (                    

Рекомендаций