Я пытаюсь перенести свои метрики Prometheus на микрометр, но теперь я застрял в одном ...
На данный момент у меня гистограмма Прометея настроена следующим образом:
private static final Histogram REQUEST_DURATION = Histogram
.build("http_request_duration_milliseconds", "Duration in milliseconds for processing a request.")
.labelNames("http_method", "http_status", "java_class", "java_method")
.buckets(10, 25, 50, 100, 500, 1000)
.register();
Поэтому для перехода на микрометр я заменил его следующим образом:
Timer.builder("http.request.duration")
.description("Duration in seconds for processing a request.")
.sla(Duration.ofMillis(10), Duration.ofMillis(25), Duration.ofMillis(50), Duration.ofMillis(100), Duration.ofMillis(500), Duration.ofMillis(1000), Duration.ofMillis(5000))
.register(registry);
ОК. Посмотрим, как я хочу его использовать ... На данный момент я просто звоню
REQUEST_DURATION.labels(httpMethod, httpStatus, javaClass, javaMethod).observe(milliseconds);
Поэтому я заменил это на
Metrics.timer("http.request.duration",
"http.method", httpMethod,
"http.status", httpStatus,
"java.class", javaClass,
"java.method", javaMethod)
.record(Duration.ofNanos(nanoseconds));
Но проблема в том, что Micrometer жалуется на то, что я ранее настраивал метрику без этих тегов. Конечно, знал, потому что на тот момент я не знал ценностей. Здесь исключение:
java.lang.IllegalArgumentException: Prometheus requires that all meters with the same name have the same set of tag keys. There is already an existing meter containing tag keys []. The meter you are attempting to register has keys [http.method, http.status, java.class, java.method].
ОК. Итак, я подумал, тогда давайте укажем ведра с вызовом Metrics.timer. Но это не работает, потому что нет способа передать эти значения.
Итак ... Как я могу установить корзины slaа также на tags для моей метрики?




Я получил ответ на Канал зазора микрометра. Микрометрический способ решения этой проблемы заключается не в регистрации самой метрики, а в зарегистрировать фильтр следующим образом:
registry.config().meterFilter(new MeterFilter() {
@Override
public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) {
if (id.getName().equals("http.request.duration")) {
return DistributionStatisticConfig.builder()
.sla(Duration.ofMillis(10).toNanos(),
Duration.ofMillis(25).toNanos(),
Duration.ofMillis(50).toNanos(),
Duration.ofMillis(100).toNanos(),
Duration.ofMillis(500).toNanos(),
Duration.ofMillis(1000).toNanos(),
Duration.ofMillis(5000).toNanos())
.build()
.merge(config);
}
return config;
}
});
При вводе значения метрики с помощью Metrics.timer(...), как указано выше, Micrometer вызовет этот фильтр и применит всю указанную здесь конфигурацию. Этот фильтр вызывается только при инициализации счетчика, то есть когда Metrics.timer(...) вызывается в первый раз с этими конкретными name и tags. Так что нам не нужно беспокоиться о производительности здесь.
Во-первых, между частями имени лучше всего использовать разделители точек. Это сохраняет метрику нейтральной для поставщика, поэтому, если вы когда-нибудь решите отправить товар чему-либо, кроме Prometheus, это сработает! Другими словами, лучше всего записывать его как http.request.duration. Когда применяется соглашение об именах Prometheus, он будет отображаться как http_request_duration_seconds.
Если это приложение Spring Boot, вы можете объявить SLA в фильтр счетчика на основе свойств:
management.metrics.distribution.sla.http.request.duration=10ns,25ns,50ns,100ns,500ns,1000ns,5000ns
Если вы используете Spring Boot 1.x, вам придется избегать имени, как описано в документации здесь.
Кстати, Spring уже длительность запроса автоматически записывает с метрикой http_server_requests. На нем нет класса Java и метода Java, но есть метод и статус, а также несколько других вещей, которых у вас здесь нет. У вас есть возможность переопределить WebMvcTagsProvider для предоставления дополнительных тегов (включая класс и метод Java):
@Bean
WebMvcTagsProvider requestTags() {
return customProvider; // can be extended from DefaultWebMvcTagsProvider
}
Для handler есть параметр WebMvcTagsProvider#httpRequestTags, по которому вы можете определить тип и метод.
О, круто! Доступны ли эти свойства уже в Spring Boot 1? Потому что в моем случае я пока не могу перейти на версию 2.
Вы можете включить micrometer-spring-legacy и micrometer-registry-prometheus в качестве зависимостей в свое приложение Spring Boot 1, и вы готовы к работе. Нет необходимости вручную настраивать конечные точки / контроллеры MVC. Кроме того, вы бесплатно получаете целый набор автоматически настраиваемых показателей JVM.
Спасибо за подсказку с точками. У меня это уже было в моем коде, но я забыл обновить его здесь. Я обновил свой код сейчас.
Что касается http_server_requests ... Я знаю, что Spring уже записывает его. Но он записывает не имя класса java и имя метода, а только путь. Кроме того, он не настраивает эти сегменты, ... но теперь я думаю, что могу установить сегменты с помощью параметра конфигурации.
@Ethan Обновил ответ, чтобы показать вам, как добавить класс / метод Java в инструментарий Spring по умолчанию. Как правило, мы не добавляем SLA / процентили и т. д. К таймерам по умолчанию, а позволяем вам добавлять их по своему усмотрению с помощью подобных свойств.
Хорошо .. только что понял, что в этом случае я должен использовать
TimerвместоDistributionSummary. Обновлю вопрос.