Мониторинг приложения Spring Boot с помощью Micrometer, Prometheus и Grafana, используя пользовательские метрики

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Важно отслеживать показатели и работоспособность приложения: это помогает нам повышать производительность, лучше им управлять и замечать неоптимизированное поведение. Мониторинг каждого сервисного модуля важен для поддержания системы, состоящей из множества микросервисов.

В этой статье я покажу, как можно мониторить веб-приложение Spring Boot с помощью Micrometer, который отображает метрики нашего приложения, Prometheus, который хранит их, и Grafana для визуализации этих данных в виде графиков.

Имплементировать эти инструменты довольно легко, добавив всего несколько конфигураций. В дополнение к стандартным метрикам JVM я покажу, как можно предоставлять кастомные, например, счетчик пользователей.

Spring Boot

Основой для нашего демо является приложение Spring Boot, которое мы инициализируем с помощью Spring Initializr:

Мы инициализировали проект с помощью spring-boot-starter-actuator, который уже предоставляет production-ready endpoints (конечные точки, готовые к продакшену).

Если мы запустим наше приложение, то увидим, что некоторые конечные точки, такие как health и info, уже по умолчанию экспонированы в эндпойнт /actuator.

При запуске конечной точки /actuator/health мы получаем метрику, если служба запущена и работает:

▶ http GET "http://localhost:8080/actuator/health"
HTTP/1.1 200
Connection: keep-alive
Content-Type: application/vnd.spring-boot.actuator.v3+json
Date: Wed, 21 Oct 2020 18:11:35 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked

{
    "status": "UP"
}

Spring Boot Actuator может быть интегрирован в Spring Boot Admin, который предоставляет визуальный интерфейс администратора для вашего приложения. Но такой подход не очень популярен и имеет некоторые ограничения. Поэтому мы используем Prometheus вместо Spring Boot Actuator и Grafana вместо Spring Boot Admin, чтобы получить более популярное и независимое от фреймворка/языка решение.

Для данного подхода необходимы платформонезависимые метрики, и Micrometer является наиболее популярным инструментом в данном случае.

Micrometer

Micrometer предоставляет простой фасад поверх клиентов инструментария наиболее популярных систем мониторинга, позволяя вам выполнять инструментарий кода приложений на базе JVM без привязки к производителю. Вспомните мигратор SLF4J, но для метрик.

Micrometer является проектом с открытым исходным кодом и предоставляет метрический фасад, который отображает метрические данные в независимом от поставщика формате, понятном системе мониторинга. 

Micrometer не является частью экосистемы Spring и должен быть добавлен в качестве зависимости. В нашем демонстрационном приложении это уже было сделано в конфигурации Spring Initializr.

Следующим шагом будет отображение метрик Prometheus в application.properties:

management.endpoints.web.exposure.include=prometheus,health,info,metric

Теперь мы можем запустить эту конечную точку и увидеть метрики Prometheus:

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

Мы также можем определить некоторые пользовательские метрики, которые я продемонстрирую в этом разделе. Демо содержит класс Scheduler, который периодически запускает встроенный метод schedulingTask.

Чтобы иметь возможность отправлять пользовательские метрики, нам нужно импортировать MeterRegistry из библиотеки Micrometer и вставить его в наш класс. Более подробную информацию можно найти в официальной документации.

Из MeterRegistry можно инстанцировать следующие типы счетчиков:

  • Counter: сообщает только о результатах подсчета указанного свойства приложения.

  • Gauge: показывает текущее значение измерительного прибора

  • Timers: измеряет задержки или частоту событий

  • DistributionSummary: обеспечивает дистрибуцию событий и простую итоговую сводку.

Я реализовал counter и gaude в демонстрационных целях:

@Component
public class Scheduler {

  private final AtomicInteger testGauge;
  private final Counter testCounter;

  public Scheduler(MeterRegistry meterRegistry) {
    // Counter vs. gauge, summary vs. histogram
    // https://prometheus.io/docs/practices/instrumentation/#counter-vs-gauge-summary-vs-histogram
    testGauge = meterRegistry.gauge("custom_gauge", new AtomicInteger(0));
    testCounter = meterRegistry.counter("custom_counter");
  }

  @Scheduled(fixedRateString = "1000", initialDelayString = "0")
  public void schedulingTask() {
    testGauge.set(Scheduler.getRandomNumberInRange(0, 100));

    testCounter.increment();
  }

  private static int getRandomNumberInRange(int min, int max) {
    if (min >= max) {
      throw new IllegalArgumentException("max must be greater than min");
    }

    Random r = new Random();
    return r.nextInt((max - min) + 1) + min;
  }
}

Если мы запустим приложение, то увидим, что наши пользовательские метрики отображаются через конечную точку actuatuor/prometheus:

▶ http GET "http://localhost:8080/actuator/prometheus" | grep custom
# HELP custom_gauge
# TYPE custom_gauge gauge
custom_gauge 29.0
# HELP custom_counter_total
# TYPE custom_counter_total counter
custom_counter_total 722.0

Поскольку теперь у нас есть метрики в формате, понятном Prometheus, посмотрим, как его настроить.

