Продвинутый мониторинг Go-приложений: от метрик до алертов
В современной разработке на Go (Golang) базового логирования и Health Check недостаточно. Для production-систем требуется глубокая observability: сбор кастомных метрик, их экспорт в Prometheus, визуализация в Grafana и автоматические алерты. В этой статье мы разберём продвинутый уровень мониторинга Go-приложений — от архитектуры метрик до настройки алертов на основе бизнес-логики.
Архитектура мониторинга: Prometheus + Go
Стандартный стек мониторинга для Go включает:
- Prometheus — система сбора и хранения метрик (pull-модель).
- Go-клиент Prometheus (
prometheus/client_golang) — библиотека для экспорта метрик. - Grafana — визуализация дашбордов.
- Alertmanager — управление алертами (email, Slack, Telegram).
Go-приложение должно предоставлять HTTP-эндпоинт (обычно /metrics), с которого Prometheus забирает данные. Рассмотрим базовую настройку.
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
// Регистрация стандартных метрик Go (runtime, GC, goroutines)
prometheus.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}))
prometheus.MustRegister(prometheus.NewGoCollector())
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":8080", nil)
}
Запустив приложение, вы получите стандартные метрики: go_goroutines, process_cpu_seconds_total, go_memstats_alloc_bytes и другие. Но для продвинутого мониторинга этого недостаточно — нужны кастомные метрики.
Создание кастомных метрик: Gauge, Counter, Histogram
Prometheus поддерживает четыре основных типа метрик. Рассмотрим их на примере Go-приложения, обрабатывающего HTTP-запросы.
Counter (счётчик) — количество событий
Используется для подсчёта запросов, ошибок, выполнения задач.
var requestCounter = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Общее количество HTTP-запросов",
},
[]string{"method", "endpoint", "status"},
)
func init() {
prometheus.MustRegister(requestCounter)
}
func handler(w http.ResponseWriter, r *http.Request) {
// Обработка запроса
requestCounter.WithLabelValues(r.Method, r.URL.Path, "200").Inc()
}
Gauge (измеритель) — текущие значения
Идеален для мониторинга очередей, пулов соединений, температуры.
var queueSize = prometheus.NewGauge(
prometheus.GaugeOpts{
Name: "task_queue_size",
Help: "Текущий размер очереди задач",
},
)
func addToQueue() {
queueSize.Inc()
}
func processFromQueue() {
queueSize.Dec()
}
Histogram (гистограмма) — распределение значений
Используется для измерения времени ответа или размера данных.
var requestDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "Гистограмма времени обработки запросов",
Buckets: prometheus.DefBuckets, // 0.005, 0.01, 0.025, 0.05, ...
},
[]string{"endpoint"},
)
func measureRequest(endpoint string, duration float64) {
requestDuration.WithLabelValues(endpoint).Observe(duration)
}
Summary (суммарий) — квантили
Похож на гистограмму, но вычисляет точные квантили (p50, p95, p99).
var requestLatency = prometheus.NewSummaryVec(
prometheus.SummaryOpts{
Name: "http_request_latency_seconds",
Help: "Латентность запросов (квантили)",
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
},
[]string{"endpoint"},
)
Продвинутые техники: middleware и бизнес-метрики
Чтобы не загромождать бизнес-логику, обёртывайте сбор метрик в middleware. Пример для net/http:
func MetricsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
wrapped := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK}
next.ServeHTTP(wrapped, r)
duration := time.Since(start).Seconds()
requestCounter.WithLabelValues(r.Method, r.URL.Path, strconv.Itoa(wrapped.statusCode)).Inc()
requestDuration.WithLabelValues(r.URL.Path).Observe(duration)
})
}
type responseWriter struct {
http.ResponseWriter
statusCode int
}
func (rw *responseWriter) WriteHeader(code int) {
rw.statusCode = code
rw.ResponseWriter.WriteHeader(code)
}
Бизнес-метрики — это метрики, отражающие состояние вашего продукта: количество активных пользователей, скорость обработки транзакций, уровень ошибок в платёжном шлюзе. Например:
var activeUsers = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "active_users_count",
Help: "Количество активных пользователей в системе",
})
// В бизнес-слое:
func userLoggedIn() {
activeUsers.Inc()
}
func userLoggedOut() {
activeUsers.Dec()
}
Такие метрики позволяют строить алерты не на уровне CPU, а на уровне бизнес-событий.
Настройка алертов: PromQL и Alertmanager
Алерты в Prometheus настраиваются через правила (rules) на языке PromQL. Файл rules.yml:
groups:
- name: go_app_alerts
rules:
- alert: HighRequestLatency
expr: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 1
for: 5m
labels:
severity: critical
annotations:
summary: "Высокая латентность запросов ({{ $value }}s)"
- alert: TooManyErrors
expr: rate(http_requests_total{status=~