> Работали ли с системами сбора и хранения метрик, например Graphite, Jaeger, Prometheus (Go)
Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: VK
Стек: Go
> Пример ответа
Короткий ответ
Да, работал с Prometheus как основным инструментом сбора метрик, с Grafana для визуализации и Jaeger для распределённой трассировки. Graphite использовал реже, в основном в легаси-проектах. В Go-сервисах применял клиентские библиотеки Prometheus, настраивал кастомные метрики, алерты и экспортеры. Также есть опыт интеграции с OpenTelemetry для унификации сбора телеметрии.
Подробное объяснение
В системах на Go обычно используется связка Prometheus + Grafana + Jaeger. Prometheus работает по pull-модели: сервисы экспонируют метрики на /metrics, а Prometheus периодически их собирает. Для Go есть официальная библиотека client_golang, которая предоставляет готовые коллекторы для runtime-метрик (GC, goroutines, память) и позволяет описывать кастомные метрики.
Типы метрик в Prometheus: counter (счётчики, только растут), gauge (произвольные значения), histogram (распределение значений, например latency), summary (аналогично, но с квантилями на стороне клиента). Для Go-сервисов важно мониторить: latency запросов, error rate, saturation (например, количество горутин или размер очереди), а также бизнес-метрики.
Jaeger используется для distributed tracing - отслеживания запроса через несколько сервисов. В Go обычно применяется OpenTelemetry SDK, который поддерживает экспорт в Jaeger. Ключевые концепции: trace, span, context propagation через заголовки (например, traceparent).
Graphite - это устаревшая система на push-модели, где метрики отправляются по TCP/UDP. В современных Go-проектах встречается редко, но если проект старый, приходится поддерживать интеграцию через statsd-клиенты.
На практике
В типичном Go-микросервисе я делаю так:
- Подключаю
prometheus/client_golangи регистрирую кастомные метрики черезpromauto. - Добавляю middleware для HTTP-сервера, который автоматически собирает latency и status code для каждого запроса.
- Настраиваю экспорт runtime-метрик через
collectors.NewGoCollector()иcollectors.NewProcessCollector(). - Для трассировки добавляю OpenTelemetry instrumentation: создаю tracer, спаны для ключевых операций (обращение к БД, внешние HTTP-вызовы).
- В Kubernetes-окружении Prometheus обнаруживает сервисы через service discovery, поэтому достаточно аннотаций в деплойменте.
Пример алерта, который я обычно настраиваю: если http_request_duration_seconds p99 превышает 500ms в течение 5 минут - это критично. Или если error rate больше 1% за 10 минут.
Пример кода
GOpackage mainimport ("net/http""time""github.com/prometheus/client_golang/prometheus""github.com/prometheus/client_golang/prometheus/promauto""github.com/prometheus/client_golang/prometheus/promhttp")var (httpRequests = promauto.NewCounterVec(prometheus.CounterOpts{Name: "http_requests_total",Help: "Total number of HTTP requests",}, []string{"method", "path", "status"})httpDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{Name: "http_request_duration_seconds",Help: "HTTP request duration",Buckets: prometheus.DefBuckets,}, []string{"method", "path"}))func metricsMiddleware(next http.Handler) http.Handler {return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {start := time.Now()wrapped := &statusRecorder{ResponseWriter: w, status: http.StatusOK}next.ServeHTTP(wrapped, r)httpRequests.WithLabelValues(r.Method, r.URL.Path, http.StatusText(wrapped.status)).Inc()httpDuration.WithLabelValues(r.Method, r.URL.Path).Observe(time.Since(start).Seconds())})}type statusRecorder struct {http.ResponseWriterstatus int}func (r *statusRecorder) WriteHeader(code int) {r.status = coder.ResponseWriter.WriteHeader(code)}func main() {mux := http.NewServeMux()mux.Handle("/metrics", promhttp.Handler())mux.Handle("/api", metricsMiddleware(http.HandlerFunc(apiHandler)))http.ListenAndServe(":8080", mux)}
Как отвечать на собеседовании
Начните с конкретики: назовите инструменты, с которыми реально работали, и в каком контексте. Затем покажите понимание архитектуры: pull vs push, типы метрик, как трассировка связана с метриками. Упомяните, как решали реальные проблемы: например, высокая кардинальность метрик, переполнение histogram bucket, потеря спанов при высокой нагрузке.
Если спросят про Graphite - честно скажите, что это легаси, и объясните, почему перешли на Prometheus (pull-модель, встроенный alerting, интеграция с Kubernetes). Для Jaeger важно показать, что понимаете разницу между метриками и трассировкой: метрики - агрегированная картина, трассировка - конкретный запрос.
Завершите примером из практики: как метрики помогли найти узкое место или как трассировка выявила проблему с N+1 запросами.
Что проверяет интервьюер
Интервьюер оценивает:
- практический опыт, а не только теорию - важно, чтобы вы могли назвать конкретные метрики и алерты, которые настраивали;
- понимание trade-off между pull и push моделями;
- знание типов метрик и когда какой использовать;
- умение проектировать наблюдаемость (observability) для Go-сервиса: что мониторить, какие метрики критичны;
- понимание, как трассировка и метрики дополняют друг друга;
- способность объяснить, как дебажить проблемы с производительностью через метрики и трейсы.
Типичные ошибки
- Путаница между counter и gauge: например, использование counter для текущего количества горутин.
- Игнорирование кардинальности метрик: добавление
user_idв labels - это быстро убивает Prometheus. - Отсутствие middleware для автоматического сбора метрик - каждый раз писать вручную.
- Непонимание разницы между histogram и summary: histogram позволяет агрегировать на стороне сервера, summary - нет.
- Забывают про экспорт runtime-метрик Go: GC, goroutines, память - это база для диагностики.
- В трассировке - не передают контекст через границы сервисов, из-за чего спаны разрываются.
> Похожие задачи по Go
Как использовать мьютексы для защиты мапы при параллельном доступе в Go
Как оптимизировать блокировки при работе с мапой и слайсом в Go, чтобы не блокировать весь слайс
Что происходит, если фича не успела быть сделана в спринт и как переносится задача
Почему важно валидировать входные данные
> Похожие задачи по backend
Какой максимальный размер строки на входе и нужно ли его обрабатывать
Как оптимизировать блокировки при работе с мапой и слайсом в Go, чтобы не блокировать весь слайс
Что происходит, если фича не успела быть сделана в спринт и как переносится задача
Почему важно валидировать входные данные
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью