Какие инструменты для мониторинга, логирования и трассировки вы использовали в Go-микросервисах? Расскажите о своем опыте настройки и применения.

Ответ

Да, я активно использовал стек инструментов для обеспечения наблюдаемости (observability) микросервисов, который строится на трех основных столпах: метрики, логи и трассировки.

1. Метрики (Monitoring)

Для сбора и анализа метрик я использовал связку Prometheus + Grafana.

  • Prometheus: Это система для сбора и хранения временных рядов (time-series). В Go-приложение легко интегрируется клиентская библиотека prometheus/client_golang. Я экспортировал стандартные метрики (CPU, память, Go runtime) и кастомные бизнес-метрики (например, количество обработанных запросов, время выполнения операций, количество ошибок — так называемый RED-метод: Rate, Errors, Duration).
  • Grafana: Инструмент для визуализации данных из Prometheus в виде дашбордов.

Пример экспорта кастомной метрики:

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

var httpRequestsTotal = promauto.NewCounterVec(
    prometheus.CounterOpts{
        Name: "http_requests_total",
        Help: "Total number of HTTP requests",
    },
    []string{"method", "path"}, // Метка для разделения по методу и пути
)

func myHandler(w http.ResponseWriter, r *http.Request) {
    httpRequestsTotal.WithLabelValues(r.Method, r.URL.Path).Inc()
    w.Write([]byte("Hello, World!"))
}

func main() {
    http.HandleFunc("/", myHandler)
    http.Handle("/metrics", promhttp.Handler()) // Эндпоинт для сбора метрик
    http.ListenAndServe(":8080", nil)
}

2. Логирование (Logging)

Для логирования я предпочитаю использовать структурированные логи в формате JSON. Это позволяет легко парсить, индексировать и искать логи в системах вроде ELK Stack (Elasticsearch, Logstash, Kibana) или Loki.

  • Библиотеки в Go: zerolog или zap. Они очень производительные и удобные для создания структурированных логов.
  • Системы сбора: Loki от Grafana Labs — легковесная альтернатива ELK, хорошо интегрируется с Prometheus и Grafana.

3. Трассировка (Tracing)

Для отслеживания запросов в распределенной системе я использовал OpenTelemetry как стандарт для инструментирования кода и Jaeger в качестве бэкенда для хранения и визуализации трейсов.

  • OpenTelemetry (OTel): Позволяет добавлять в код информацию о span-ах (этапах выполнения запроса) и передавать контекст трассировки между сервисами через HTTP-заголовки или метаданные сообщений.
  • Jaeger: Помогает визуализировать полный путь запроса через все микросервисы, находить узкие места и анализировать ошибки в сложных взаимодействиях.

4. Профилирование (Profiling)

Для глубокого анализа производительности я использовал встроенный в Go инструмент pprof. Он позволяет собирать профили CPU, памяти (heap), горутин и блокировок, чтобы находить и устранять проблемы производительности непосредственно в коде.

Ответ 18+ 🔞

А, наблюдаемость, говоришь? Ну, это ж святое, когда у тебя этих микросервисов, как тараканов за печкой, овердохуища! Если за всем этим зоопарком не следить — пиши пропало, через неделю уже не поймёшь, какой из них тебе в тихую всю память сожрал или в бесконечный цикл ушёл.

Короче, я эту магию строил на трёх китах, как и полагается: метрики, логи и трассировки. Без этого — ты просто слепой крот в подземном лабиринте, блядь.

1. Метрики (Твои цифровые стукачи)

Тут мой выбор — связка Prometheus + Grafana. Просто, как три копейки, и работает, как швейцарские часы, если, конечно, не накосячить.

  • Prometheus — это такой занудный бухгалтер, который только и делает, что сидит и постоянно пересчитывает все твои цифры: сколько запросов, сколько времени, сколько ошибок. В Go втыкаешь библиотечку prometheus/client_golang — и понеслась.
  • Grafana — это уже для начальства. Берёт все эти скучные цифры от бухгалтера и рисует красивые картинки, графики и дашборды, чтобы даже менеджер мог понять, что всё «охуенно зелёное» или «пиздец как красное».

