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

Как мониторишь приложение?

2.2 Middle🔥 192 комментариев
#Observability

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

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

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

Мониторинг Go-приложений: стратегия и инструменты

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

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

Prometheus — основа моей системы мониторинга. В Go-приложениях я использую официальный клиент github.com/prometheus/client_golang.

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

  • Бизнес-метрики: количество обработанных заказов, уникальных пользователей, сумма транзакций
  • Метрики приложения: время выполнения запросов (гистограммы), количество запросов в секунду, ошибки по типам
  • Системные метрики: использование CPU, памяти, количество горутин, размер хипа
package metrics

import (
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promauto"
)

var (
    requestDuration = promauto.NewHistogramVec(
        prometheus.HistogramOpts{
            Name:    "http_request_duration_seconds",
            Help:    "Duration of HTTP requests",
            Buckets: prometheus.DefBuckets,
        },
        []string{"path", "method", "status"},
    )
    
    activeGoroutines = promauto.NewGauge(
        prometheus.GaugeOpts{
            Name: "go_goroutines",
            Help: "Number of active goroutines",
        },
    )
)

func RecordRequest(duration float64, path, method, status string) {
    requestDuration.WithLabelValues(path, method, status).Observe(duration)
}

2. Централизованное логирование

Для логирования использую структурированный подход с zerolog или slog (встроен в Go 1.21+):

package logger

import (
    "os"
    "github.com/rs/zerolog"
)

func NewLogger() zerolog.Logger {
    logger := zerolog.New(os.Stdout).
        With().
        Timestamp().
        Str("service", "my-service").
        Logger()
    
    zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
    
    return logger
}

// Использование с контекстом
func handleRequest(ctx context.Context) {
    logger := zerolog.Ctx(ctx)
    logger.Info().
        Str("method", "GET").
        Str("path", "/api/v1/users").
        Int("user_id", 123).
        Msg("request processed")
}

Логи отправляю в Elasticsearch через Filebeat или напрямую, что позволяет:

  • Быстрый поиск по логам через Kibana
  • Анализ паттернов ошибок
  • Настройка алертов на критические ошибки

3. Распределенная трассировка

Для микросервисной архитектуры обязательна трассировка через OpenTelemetry:

package tracing

import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/jaeger"
    "go.opentelemetry.io/otel/sdk/trace"
)

func InitTracing(serviceName string) (*trace.TracerProvider, error) {
    exporter, err := jaeger.New(jaeger.WithCollectorEndpoint())
    if err != nil {
        return nil, err
    }
    
    tp := trace.NewTracerProvider(
        trace.WithBatcher(exporter),
        trace.WithResource(resource.NewWithAttributes(
            semconv.SchemaURL,
            semconv.ServiceNameKey.String(serviceName),
        )),
    )
    
    otel.SetTracerProvider(tp)
    return tp, nil
}

Инструменты для визуализации: Jaeger или Tempo + Grafana.

4. Health checks и readiness probes

Обязательно реализую эндпоинты для проверки здоровья:

package health

import (
    "net/http"
    "database/sql"
)

type HealthChecker struct {
    db *sql.DB
    cache redis.Conn
}

func (h *HealthChecker) HealthHandler(w http.ResponseWriter, r *http.Request) {
    // Проверяем все критичные зависимости
    if err := h.db.Ping(); err != nil {
        http.Error(w, "DB unavailable", http.StatusServiceUnavailable)
        return
    }
    
    // Проверяем кэш
    if _, err := h.cache.Do("PING"); err != nil {
        http.Error(w, "Cache unavailable", http.StatusServiceUnavailable)
        return
    }
    
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("OK"))
}

func (h *HealthChecker) ReadinessHandler(w http.ResponseWriter, r *http.Request) {
    // Более строгие проверки для готовности
    // Например, проверка миграций БД, доступности внешних API
    w.WriteHeader(http.StatusOK)
    w.Write([]byte("READY"))
}

5. Инфраструктурный мониторинг

Для инфраструктуры использую:

  • cAdvisor или node-exporter для метрик контейнеров и хостов
  • Blackbox exporter для проверки доступности извне
  • Kubernetes metrics API для оркестрации

6. Визуализация и алертинг

Grafana — основной инструмент для дашбордов:

  1. Общий дашборд: ключевые бизнес-метрики и SLO
  2. Технический дашборд: метрики приложения, горутины, память, GC
  3. Инфраструктурный дашборд: CPU, память, сеть, диск

Alertmanager настраиваю для алертов:

  • Критические алерты (P1): недоступность сервиса, ошибки 5xx > 5%
  • Предупреждения (P2): рост latency, повышение ошибок 4xx
  • Информационные алерты: достижение лимитов по бизнес-метрикам

7. Профилирование и отладка

Регулярно использую pprof для глубокого анализа:

# Онлайн-профилирование
go tool pprof http://localhost:8080/debug/pprof/profile
go tool pprof http://localhost:8080/debug/pprof/heap

# Автоматическое профилирование в продакшене
import _ "net/http/pprof"

Практические принципы мониторинга:

  1. Измеряй то, что важно для бизнеса — не собирай метрики "на всякий случай"
  2. SLO/SLA-ориентированный подход — настрой алерты на нарушение SLO, а не на каждое отклонение
  3. Контекстуализация логов — всегда добавляй request_id, user_id, correlation_id
  4. Автоматическое восстановление — настрой автоскейлинг и circuit breakers
  5. Регулярные ревью метрик — удаляй неиспользуемые метрики, оптимизируй кардинальность лейблов

Такой подход позволяет не только оперативно реагировать на инциденты, но и проводить профилактический анализ, планировать емкость и постоянно улучшать надежность приложения.