Как зарегистрировать Микрометр Таймер с SLA и тегами? - PullRequest
0 голосов
/ 16 мая 2018

Я пытаюсь перенести мои метрики Прометея в микрометры, но теперь я застрял здесь с одной вещью ...

На данный момент у меня есть гистограмма Прометея, настроенная следующим образом:

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);

Ok. Давайте посмотрим, как я хочу это использовать ... На данный момент я просто звоню

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));

Но проблема сейчас в том, что Микрометр жалуется, что я ранее настроил метрику без этих тегов. Конечно, я сделал, потому что я не знаю значения на тот момент. Вот исключение:

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].

Ok. Итак, я подумал, тогда давайте определим сегменты с помощью вызова Metrics.timer. Но это не работает, потому что нет способа передачи этих значений.

Итак ... Как я могу установить sla сегментов и tags для моей метрики?

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Во-первых, лучше всего использовать точечные разделители между именными частями. Это сохраняет метрику нейтральной в зависимости от поставщика, поэтому, если вы когда-нибудь решите отправить что-то иное, чем Прометей, это сработает! Другими словами, лучше всего записать его как 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
}

Для WebMvcTagsProvider#httpRequestTags имеется параметр handler, из которого можно вывести тип и метод.

0 голосов
/ 16 мая 2018

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

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(...), как указано вышеМикрометр вызовет этот фильтр и применит всю конфигурацию, указанную здесь.Этот фильтр вызывается только при инициализации счетчика, т. Е. Когда Metrics.timer(...) вызывается в первый раз с указанными name и tags.Поэтому нам не нужно беспокоиться о производительности здесь.

...