Prometheus

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

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

global:
    scrape_interval: 10s # How frequently to scrape targets by default
  
scrape_configs:
    - job_name: 'spring_micrometer'         # The job name is assigned to scraped metrics by default.
      metrics_path: '/actuator/prometheus'  # The HTTP resource path on which to fetch metrics from targets.
      scrape_interval: 5s                   # How frequently to scrape targets from this job.
      static_configs:                       # A static_config allows specifying a list of targets and a common label set for them
        - targets: ['192.168.178.22:8080']

Все доступные варианты конфигурации описаны в официальной документации.

Поскольку мы хотим запустить Prometheus в контейнере Docker, необходимо указать Prometheus наш IP-адрес взамен localhost в static_configs -> targets. Вместо localhost:8080 выбираем 192.168.178.22:8080, где 192.168.178.22 - это мой IP-адрес в данный момент. Чтобы узнать IP-адрес вашей системы, используйте ifconfig или ipconfig в терминале в зависимости от вашей операционной системы.

Теперь мы готовы к запуску Prometheus:

docker run -d -p 9090:9090 -v <path-to-your-prometheus.yml>:/etc/prometheus/prometheus.yml prom/prometheus

<path-to-your-prometheus.yml> это должен быть путь, куда вы поместили конфигурационный файл prometheus.yml, описанный выше.

Наконец, мы можем открыть Prometheus на сайте http://localhost:9090 в веб-браузере и найти нашу пользовательскую метрику с именем custom_gauge:

Чтобы проверить, что Prometheus правильно прослушивает наше локально запущенное приложение Spring Boot, мы можем перейти в Status -> Targets на главной верхней навигационной панели:

Prometheus предоставляет язык запросов PromQL, более подробную информацию можно найти в официальной документации.

Grafana

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

Grafana может получать данные из различных источников данных, таких как Prometheus, Elasticsearch, InfluxDB и др. Она также позволяет настраивать на основе правил оповещения, которые затем могут уведомлять вас через Slack, Email, Hipchat и т.п.

Мы запускаем Grafana также локально в контейнере Docker:

docker run -d -p 3000:3000 grafana/grafana

При открытии http://localhost:3000 в браузере должна появиться следующая страница авторизации:

Вы можете войти в систему, используя стандартное имя пользователя admin и пароль admin. После входа следует изменить эти пароли по умолчанию, посетив страницу http://localhost:3000/profile/password.

Первым шагом будет добавление нашего локального Prometheus в качестве источника данных:  

Дашборд сообщества

Первая приборная панель, которую мы хотим добавить, - это дашборд сообщества. Поскольку в качестве приложения используется Spring Boot, выбираем популярную панель JVM:

После загрузки URL мы видим импортированный дашборд:

Пользовательский дашборд метрик

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

Теперь мы видим новый дашборд, где мы можем создать новую панель:

На первой панели мы добавляем отображение для нашей метрики custom_gauge. Я использую визуализацию Stat, так как она показывает текущее значение и простой график:

Кроме того, в дашборд добавляется новая панель для метрики custom_counter:

В итоге дашборд выглядит следующим образом:

Заключение

Важно контролировать метрики и работоспособность приложения: это помогает нам повысить производительность, лучше управлять приложением и замечать неоптимизированное поведение. Мониторинг каждой службы важен для поддержания системы, состоящей из множества микросервисов.

В этой статье я показал, как можно мониторить веб-приложение Spring Boot с помощью Micrometer, отображающего метрики нашего приложения; Prometheus, хранящего данные метрик; Graphana для визуализации данных в виде графиков.

Этот популярный подход к мониторингу должен способствовать поддержке ваших приложений и радовать клиентов.

Как всегда, код демонстрации, использованной в этой статье, можно найти на GitHub.


Перевод материала подготовлен для будущих студентов курса "Observability: мониторинг, логирование, трейсинг". Всех желающих приглашаем на открытый урок "Grafana: формирование дашбордов". На занятии мы:
— проанализируем возможности по формированию дашбордов;
— разберем, как использовать дашборды и тиражирование, а также переменные;
— посмотрим формирование дашбордов для различных окружений.
Регистрация по ссылке.

Источник: https://habr.com/ru/company/otus/blog/650871/


Интересные статьи

Интересные статьи

Data Science — это не только данные о клиентах. К старту нашего флагманского курса рассмотрим пример геопространственной семантической сегментации, где с помощью данных цифровой модели рельефа отобраз...
Большинство наших приложений зависят от внешних сервисов, например серверов баз данных, SMS-шлюзов и систем наподобие PayPal. Эти сервисы могут существовать более чем в одной среде, то есть в сре...
Вторая часть истории про слияние репозиториев. Суть проблемы вкратце такова: надо слить репозиторий с подрепозиторием с сохранением истории. Решение на gitpython работал...
Данная статья будет состоять из 3 частей (Теория/Методы и алгоритмы для решение задач/Разработка и реализация на Java) для описания полной картины. Первая статья будет включать только...
Мощность современных процессоров растёт, как в стационарных компьютерах, так и в различных embedded устройствах, на борту которых процессоры на базе ARM с операционной системой linux....