Микрометр - Prometheus Gauge отображает NaN - PullRequest
0 голосов
/ 12 июня 2018

Я пытаюсь сгенерировать метрики Prometheus с помощью Micrometer.io с Spring Boot 2.0.0.RELEASE.

Когда я пытаюсь выставить размер списка в качестве индикатора, он продолжает отображатьсяNaN.В документации говорится, что;

Вы несете ответственность за точное указание объекта измерения, который вы измеряете с помощью датчика.

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

import io.micrometer.core.instrument.*;
import io.swagger.backend.model.Product;
import io.swagger.backend.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@RestController
@RequestMapping("metrics")
public class ExampleController {

    private AtomicInteger atomicInteger = new AtomicInteger();

    private ProductService productService;
    private final Gauge productGauge;

    @Autowired
    public HelloController(ProductService productService,
                           MeterRegistry registry) {

        this.productService = productService;

        createGauge("product_gauge", productService.getProducts(), registry);
    }

    private void createGauge(String metricName, List<Product> products,
                                    MeterRegistry registry) {

        List<Product> products = productService.getProducts();

        // #1
        // this displays product_gauge as NaN
        AtomicInteger n = registry.gauge("product_gauge", new AtomicInteger(0));
        n.set(1);
        n.set(2);

        // #2
        // this also displays product_gauge as NaN
        Gauge
            .builder("product_gauge", products, List::size)
            .register(registry);

        // #3
        // this displays also NaN
        testListReference = Arrays.asList(1, 2);
        Gauge
            .builder("random_gauge", testListReference, List::size)
            .register(registry);

        // #4
        // this also displays NaN
        AtomicInteger currentHttpRequests = registry.gauge("current.http.requests", new AtomicInteger(0));
    }

    @GetMapping(path = "/product/decrement")
    public Counter decrementAndGetProductCounter() {
        // decrement the gague by one
    }
}

Кто-нибудь может помочь с этой проблемой?Любая помощь будет оценена.

Ответы [ 4 ]

0 голосов
/ 28 июня 2019

У меня была такая же проблема с датчиками Micrometer.io, когда я использовал ваш метод # 1 meterRegistry.gauge("myGauge", new AtomicDouble()).Кстати, я использую Scala.Я заметил, что после того, как я создал около 50 датчиков, новые датчики после этого отображали NaN.

Вместо этого я использовал:

val atomicDouble = new AtomicDouble()
Gauge
  .builder("myGauge", atomicDouble, new AtomicDoubleToDoubleFunction)
  .strongReference(true)
  .register(meterRegistry)

с

class AtomicDoubleToDoubleFunction extends ToDoubleFunction[AtomicDouble] {
  override def applyAsDouble(value: AtomicDouble): Double = value.doubleValue()
}

Это исправило проблему NaN, и все мои датчики отображаются правильно.Я нашел .strongReference(true) пример из https://www.codota.com/code/java/classes/io.micrometer.core.instrument.Gauge.

0 голосов
/ 03 января 2019

мой пример для датчика с использованием

private final AtomicLong countTryUsers = new AtomicLong(0);
Metrics.gauge("app.countTry", countTryUsers);

public void updateCountTryUsers(Long countTryUsersDb){
   countTryUsers.set(countTryUsersDb);
}

, поэтому я регистрирую app.countTry только один раз, а затем просто обновляю AtomicLong countTryUsers через пользовательский метод updateCountTryUsers ()

0 голосов
/ 22 января 2019

Я не смог использовать решение @panser, потому что я использую датчики с метками.Мое решение заключалось в создании com.google.common.util.concurrent.AtomicDouble кэша с ключом и значениями io.micrometer.core.instrument.Tag в качестве ключа карты, вот так:

    private static final Map<String, AtomicDouble> GAUGE_CACHE = new HashMap<>();

    public void handleGauge(String name, List<Tag> tags, double value) {
        String gaugeKey = this.gaugeKey(name, tags);
        if (!GAUGE_CACHE.containsKey(gaugeKey)) {
            GAUGE_CACHE.put(gaugeKey, new AtomicDouble());
        }
        Objects.requireNonNull(this.registry.gauge(name, tags, GAUGE_CACHE.get(gaugeKey))).set(value);
    }

    private String gaugeKey(String name, List<Tag> tags) {
        return name + ":" + tags.stream().map(tag -> tag.getKey() + tag.getValue()).collect(Collectors.joining(""));
    }

Это сработало очень хорошо для моих нужд, надеюсь, поможет другим людям.

0 голосов
/ 26 июня 2018

Во всех случаях вы должны иметь строгую ссылку на наблюдаемый экземпляр.Когда ваш метод createGauge() завершен, все выделенные ссылки на стек функций могут быть использованы для сборки мусора.

Для #1, передайте поле atomicInteger следующим образом: registry.gauge("my_ai", atomicInteger);.Затем увеличивайте / уменьшайте по своему желанию.Всякий раз, когда микрометр должен запросить его, он будет искать, пока не найдет ссылку.

Для #2, передайте поле productService и лямбду.По сути, всякий раз, когда датчик запрашивается, он будет вызывать лямбду с указанным объектом: registry.gauge("product_gauge", productService, productService -> productService.getProducts().size());

(никаких гарантий относительно синтаксических ошибок.)

...