-1

I want to monitor a value from my database. This value could increase and decrease, so I use a gauge. I have no instance variable for this value, so I use a method reference instead of a object reference. The gauge calls this method automatically.

For performance reasons I don't want to call the method periodically. How can I trigger the gauge only on demand?

Code

@SpringBootApplication
public class TestApplication {

  @Autowired private TestController testController;
  @Autowired private MeterRegistry meterRegistry;

  public static void main(String[] args) {
    SpringApplication.run(TestApplication.class, args);
  }

  @Bean
  public Gauge myGauge() {
    return Gauge.builder("test_gauge", testController::calc).register(meterRegistry);
  }
}
@RestController
@Slf4j
public class TestController {

  public Double calc() {

    // read value from database
    Double d = RandomUtils.nextDouble();
    log.info("Called with value {}", d);

    return d;
  }

  @GetMapping(path = "/call")
  public String call(@RequestParam(name = "value") Integer value) {

    // save value to database

    // trigger gauge

    return "ok";
  }
}

Logs

The method is called every 15 seconds when Prometheus is scraping the metrics.

2022-12-16 15:12:17.556  INFO 6260 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
2022-12-16 15:12:18.039  INFO 6260 --- [nio-8081-exec-1] test.TestController                      : Called with value 1.1228275083891679E306
2022-12-16 15:12:32.778  INFO 6260 --- [nio-8081-exec-2] test.TestController                      : Called with value 6.136924711044749E307
2022-12-16 15:12:44.798  INFO 6260 --- [nio-8081-exec-3] test.TestController                      : Called with value 4.914434799158517E307
2022-12-16 15:12:58.095  INFO 6260 --- [nio-8081-exec-5] test.TestController                      : Called with value 1.2183342676183758E308

Metric

The actuator endpoint prometheus returns the gauge metric.

# HELP test_gauge  
# TYPE test_gauge gauge
test_gauge{application="test-service",} 1.2183342676183758E308
dur
  • 15,689
  • 25
  • 79
  • 125

1 Answers1

0

You can write a method that updates the value less frequently or on whatever trigger you want and return some default value or the old value. E.g. only update the value if it is older than X:

AtomicLong lastCalculatedTime = new AtomicLong(0);
AtomicLong gaugeValue = new AtomicLong(0);
Gauge.builder("expensive", () -> {
    long curr = System.nanoTime();
    return gaugeValue.updateAndGet(old ->
            lastCalculatedTime.updateAndGet(ts -> curr - ts > 10_000 ? curr : ts) == curr ? 0L /* new */ : old);
});
Jonatan Ivanov
  • 4,895
  • 2
  • 15
  • 30