Вот, смотри, как я, например, счетчик запросов на коленке делал:

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

// Создаём счётчик, который будет считать запросы по методу и пути
var httpRequestsTotal = promauto.NewCounterVec(
    prometheus.CounterOpts{
        Name: "http_requests_total", // Имя, как в паспорте
        Help: "Total number of HTTP requests", // Пояснение для чайников
    },
    []string{"method", "path"}, // Разделяем, кто есть кто
)

func myHandler(w http.ResponseWriter, r *http.Request) {
    // Пришёл запрос — чик, увеличили счётчик
    httpRequestsTotal.WithLabelValues(r.Method, r.URL.Path).Inc()
    w.Write([]byte("Hello, World!"))
}

func main() {
    http.HandleFunc("/", myHandler)
    // Вот этот волшебный эндпоинт, куда Prometheus будет приходить как голодный студент в столовую
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":8080", nil)
}

И вот уже Prometheus тыкается в твой /metrics, считывает эти цифры, а ты в Grafana смотришь, какой эндпоинт у тебя самый популярный — может, его уже пора в отдельный сервис выносить, пока он всё не обоссал.

2. Логи (История болезни каждого сервиса)

А вот логировать просто в текстовый файл — это уровень пещерного человека, ей-богу. Сейчас в моде структурированные логи, в идеале — в JSON. Почему? Да потому что потом их машине легче жрать!

  • Библиотеки: В Go я уважаю zerolog или zap. Быстрые, не грузят приложение, и ты можешь к каждому сообщению прилепить кучу полей: user_id, transaction_id, error_code. Не то что эти ваши printf с кучей текста.
  • Куда складывать: Раньше все тащили в ELK Stack (Elasticsearch, Logstash, Kibana) — мощно, но для него свой отдельный кластер порой нужен. Сейчас модно использовать Loki от Grafana. Он как Prometheus, только для логов. Легковесный, и логи сразу рядом с метриками в Grafana можно смотреть — красота!

3. Трассировка (Детектив следователь)

Ну а это самый крутой уровень, когда тебе нужно проследить один-единственный запрос пользователя, который прошарился через пять разных сервисов, в каждом по два раза побывал, и в итоге вернулся с ошибкой 500. Без трассировки ты будешь как тот Герасим из рассказа — только «Муму» мычать и не понять, где же именно пиздец случился.

  • OpenTelemetry (OTel) — это сейчас стандарт де-факто. Ты инструментируешь код: отмечаешь начала и концы операций (спаны), а OTel аккуратно протаскивает идентификатор трассировки через все сервисы, будь то HTTP или очередь сообщений.
  • Jaeger — это следователь, который все эти спаны собирает и показывает тебе на красивом дереве весь путь запроса. Видно сразу: ага, этот сервис отработал за 5 мс, а этот — за 5 секунд, потому что десять раз сходил в базу, идиот. Находишь узкое место — и тут уже можно с профилированием разбираться.

4. Профилирование (Вскрытие покажет)

А вот когда метрики показали, что CPU ушёл в даун, а логи молчат, — тут в бой идёт тяжёлая артиллерия. В Go для этого есть встроенный pprof. Это как рентген для твоего приложения.

Поднимаешь специальный эндпоинт, подключаешься к нему — и можешь снять снимок:

  • Профиль CPU — покажет, какая функция твою процессорную мощь пожирает.
  • Профиль памяти (heap) — выявит, кто там память не отпускает и устраивает утечку.
  • Профиль горутин — найдет тех, кто уснул и забыл проснуться, создавая утечку.

В общем, наблюдаемость — это не роскошь, а средство выживания в мире микросервисов. Без этого ты просто на ощупь в тёмной комнате ищешь чёрную кошку, которой там, вполне возможно, уже давно нет. А с этим — у тебя полная картина, тепловизор и датчики движения на каждый чих. Живи спокойно. Ну, почти.