Go: почему без Observability ты отлаживаешь систему вслепую

Сетка - живи!!! Пожелаем сервису здоровья. А мы продолжаем!

Представим, что у нас есть Go-сервис, который обрабатывает заказы.

Пользователь нажимает кнопку, запрос уходит на бэк, а ответ приходит через 5 секунд вместо обычных 100 мс.

Что делать?

Можно открыть логи и искать ошибку. Но если ошибка не возникла, а сервис просто тормозит? Как понять, где именно проблема: в обработчике, базе данных или внешнем апи?

Для этого нужна Observability, ну то есть простыми словами - наблюдаемость.

Обычно выделяют три основных компонента: Logs - что произошло. Metrics - как часто и насколько хорошо это происходит. Traces - где именно теряется время при обработке запроса.

Покажу на простом примере, как минимум можно сделать уже сейчас.

Практика: измеряем время обработки HTTP-запросов

В Go можно начать с middleware, который измеряет длительность запроса и записывает её в лог.

package main

import ( “log” “net/http” “time” )

func observability(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now()

next.ServeHTTP(w, r)

duration := time.Since(start)

log.Printf( “method=%s path=%s duration=%s”, r.Method, r.URL.Path, duration, ) }) }

func main() { mux := http.NewServeMux()

mux.HandleFunc(“/orders”, func(w http.ResponseWriter, r *http.Request) { time.Sleep(300 * time.Millisecond) w.Write([]byte(“orders”)) })

log.Println(“server started on :8080”)

err := http.ListenAndServe(“:8080”, observability(mux)) if err != nil { log.Fatal(err) } }

Запускаем сервис и отправляем запрос: curl http://localhost:8080/orders

В логах увидим примерно следующее: method=GET path=/orders duration=300.4ms

Теперь у нас есть хотя бы одна полезная зацепка. Если обработка занимает 300 мс, можно двигаться дальше и измерять отдельные этапы: запрос к БД, обращение к внешнему сервису, сериализацию ответа.

Но одного лога недостаточно

В production я бы развивал эту схему дальше: Prometheus - собирать метрики количества запросов, ошибок и задержек, смотреть p95 и p99. OpenTelemetry - создавать трассировки запросов и связывать между собой вызовы разных сервисов. Grafana - строить дашборды и наблюдать за состоянием приложения.

Например, p99 в 2 секунды при среднем времени ответа в 100 мс означает, что для части запросов ситуация намного хуже, чем кажется по среднему значению. И ещё важный момент: в реальном middleware стоит записывать HTTP-статус и размер ответа. Для этого понадобится ResponseWriter-обёртка. А в production-логах лучше использовать структурированный логгер, например log/slog, и не записывать чувствительные данные.

Главная мысль: Observability нужна не только тогда, когда сервис уже упал. Она позволяет понять, что происходит внутри работающей системы, обнаружить деградацию и найти узкое место до того, как проблема станет заметна всем пользователям.

Чем больше сервисов и зависимостей, тем дороже обходится работа вслепую. А что вы используете в Go-проектах: только логи или уже связку метрик и распределённых трассировок?