Цели
- Создание пользовательских метрик Prometheus в Go.
- Визуализация пользовательских метрик в Grafana.
- Создать веб-хук Slack.
- Создать оповещение в Grafana.
- Отправить в Slack сообщение с оповещением.
Создание пользовательских метрик Prometheus
- prometheus.go:
package metrics
import (
"github.com/prometheus/client_golang/prometheus"
)
var (
HttpRequestCountWithPath = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total_with_path",
Help: "Number of HTTP requests by path.",
},
[]string{"url"},
)
// PROMQL => rate(http_request_duration_seconds_sum{}[5m]) / rate(http_request_duration_seconds_count{}[5m])
HttpRequestDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "Response time of HTTP request.",
},
[]string{"path"},
)
)
func init() {
prometheus.MustRegister(HttpRequestCountWithPath)
prometheus.MustRegister(HttpRequestDuration)
}
HttpRequestCountWithPath
: этой метрикой показывается, сколько HTTP-запросов отправляется по одному и тому же пути.
HttpRequestDuration
: этой метрикой показывается время ответа HTTP-запроса.
prometheus.MustRegister()
вызывается для регистрации метрик с Prometheus. Регистрация необходима для извлечения этих метрик с помощью Prometheus.
Использование метрик в промежуточном ПО
- middleware.go:
/*
Регистрируем на New Relic все HTTP-запросы и ответы.
Генерируется пользовательская метрика счетчика для Prometheus. Используются путь HTTP-запроса и HTTP-метод.
*/
func (m middleware) LogMiddleware(ctx *gin.Context) {
reqMethodAndPath := fmt.Sprintf("[%s] %s", ctx.Request.Method, ctx.FullPath())
// Длительность ответа на HTTP-запрос
timer := prometheus.NewTimer(metrics.HttpRequestDuration.WithLabelValues(reqMethodAndPath))
defer timer.ObserveDuration()
var responseBody = logging.HandleResponseBody(ctx.Writer)
var requestBody = logging.HandleRequestBody(ctx.Request)
requestId := uuid.NewString()
if hub := sentrygin.GetHubFromContext(ctx); hub != nil {
hub.Scope().SetTag("requestId", requestId)
ctx.Writer = responseBody
}
ctx.Next()
statusCode := ctx.Writer.Status()
// Тот же счетчик пути HTTP-запроса
metrics.HttpRequestCountWithPath.With(prometheus.Labels{"url": reqMethodAndPath}).Inc()
logMessage := logging.FormatRequestAndResponse(statusCode, ctx.Request, responseBody.Body.String(), requestId, requestBody)
if logMessage != "" {
if isSuccessStatusCode(statusCode) {
m.logger.Info(logMessage)
} else {
m.logger.Error(logMessage)
}
}
}
func isSuccessStatusCode(statusCode int) bool {
switch statusCode {
case http.StatusOK, http.StatusCreated, http.StatusAccepted, http.StatusNoContent:
return true
default:
return false
}
}
Пользовательские метрики в Grafana
PromQl => my_http_requests_total_with_path
PromQl =>
rate(http_request_duration_seconds_sum{}[5m])
/
rate(http_request_duration_seconds_count{}[5m])
Разделив показатель суммы на показатель счетчика, получаем среднюю продолжительность каждого запроса за последние пять минут.
Создание веб-хука Slack
У меня уже имеются бот и веб-хук Slack, которым на канал #random в Slack отправляется сообщение.
Создание оповещения в Grafana
По этой ссылке создаем контактную точку оповещения с URL-адресом веб-хука Slack:
Если среднее время ответа на HTTP-запрос больше 0,3 мс, на канал Slack отправляется сообщение с оповещением, это последние пять минут в этом запросе.
Сохраним правило и обратим внимание на состояние работоспособности:
Похоже, работоспособность в норме.
Отправка HTTP-запроса со временем ожидания
Этой строкой время отклика задерживается.
В конечную точку GetUserById отправлено слишком много запросов.
- Время отклика — более 0,5 мс.
- Среднее время отклика увеличилось.
- Появляется тег запуска.
- Похоже, метрика нерабочая.
- Оповещение активировалось, и на канал Slack отправлено сообщение.
Сообщение с оповещением настраивается добавлением аннотаций или указанием пользователей.
Вот репозиторий на GitHub.
Читайте также:
- Как отслеживать среду выполнения Docker с помощью Prometheus и Grafana
- Как создать свой Twitter или управляемое данными приложение с Golang и Kafka
- Почему Go прекрасно подходит для DevOps
Читайте нас в Telegram, VK и Дзен
Перевод статьи Mert ÇAKMAK: Creating Custom Prometheus Metrics in Golang and Sending Alerts to Slack (with Grafana)