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

Как отправить метрики с приложения в Grafana?

1.2 Junior🔥 61 комментариев
#Observability

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

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

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

Конечно, как опытный Go-разработчик, я подробно расскажу об отправке метрик из Go-приложения в экосистему Grafana. Важно понимать, что Grafana — это в первую очередь платформа для визуализации и анализа данных, а не система их сбора или хранения. Поэтому отправка метрик происходит не напрямую в Grafana, а в систему хранения временных рядов (TSDB), которую затем подключают к Grafana в качестве источника данных.

Основной принцип работы

Типичный пайплайн выглядит так:

  1. Приложение (Instrumentation): Генерирует метрики (счётчики, гистограммы и т.д.).
  2. Сборщик/Агент (Optional): Собирает метрики (например, Prometheus node_exporter или Pushgateway).
  3. База данных временных рядов (Storage): Хранит метрики (Prometheus, InfluxDB, Graphite, VictoriaMetrics).
  4. Grafana (Visualization): Запрашивает данные из базы и строит дашборды.

Рассмотрим самые популярные способы отправки метрик из Go-приложения.

Способ 1: Prometheus (Pull-модель) — Самый распространённый подход

Prometheus работает по pull-модели: он периодически "опрашивает" (scrapes) ваше приложение по HTTP-эндпоинту (обычно /metrics), чтобы получить текущие значения метрик.

Шаги для реализации:

  1. Установите клиентскую библиотеку:

    go get github.com/prometheus/client_golang
    
  2. Инструментируйте ваше приложение. Создайте и зарегистрируйте метрики:

    package main
    
    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", "status"},
        )
        requestDuration = promauto.NewHistogramVec(
            prometheus.HistogramOpts{
                Name:    "http_request_duration_seconds",
                Help:    "Duration of HTTP requests.",
                Buckets: prometheus.DefBuckets, // Предопределённые корзины для гистограммы
            },
            []string{"method", "path"},
        )
    )
    
    func main() {
        // Регистрируем стандартные метрики Go и процесса (GC, горутины, память)
        prometheus.MustRegister(prometheus.NewBuildInfoCollector())
    
        // Экспортируем метрики по адресу /metrics
        http.Handle("/metrics", promhttp.Handler())
    
        // Пример обработчика, который инкрементит метрики
        http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
            timer := prometheus.NewTimer(requestDuration.WithLabelValues(r.Method, r.URL.Path))
            defer timer.ObserveDuration()
    
            // Логика обработки запроса...
            w.WriteHeader(http.StatusOK)
            w.Write([]byte("Hello World"))
    
            // Увеличиваем счётчик запросов
            httpRequestsTotal.WithLabelValues(r.Method, r.URL.Path, "200").Inc()
        })
    
        http.ListenAndServe(":8080", nil)
    }
    
  3. Настройте Prometheus на сбор метрик с вашего приложения, добавив задание (job) в prometheus.yml:

    scrape_configs:
      - job_name: 'my_go_app'
        static_configs:
          - targets: ['localhost:8080']
    
  4. В Grafana добавьте Prometheus как источник данных, указав его адрес (например, http://prometheus:9090). После этого вы сможете создавать дашборды, используя запросы на языке PromQL (например, rate(http_requests_total[5m])).

Преимущества Pull-модели (Prometheus):

  • Простота отладки: можно вручную зайти на /metrics и увидеть все данные.
  • Централизованное управление сбором с одной стороны.
  • Сложнее "потерять" данные при кратковременных сбоях приложения.

Способ 2: Push-модель (Graphite, InfluxDB)

Иногда pull-модель невозможна (например, для кратковременных задач или в serverless-средах). Тогда используют push-подход, где приложение само отправляет метрики.

Пример с InfluxDB 2.x (используя официальный клиент):

package main

import (
    "context"
    "fmt"
    "time"
    influxdb2 "github.com/influxdata/influxdb-client-go/v2"
)

func main() {
    // Создаём клиент
    client := influxdb2.NewClient("http://localhost:8086", "your-auth-token")
    defer client.Close()

    // Получаем API для записи
    writeAPI := client.WriteAPI("your-org", "your-bucket")

    // Создаём точку (point) — запись метрики
    p := influxdb2.NewPointWithMeasurement("http_requests").
        AddTag("method", "GET").
        AddTag("path", "/api/v1/users").
        AddField("duration_ms", 152.5).
        AddField("count", 1).
        SetTime(time.Now())

    // Асинхронная запись
    writeAPI.WritePoint(p)

    // Для синхронной записи
    // err := writeAPI.WritePoint(context.Background(), p)

    // Гарантируем отправку всех ожидающих записей
    writeAPI.Flush()
}

Для работы с Grafana вам нужно будет добавить InfluxDB (или Graphite) как источник данных, указав соответствующие параметры подключения.

Способ 3: Использование Pushgateway (для задач в Prometheus)

Pushgateway в экосистеме Prometheus служит буфером для метрик от short-lived jobs (например, Cron-задач).

package main

import (
    "fmt"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/push"
)

func main() {
    // Создаём метрику
    completionTime := prometheus.NewGauge(prometheus.GaugeOpts{
        Name: "batch_job_last_completion_timestamp_seconds",
        Help: "The timestamp of the last successful batch job completion.",
    })
    completionTime.SetToCurrentTime()

    // Пушим метрику в Pushgateway
    err := push.New("http://pushgateway:9091", "my_batch_job").
        Collector(completionTime).
        Grouping("instance", "my_hostname").
        Push()

    if err != nil {
        fmt.Println("Could not push to Pushgateway:", err)
    }
}

Ключевые рекомендации

  • Выбор инструмента: Для долгоживущих сервисов (микросервисов, API) используйте Prometheus (Pull). Для задач, живущих меньше периода сбора Prometheus, или для legacy-систем — Pushgateway или прямой push в TSDB.
  • Библиотеки: Для Prometheus всегда используйте официальный client_golang. Он потокобезопасен, эффективен и предоставляет все типы метрик (Counter, Gauge, Histogram, Summary).
  • Лейблы (labels): Используйте их разумно. Лейблы должны иметь ограниченный набор значений (как status=200, method=GET). Не используйте в качестве лейбла уникальные ID (например, user_id), это создаст кардинальность метрик и убьёт производительность системы.
  • Экспорт стандартных метрик: Всегда включайте сбор стандартных метрик Go (go_*) и процесса (process_*) с помощью promhttp.Handler().
  • Сервис-открытие (Service Discovery): В продакшене настройте автоматическое обнаружение целей для Prometheus (через Kubernetes, Consul, файлы и т.д.), а не хардкодьте адреса.

Таким образом, отправка метрик из Go-приложения в Grafana — это процесс инструментирования кода, выбора и настройки подходящей системы хранения (Prometheus, InfluxDB и др.) и последующего подключения этой системы к Grafana для построения наглядных дашбордов.

Как отправить метрики с приложения в Grafana? | PrepBro