Пробовали ли использовать метрики, счетчики и трассировку в коде
Что проверяют
Инструментируете ли вы сервис сами или только смотрите на чужие дашборды. За вопросом стоит эксплуатация: дежурному нужно по графику понять, что сломалось, а по трассе найти, где именно.
Как отвечать
Разделите сигналы и скажите, что делали руками.
- Метрики. В Go это клиент Prometheus:
Counterдля событий,Gaugeдля текущего значения,Histogramдля длительностей, отдача черезpromhttp.Handler(). Квантили считаются запросомhistogram_quantileпо гистограмме, а счётчик читается черезrate(), потому что после рестарта он обнуляется.
var reqs = prometheus.NewCounterVec(
prometheus.CounterOpts{Name: "http_requests_total"},
[]string{"route", "code"},
)- Трассировка. OpenTelemetry: спан живёт в
context.Context, который идёт первым аргументом, между сервисами контекст передаётся заголовкомtraceparent. Сэмплирование настраивается, иначе хранилище трасс выйдет дороже самого сервиса. - Логи. Структурные, через
log/slog, с полем идентификатора трассы, чтобы проваливаться из трассы в логи.
Добавьте, что смотрите и на рантайм: число горутин, паузы сборщика мусора, размер кучи, а для разового расследования подключаете net/http/pprof с профилями процессора и кучи. Набор показателей сервиса удобно описывать как частоту запросов, долю ошибок и длительность.
Где спотыкаются
Кладут в метку идентификатор пользователя, путь с параметрами или текст ошибки. Каждое новое значение это отдельный временной ряд, память хранилища растёт лавиной, и мониторинг падает раньше сервиса.
Меряют среднее время ответа. Среднее прячет хвост: половина пользователей ждёт секунду, а на графике спокойные сто миллисекунд. Нужны квантили, причём усреднять готовые квантили с разных экземпляров нельзя, складывать надо гистограммы.
Подключают трассировку и теряют контекст: внутри горутины берут пустой контекст, и трасса рассыпается на несвязанные куски. Тот же эффект даёт вызов соседнего сервиса клиентом без распространения заголовков.