Оглавление
Введение
На одном из проектов передо мной стояла задача по включению метрик-счетчиков на маршрутах при штатном прохождении и при отклонении запросов.
Дано:
Spring Boot (2.5.6) для инъекции зависимостей, безопасности, предоставления веб-страничек для служебных целей.
Apache Camel (3.13.0) для маршрутизации запросов, троттлинга, направления метрик по каждому маршруту в точку сбора (в нашем случае /actuator/prometheus).
Micrometer (1.18.0) для сбора метрик и выставления их по адресу /actuator/prometheus.
Популярный подход
Самый частый подход, который мне встречался в интернете (во всех статьях от 2016 года и новее, а также во многих видео) состоит в следующем:
Добавление следующей зависимости
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-micrometer-starter</artifactId>
</dependency>
Добавление следующей записи в application.properties файл
camel.component.metrics.metric-registry=prometheusMeterRegistry
Создание следующего кода в конфигурационном классе:
@Bean
public CamelContextConfiguration camelContextConfiguration() {
return new CamelContextConfiguration() {
@Override
public void beforeApplicationStart(CamelContext camelContext) {
camelContext.addRoutePolicyFactory(new MicrometerRoutePolicyFactory());
camelContext.setMessageHistoryFactory(new MicrometerMessageHistoryFactory());
}
@Override
public void afterApplicationStart(CamelContext camelContext) {
}
};
}
По сообщениям и по результатам на видео это должно приводить к появлению стандартных метрик Apache Camel на странице /actuator/prometheus, таких как CamelMessageHistory_seconds_count, и, в дальнейшем, возможности добавлять свои метрики, пользуясь синтаксисом micrometer:counter:simple.counter.
Проблема
В моём случае проблема заключается в том что у меня это не работает.
Попытки (ход) решения
-
Попробовал учесть староватость способа приведённого выше и перебрал кучу комбинаций версий зависимостей (в данном случае у меня была некоторая гибкость):
Spring Boot 2.4.2 - 2.5.6
Apache Camel 3.8.0 - 3.13.0
io.micrometer 1.7.2 - 1.8.0
Множество раз проверил код на опечатки. Попутно выяснил что они присутствуют во многих местах в интернете на данную тему, включая документацию Apache Camel (речь про похожесть синтаксиса метрик через metrics: и micrometer: )
Много дебаггинга разных мест из моего сервиса, Apache Camel, Spring Boot, Micrometer.
В процессе дебаггинга выяснилось слушатель канала micrometer: не "видит" ссылку на prometheusMeterRegistry.
Попытался прописать явно добавление PrometheusMeterRegistry
@Bean(name = { MicrometerConstants.METRICS_REGISTRY_NAME })
public PrometheusMeterRegistry prometheusMeterRegistry() {
return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
}
Это не решило проблему в полной мере. По ссылке /actuator/metrics всё-таки появились искомые метрики (как дефолтные от Apache Camel, так и новые, добавленные в коде). Но на странице /actuator/prometheus метрики Apache Camel не появлялись, а также использование micrometer:counter:simple.counter не добавляет simple.counter к списку метрик.
Метрики удаётся добавить в список примерно следующим способом:
@Bean
public void initCounter(MeterRegistry meterRegistry) {
Counter.builder("simple.counter")
.register(meterRegistry);
}
Но в таком случае они не обновляются на странице /actuator/prometheus и имеют константное значение - 0.
Ещё после некоторого дебага выяснилась следующая картина - в экземпляре CamelContext лежит 3 объекта MeterRegistry (один JmxMeterRegistry и два PrometheusMeterRegistry). Что говорит о том что где-то инициализируется ещё один PrometheusMeterRegistry помимо описанного выше.
Так и есть, spring-boot-actuator-autoconfigure имеет свой Bean с данным типом.
Как итог - остаётся проинициализировать и для /actuator и для Apache Camel один и тот же bean.
Финальное (моё) решение
Итоговое решение выглядит так:
Добавить зависимость:
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-micrometer-starter</artifactId>
<version>${org.apache.camel.springboot.version}</version>
</dependency>
Объявить @Bean следующим образом
@Bean(name = { MicrometerConstants.METRICS_REGISTRY_NAME, "prometheusMeterRegistry" })
public PrometheusMeterRegistry prometheusMeterRegistry(
PrometheusConfig prometheusConfig, CollectorRegistry collectorRegistry, Clock clock) {
return new PrometheusMeterRegistry(prometheusConfig, collectorRegistry, clock);
}
В данном случае у нас среди MeterRegistry оказываются всего один JmxMeterRegistry и один PrometheusMeterRegistry который доступен и для ApacheCamel и для Spring Boot Actuator.
Также сразу заметен результат работы данного решения, а именно - по адресу /actuator/prometheus доступны как метрики Apache Camel так и кастомные:
Заключение
По итогу проделанной работы было найдено рабочее решение по интеграции Apache Camel метрик в Spring Boot Actuator и проброской их в Prometheus.
Спасибо за внимание.
Комментарии (3)
chemtech
04.12.2021 12:57Спасибо за пост. Подскажите, пожалуйста, если знаете. Есть проект https://github.com/spring-petclinic/spring-petclinic-cloud
Я пытаюсь запустить spring-petclinic-cloud в kubernetes. Получаю ошибку
java.net.UnknownHostException: wavefront-proxy
Как развернуть Spring-Petclinic-Cloud на k8s без
wavefront
?Issue есть https://github.com/spring-petclinic/spring-petclinic-cloud/issues/39
Shmaiser
У меня все настроено как описано в доках, ну плюс явно обновляю счетчики и таймеры в рутах когда надо:
.to("micrometer:counter:events.counter?tags=type=my_type,my_other_tag=zzz")
.to("micrometer:timer:events.timer?tags=type=my_type,my_other_tag=zzz")
RoutePolicy фабрику я добавляю до старта camel context
и плюс включить
management.endpoint.metrics.enabled=true
management.endpoint.prometheus.enabled=true
MasteR_GeliOS Автор
Только что попробовал сделать у себя в тестовом проекте так как вы и описали - без объявленного моим способом PrometheusMeterRegistry не срабатывает.
Даже частичного срабатывания (когда метрики есть по адресу /actuator/metrics но не попадают или не обновляются в /actuator/prometheus) у меня не происходит.