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 ( Также в библиотеке
Миграции баз данных в Rust: обзор инструментов Diesel, SeaORM и sqlx
Joi для JavaScript (Node.js): полное руководство с примерами
Валидация данных в Swift (iOS/macOS): лучшие практики и инструменты