Введение в Prometheus

Прежде чем мы углубимся в тонкости реализации метрик и оповещений в приложениях Go с использованием Prometheus, давайте кратко рассмотрим, что такое Prometheus и почему он так популярен. Prometheus — это набор инструментов с открытым исходным кодом для мониторинга систем и оповещения, который изначально был создан в SoundCloud. С тех пор он стал краеугольным камнем в области мониторинга, особенно в рамках Cloud Native Computing Foundation.

Prometheus собирает и хранит метрики в виде временных рядов данных, которые включают значение метрики вместе с отметкой времени и необязательными парами «ключ-значение», известными как метки. Это делает его невероятно мощным инструментом для мониторинга и анализа производительности ваших приложений с течением времени.

Настройка Prometheus в Go

Чтобы начать работу с Prometheus в вашем приложении Go, вам потребуется установить необходимые пакеты. Вот как вы можете это сделать:

go get github.com/prometheus/client_golang/prometheus
go get github.com/prometheus/client_golang/prometheus/promauto
go get github.com/prometheus/client_golang/prometheus/promhttp

Предоставление стандартных метрик

Давайте создадим простое приложение Go, которое предоставляет стандартные метрики Go через HTTP-конечную точку. Вот минимальный пример:

package main

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

func main() {
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":2112", nil)
}

Чтобы запустить это приложение, просто выполните:

go run main.go

Затем вы можете получить доступ к метрикам, посетив http://localhost:2112/metrics в своём браузере или используя curl:

curl http://localhost:2112/metrics

Это отобразит стандартные метрики Go, такие как статистика сборки мусора и метрики процесса.

Пользовательские метрики

Теперь давайте добавим несколько пользовательских метрик в наше приложение. Например, мы можем создать счётчик для отслеживания количества операций, обработанных нашим приложением.

package main

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

var (
    opsProcessed = promauto.NewCounter(prometheus.CounterOpts{
        Name: "myapp_processed_ops_total",
        Help: "Общее количество обработанных событий",
    })
)

func recordMetrics() {
    go func() {
        for {
            opsProcessed.Inc()
            time.Sleep(2 * time.Second)
        }
    }()
}

func main() {
    recordMetrics()
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":2112", nil)
}

В этом примере opsProcessed — это счётчик, который увеличивается каждые 2 секунды. Когда вы перейдёте к конечной точке /metrics, вы увидите справочное сообщение, информацию о типе и текущее значение счётчика myapp_processed_ops_total.

Другие типы метрик

Prometheus поддерживает несколько типов метрик, включая счётчики, датчики и гистограммы.

  • Счётчики: это совокупные метрики, которые могут только увеличиваться. Они идеально подходят для отслеживания количества запросов, ошибок или других событий.
  • Датчики: они могут увеличиваться или уменьшаться и полезны для отслеживания таких значений, как активные соединения, размеры очередей или использование памяти.
  • Гистограммы: используются для отслеживания распределения значений, таких как продолжительность запроса или размер ответа.

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

var (
    activeConnections = promauto.NewGauge(prometheus.GaugeOpts{
        Name: "myapp_active_connections",
        Help: "Количество активных соединений",
    })
)

func main() {
    // Имитация изменения количества активных соединений
    go func() {
        for {
            activeConnections.Set(10)
            time.Sleep(5 * time.Second)
            activeConnections.Set(20)
            time.Sleep(5 * time.Second)
        }
    }()

    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":2112", nil)
}

Настройка Prometheus для сбора метрик

Чтобы настроить Prometheus на сбор метрик из вашего приложения Go, вам нужно создать файл конфигурации prometheus.yml. Вот пример:

scrape_configs:
  - job_name: myapp
    scrape_interval: 10s
    static_configs:
      - targets:
        - localhost:2112

Эта конфигурация указывает Prometheus собирать метрики с localhost:2112 каждые 10 секунд.

Визуализация метрик с помощью Grafana

После того как Prometheus начнёт собирать ваши метрики, вы можете использовать Grafana для их визуализации. Вот простая блок-схема, показывающая, как взаимодействуют компоненты:

graph TD A("Приложение Go") -->|Предоставить метрики| B(Prometheus) B -->|Собрать метрики| A B -->|Сохранить метрики|C(Хранилище Prometheus) B(Grafana) -->|Запросить метрики| C D -->|Отобразить панели мониторинга| E(Пользователь)

Добавление метрик HTTP-обработчиков

Добавление метрик ваших HTTP-обработчиков с помощью Prometheus может дать ценную информацию о производительности вашего приложения. Вот пример того, как вы можете добавить метрику HTTP-обработчику для отслеживания количества и продолжительности запросов:

package main

import (
    "net/http"
    "time"
    "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: "Общее количество HTTP-запросов",
    }, []string{"code", "method", "handler"})
    httpRequestDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
        Name: "http_request_duration_seconds",
        Help: "Продолжительность HTTP-запросов",
    }, []string{"code", "method", "handler"})
)

func instrumentHandler(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        next(w, r)
        duration := time.Since(start)
        httpRequestDuration.WithLabelValues(r.Method, r.URL.Path, "handler").Observe(duration.Seconds())
        httpRequestsTotal.WithLabelValues("200", r.Method, "handler").Inc()
    }
}

func main() {
    http.Handle("/", instrumentHandler(func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Hello, World"))
    }))
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":2112", nil)
}

В этом примере функция instrumentHandler оборачивает исходный HTTP-обработчик для отслеживания продолжительности и количества запросов.

Развёртывание в кластере Kubernetes

Если вы запускаете своё приложение в кластере Kubernetes, вы можете использовать Prometheus Operator для управления сбором метрик. Вот пример того, как можно развернуть пример приложения и настроить Prometheus на сбор его метрик:

graph TD A("Кластер Kubernetes") -->|Развернуть приложение|B(Pod) B -->|Предоставить метрики| C(Prometheus) C -->|Собрать метрики| B C -->|Сохранить метрики|D(Хранилище Prometheus) B(Grafana) -->|Запросить метрики| D E -->|Отобразить панели мониторинга| F(Пользователь)

Вам потребуется создать манифест Deployment для вашего приложения и настраиваемый ресурс PodMonitor, чтобы настроить Prometheus на сбор метрик.

Заключение

Реализация метрик и предупреждений в приложениях Go с использованием Prometheus — это мощный способ получить представление о производительности и работоспособности вашего приложения. Благодаря возможности предоставлять пользовательские метрики, добавлять метрики HTTP-обработчикам и визуализировать данные с помощью Grafana вы можете создать надёжную систему мониторинга, которая поможет вам быстро и эффективно диагностировать проблемы.

Помните, мониторинг — это не только сбор данных; это ещё и рассказ истории с помощью этих данных. Итак, вперёд, добавляйте метрики своим приложениям Go, и пусть Prometheus поможет вам написать эту историю. Удачного мониторинга!