Micrometer - Prometheus Gauge displays NaN

后端 未结 4 1138
一个人的身影
一个人的身影 2021-02-20 12:59

I am trying to generate Prometheus metrics with using Micrometer.io with Spring Boot 2.0.0.RELEASE.

When I am trying to expose the size of a List as Gauge, it ke

相关标签:
4条回答
  • 2021-02-20 13:42

    my example for gauge using

    private final AtomicLong countTryUsers = new AtomicLong(0);
    Metrics.gauge("app.countTry", countTryUsers);
    
    public void updateCountTryUsers(Long countTryUsersDb){
       countTryUsers.set(countTryUsersDb);
    }
    

    so I register app.countTry just once, and then just update AtomicLong countTryUsers over custom method updateCountTryUsers()

    0 讨论(0)
  • 2021-02-20 13:52

    I wasn't able to use @panser solution 'cause I'm using gauges with labels. My solution involved the creation of com.google.common.util.concurrent.AtomicDouble cache with io.micrometer.core.instrument.Tag's key and values as map key, heres goes:

        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(""));
        }
    

    That worked pretty well for my needs, hopefully help other people.

    0 讨论(0)
  • 2021-02-20 13:59

    In all cases, you must hold a strong reference to the observed instance. When your createGauge() method is exited, all function stack allocated references are eligible for garbage collection.

    For #1, pass your atomicInteger field like this: registry.gauge("my_ai", atomicInteger);. Then increment/decrement as you wish. Whenever micrometer needs to query it, it will as long as it finds the reference.

    For #2, pass your productService field and a lambda. Basically whenever the gauge is queried, it will call that lambda with the provided object: registry.gauge("product_gauge", productService, productService -> productService.getProducts().size());

    (No guarantee regarding syntax errors.)

    0 讨论(0)
  • 2021-02-20 14:00

    I had the same issue with Micrometer.io gauges when I used your method #1 meterRegistry.gauge("myGauge", new AtomicDouble()). I am using Scala by the way. I noticed that after I created about 50 gauges, the new gauges after that displayed NaN.

    Instead I used:

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

    with

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

    This fixed the NaN issue, and all of my gauges appear correctly. I found the .strongReference(true) example from https://www.codota.com/code/java/classes/io.micrometer.core.instrument.Gauge .

    0 讨论(0)
提交回复
热议问题