我正在尝试使用带有Spring Boot 2.0.0.RELEASE的Micrometer.io生成Prometheus指标。
当我尝试将List的大小公开为Gauge时,它会一直显示NaN。它在文档中说明了这一点;
您有责任对使用Gauge测量的状态对象进行强有力的参考。
我尝试了一些不同的方法,但我无法解决问题。这是我的代码,有一些试验。
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
}
}
有没有人可以帮助解决这个问题?任何帮助将不胜感激。
答案 0 :(得分:2)
在所有情况下,您必须对观察到的实例保持强烈的引用。当您退出createGauge()
方法时,所有分配给函数堆栈的引用都可以进行垃圾回收。
对于#1
,请像这样传递您的atomicInteger
字段:registry.gauge("my_ai", atomicInteger);
。然后根据需要增加/减少。每当千分尺需要查询时,只要找到参考,就可以。
对于#2
,请传递您的productService
字段和一个lambda。基本上,每当查询量规时,它将使用提供的对象调用registry.gauge("product_gauge", productService, productService -> productService.getProducts().size());
(不保证语法错误。)
答案 1 :(得分:0)
我的量规使用示例
private final AtomicLong countTryUsers = new AtomicLong(0);
Metrics.gauge("app.countTry", countTryUsers);
public void updateCountTryUsers(Long countTryUsersDb){
countTryUsers.set(countTryUsersDb);
}
所以我只注册一次 app.countTry ,然后通过自定义方法updateCountTryUsers()更新AtomicLong countTryUsers
答案 2 :(得分:0)
我无法使用@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(""));
}
对于我的需求来说效果很好,希望可以帮助其他人。
答案 3 :(得分:0)
使用#1 meterRegistry.gauge("myGauge", new AtomicDouble())
方法时,我在Micrometer.io压力计上遇到了同样的问题。我正在使用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
问题,并且我的所有仪表都正确显示了。我从https://www.codota.com/code/java/classes/io.micrometer.core.instrument.Gauge找到了.strongReference(true)
的例子。