-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
Describe the bug
When running an application as a GraalVM native image with percentiles configured, at runtime an error like the following will happen when trying to record e.g. a Timer.
Failed to record timer metrics
java.lang.IllegalArgumentException: java.lang.NoSuchMethodException: org.HdrHistogram.Histogram.<init>(long, long, int)
at org.HdrHistogram.DoubleHistogram.<init>(DoubleHistogram.java:220) ~[na:na]
at org.HdrHistogram.DoubleHistogram.<init>(DoubleHistogram.java:141) ~[na:na]
at org.HdrHistogram.DoubleHistogram.<init>(DoubleHistogram.java:77) ~[na:na]
at io.micrometer.core.instrument.distribution.TimeWindowPercentileHistogram.<init>(TimeWindowPercentileHistogram.java:38) ~[na:na]
at io.micrometer.core.instrument.AbstractTimer.<init>(AbstractTimer.java:85) ~[na:na]
at io.micrometer.prometheus.PrometheusTimer.<init>(PrometheusTimer.java:42) ~[na:na]
at io.micrometer.prometheus.PrometheusMeterRegistry.newTimer(PrometheusMeterRegistry.java:268) ~[na:na]
at io.micrometer.core.instrument.MeterRegistry.lambda$timer$2(MeterRegistry.java:311) ~[actuator-webmvc-metrics:1.8.2]
at io.micrometer.core.instrument.MeterRegistry.getOrCreateMeter(MeterRegistry.java:620) ~[actuator-webmvc-metrics:1.8.2]
at io.micrometer.core.instrument.MeterRegistry.registerMeterIfNecessary(MeterRegistry.java:569) ~[actuator-webmvc-metrics:1.8.2]
at io.micrometer.core.instrument.MeterRegistry.timer(MeterRegistry.java:309) ~[actuator-webmvc-metrics:1.8.2]
at io.micrometer.core.instrument.Timer$Builder.register(Timer.java:403) ~[na:na]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.getTimer(WebMvcMetricsFilter.java:161) ~[na:na]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.lambda$record$0(WebMvcMetricsFilter.java:139) ~[na:na]
at org.springframework.boot.actuate.metrics.AutoTimer.apply(AutoTimer.java:109) ~[actuator-webmvc-metrics:2.6.3]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.record(WebMvcMetricsFilter.java:138) ~[na:na]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:103) ~[na:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[na:na]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[na:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[na:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[na:na]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[na:na]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[na:na]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) ~[na:na]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[na:na]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[na:na]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[na:na]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[na:na]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) ~[na:na]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[na:na]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:895) ~[na:na]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1732) ~[na:na]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[na:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[na:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[na:na]
at java.lang.Thread.run(Thread.java:833) ~[na:na]
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:600) ~[na:na]
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:192) ~[na:na]
Caused by: java.lang.NoSuchMethodException: org.HdrHistogram.Histogram.<init>(long, long, int)
at java.lang.Class.getConstructor0(DynamicHub.java:3585) ~[actuator-webmvc-metrics:na]
at java.lang.Class.getConstructor(DynamicHub.java:2271) ~[actuator-webmvc-metrics:na]
at org.HdrHistogram.DoubleHistogram.<init>(DoubleHistogram.java:178) ~[na:na]
... 41 common frames omitted
Environment
- Micrometer version: 1.8.2
- Micrometer registry: any
- OS: macOS
- Java version: [e.g. output of
java -version
] tested with GraalVM22.0.0.2.r17-grl
To Reproduce
How to reproduce the bug:
In an application with micrometer-core
on the classpath, have a main class like the following. Compile it to a native image and run it.
public static void main(String[] args ) {
MeterRegistry registry = new SimpleMeterRegistry();
Timer timer = Timer.builder("my.timer").publishPercentiles(0.5, 0.9, 0.99).register(registry);
timer.record(5, TimeUnit.MILLISECONDS);
}
Expected behavior
No runtime exception. No additional reflection config required.
Additional context
While it would be ideal if the HdrHistogram library had the necessary native image reflection config provided, we may want to add configuration for the reflection usage we know about from Micrometer code.
The Spring Native project recently added hints for this same issue, but for non-Spring native usage of Micrometer, it would help those users to have it here, or eventually perhaps in HdrHistogram itself.