-
Notifications
You must be signed in to change notification settings - Fork 831
Add GC duration histogram #1854
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ff3ece3
b2e2af3
6423922
683150b
298717f
c5d1b90
94ac2d6
2f73e11
5d925cc
d0e8172
447d0a3
20cc588
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,8 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| package io.prometheus.metrics.instrumentation.jvm; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| import com.sun.management.GarbageCollectionNotificationInfo; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.prometheus.metrics.config.PrometheusProperties; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.prometheus.metrics.core.metrics.Histogram; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.prometheus.metrics.core.metrics.SummaryWithCallback; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.prometheus.metrics.model.registry.PrometheusRegistry; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import io.prometheus.metrics.model.snapshots.Labels; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -10,6 +12,8 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.lang.management.ManagementFactory; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.util.List; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import javax.annotation.Nullable; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import javax.management.NotificationEmitter; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import javax.management.openmbean.CompositeData; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * JVM Garbage Collector metrics. The {@link JvmGarbageCollectorMetrics} are registered as part of | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -19,14 +23,14 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||
| * JvmMetrics.builder().register(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * }</pre> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * However, if you want only the {@link JvmGarbageCollectorMetrics} you can also register them | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * <p>However, if you want only the {@link JvmGarbageCollectorMetrics} you can also register them | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * directly: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * <pre>{@code | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * JvmGarbageCollectorMetrics.builder().register(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * }</pre> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Example metrics being exported: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * <p>Example metrics being exported: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * <pre> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| * # HELP jvm_gc_collection_seconds Time spent in a given JVM garbage collector in seconds. | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -40,6 +44,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||
| public class JvmGarbageCollectorMetrics { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static final String JVM_GC_COLLECTION_SECONDS = "jvm_gc_collection_seconds"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static final String JVM_GC_DURATION = "jvm.gc.duration"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final PrometheusProperties config; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| private final List<GarbageCollectorMXBean> garbageCollectorBeans; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -55,7 +60,14 @@ private JvmGarbageCollectorMetrics( | |||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| private void register(PrometheusRegistry registry) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (config.useOtelSemconv(JVM_GC_DURATION)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| registerOtel(registry); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| registerPrometheus(registry); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| private void registerPrometheus(PrometheusRegistry registry) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| SummaryWithCallback.builder(config) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .name(JVM_GC_COLLECTION_SECONDS) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .help("Time spent in a given JVM garbage collector in seconds.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -75,6 +87,54 @@ private void register(PrometheusRegistry registry) { | |||||||||||||||||||||||||||||||||||||||||||||||||||
| .register(registry); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| private void registerOtel(PrometheusRegistry registry) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| double[] buckets = {0.01, 0.1, 1, 10}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| Histogram gcDurationHistogram = | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| Histogram.builder(config) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .name(JVM_GC_DURATION) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .unit(Unit.SECONDS) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .help("Duration of JVM garbage collection actions.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .labelNames("jvm.gc.action", "jvm.gc.name", "jvm.gc.cause") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| .classicUpperBounds(buckets) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .register(registry); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| registerNotificationListener(gcDurationHistogram); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| private void registerNotificationListener(Histogram gcDurationHistogram) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. taking a look at the OTel implementation, they also track the listeners and do a cleanup, not sure if it makes sense for us to implement something like that, by making Another thing they do is check to see if the class exists first , which I think would be good to do here too |
||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (GarbageCollectorMXBean gcBean : garbageCollectorBeans) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!(gcBean instanceof NotificationEmitter)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| ((NotificationEmitter) gcBean) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .addNotificationListener( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| (notification, handback) -> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION.equals( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| notification.getType())) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| GarbageCollectionNotificationInfo info = | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| GarbageCollectionNotificationInfo.from( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| (CompositeData) notification.getUserData()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| observe(gcDurationHistogram, info); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+115
to
+124
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. try/catch here to avoid crashing the JVM is the notification listener throws something
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| null, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| private void observe(Histogram gcDurationHistogram, GarbageCollectionNotificationInfo info) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| double observedDuration = Unit.millisToSeconds(info.getGcInfo().getDuration()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| gcDurationHistogram | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .labelValues(info.getGcAction(), info.getGcName(), info.getGcCause()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| .observe(observedDuration); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static Builder builder() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return new Builder(PrometheusProperties.get()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we be consistent with the way the other metric is defined?