Duplicate metric error when mapping two MBeans to the same metric with different label
IncandescentChrysalis opened this issue · 10 comments
I have been successfully using the following configuration up until 0.19.0
:
- pattern: '^java.lang<type=Memory><HeapMemoryUsage>committed'
name: jvm_memory_committed_bytes
labels:
area: heap
- pattern: '^java.lang<type=Memory><NonHeapMemoryUsage>committed'
name: jvm_memory_committed_bytes
labels:
area: nonheap
Trying to upgrade to 1.0.1
, I now encounter the following error:
An Exception occurred while scraping metrics: java.lang.IllegalStateException: jvm_memory_committed_bytes: duplicate metric name.
at io.prometheus.metrics.model.registry.PrometheusRegistry.scrape(PrometheusRegistry.java:75)
at io.prometheus.metrics.exporter.common.PrometheusScrapeHandler.scrape(PrometheusScrapeHandler.java:112)
at io.prometheus.metrics.exporter.common.PrometheusScrapeHandler.handleRequest(PrometheusScrapeHandler.java:53)
at io.prometheus.metrics.exporter.httpserver.MetricsHandler.handle(MetricsHandler.java:43)
at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:95)
at jdk.httpserver/sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:82)
at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:98)
at jdk.httpserver/sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:851)
at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:95)
at jdk.httpserver/sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:818)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:840)
How do I add several values to the same metric on distinct labels with 1.0.1
?
@IncandescentChrysalis This appears to be a bug. I have written an integration test and reproduced the issue.
Investigation
The exception is generated from the underlying client_java library.
[duplicate metric name.](https://github.com/prometheus/client_java/blob/ac0a930dd213bc598030af417e58478ba29d669e/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/registry/PrometheusRegistry.java#L60-L80)
In the exporter, we try to reuse the same builder if the rule name matches.
Workaround
To workaround the issue using 1.0.1
until the bug is resolved, you can use different names for each metric.
rules:
- pattern: '^java.lang<type=Memory><HeapMemoryUsage>committed'
name: jvm_memory_committed_heap_bytes
- pattern: '^java.lang<type=Memory><NonHeapMemoryUsage>committed'
name: jvm_memory_committed_nonheap_bytes
Thanks for having taken the time to look into the issue and having improved the tests suite!
The circumvention would wreak havoc in out monitoring system.
The most stable path would be to put the upgrade attempt on hold until this is fixed.
@IncandescentChrysalis are you using the Java agent or the standalone (HTTP) version?
Investigation
I have created a branch with a test that reproduces the issues.
Branch
https://github.com/dhoard/jmx_exporter/tree/issue-988
Integration test
Integration test configuration
@IncandescentChrysalis are you using the Java agent or the standalone (HTTP) version?
Java agent
Investigation
JvmMetrics collector
When using the Java agent exporter, the exporter registers a JvmMetrics
collector for JVM metrics...
The JvmMetrics
collector creates various Jvm metrics...
Reference: https://prometheus.github.io/client_java/instrumentation/jvm/
Exporter rules that define overlapping metrics named collected by the JvmMetrics
collector will result in an exception...
An Exception occurred while scraping metrics: java.lang.IllegalStateException: jvm_memory_committed_bytes: duplicate metric name.
at io.prometheus.metrics.model.registry.PrometheusRegistry.scrape(PrometheusRegistry.java:75)
at io.prometheus.metrics.exporter.common.PrometheusScrapeHandler.scrape(PrometheusScrapeHandler.java:112)
at io.prometheus.metrics.exporter.common.PrometheusScrapeHandler.handleRequest(PrometheusScrapeHandler.java:53)
at io.prometheus.metrics.exporter.httpserver.MetricsHandler.handle(MetricsHandler.java:43)
at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:95)
at jdk.httpserver/sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:82)
at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:98)
at jdk.httpserver/sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:851)
at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:95)
at jdk.httpserver/sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:818)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:840)
Solution
-
Remove exporter configuration rules that define conflicting metric names. (The
JvmCollector
is already exposing the metrics.) -
Use an alternate metric names.
I am unsure if the status: waiting on feedback
tag is targeted at the requester.
If that is the case, my original question stands
How do I add several values [from distinct MBeans] to the same metric on distinct labels with 1.0.1?
As of now, there is a functional regression, upgrading a working configuration achieving this from 0.19.0
@IncandescentChrysalis The code is working as designed/documented in the 1.0.1 release announcement (https://github.com/prometheus/jmx_exporter/tree/release-1.0.1/docs) and client_java
documentation https://prometheus.github.io/client_java/instrumentation/jvm/
Solution
-
Remove exporter configuration rules that define conflicting metric names. (The JvmCollector is already exposing the metrics.)
-
Use a(n) alternate metric name(s).
-
Add additional labels such that metric + labels do not conflict.
I finally understood what is happening.
The JVM metrics, originally managed by the current exporter directly, is now off-handed to your client_java
library.
hence, the exporter at hand does not manage JVM metrics anymore and any definition referencing them shall be removed, generating a conflict otherwise, which is what happened to be my case.
This is a major functional change which is not particularly underlined in the 1.*
documentation.
The solution for me was to remove any definition to JVM metrics on my JMX exporter configuration. We were lucky enough not to endure any breaking change, as the metrics & labels name we had defined were exactly the same as the ones client_java
generates.
Moreover, there is no control over JVM metrics anymore since you hardcode the use of client_java
's JvmMetrics
.
If someone wished control over which JVM metrics to expose with 0.*
, 1.*
will have this ability removed.
This could also be underlined.
@IncandescentChrysalis previous versions of the exporter used an older version of client_java
which exposed JVM metrics but didn't correctly enforce metric uniqueness (metric name + labels)
You could have duplicate metrics with potentially different values.
The change was required to support upcoming OpenTelemetry support and is referenced here...
https://github.com/prometheus/jmx_exporter/tree/release-1.0.1/docs#notes
https://github.com/prometheus/jmx_exporter/releases/tag/1.0.1
... but I'm sure it could be improved.