From d787b9bcaaf694d3cf3a6d4fc955f9ec47be25d9 Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Tue, 22 Apr 2025 11:20:53 +0800 Subject: [PATCH 01/11] Add GC cause to jvm GC related metric --- .../runtimemetrics/java8/GarbageCollector.java | 16 ++++++++++++---- .../java8/GarbageCollectorTest.java | 15 +++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java index deabc1e034c7..a505049ecf21 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java @@ -10,9 +10,11 @@ import com.sun.management.GarbageCollectionNotificationInfo; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil; import io.opentelemetry.semconv.JvmAttributes; import java.lang.management.GarbageCollectorMXBean; @@ -125,11 +127,17 @@ public void handleNotification(Notification notification, Object unused) { String gcName = notificationInfo.getGcName(); String gcAction = notificationInfo.getGcAction(); + String gcCause = notificationInfo.getGcCause(); double duration = notificationInfo.getGcInfo().getDuration() / MILLIS_PER_S; - - gcDuration.record( - duration, - Attributes.of(JvmAttributes.JVM_GC_NAME, gcName, JvmAttributes.JVM_GC_ACTION, gcAction)); + boolean enableJvmGcCauseAttribute = ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.runtime-telemetry.enable-jvm-gc-cause-attribute", false); + Attributes gcAttributes = + enableJvmGcCauseAttribute ? Attributes.of(JvmAttributes.JVM_GC_NAME, gcName, + JvmAttributes.JVM_GC_ACTION, gcAction, + AttributeKey.stringKey("jvm.gc.cause"), gcCause) + : Attributes.of(JvmAttributes.JVM_GC_NAME, gcName, JvmAttributes.JVM_GC_ACTION, + gcAction); + gcDuration.record(duration, gcAttributes); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java index 92bf23d10748..44dcac3baa98 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java @@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.RegisterExtension; +import org.junitpioneer.jupiter.SetSystemProperty; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; @@ -48,6 +49,7 @@ class GarbageCollectorTest { @Captor private ArgumentCaptor listenerCaptor; + @SetSystemProperty(key = "otel.instrumentation.runtime-telemetry.enable-jvm-gc-cause-attribute", value = "true") @Test void registerObservers() { GarbageCollector.registerObservers( @@ -60,11 +62,13 @@ void registerObservers() { NotificationListener listener = listenerCaptor.getValue(); listener.handleNotification( - createTestNotification("G1 Young Generation", "end of minor GC", 10), null); + createTestNotification("G1 Young Generation", "end of minor GC", "Allocation Failure", 10), + null); listener.handleNotification( - createTestNotification("G1 Young Generation", "end of minor GC", 12), null); + createTestNotification("G1 Young Generation", "end of minor GC", "Allocation Failure", 12), + null); listener.handleNotification( - createTestNotification("G1 Old Generation", "end of major GC", 11), null); + createTestNotification("G1 Old Generation", "end of major GC", "System.gc()", 11), null); testing.waitAndAssertMetrics( "io.opentelemetry.runtime-telemetry-java8", @@ -87,6 +91,7 @@ void registerObservers() { Attributes.builder() .put("jvm.gc.name", "G1 Young Generation") .put("jvm.gc.action", "end of minor GC") + .put("jvm.gc.cause", "Allocation Failure") .build()) .hasBucketBoundaries(GC_DURATION_BUCKETS), point -> @@ -97,16 +102,18 @@ void registerObservers() { Attributes.builder() .put("jvm.gc.name", "G1 Old Generation") .put("jvm.gc.action", "end of major GC") + .put("jvm.gc.cause", "System.gc()") .build()) .hasBucketBoundaries(GC_DURATION_BUCKETS))))); } private static Notification createTestNotification( - String gcName, String gcAction, long duration) { + String gcName, String gcAction, String gcCause, long duration) { GarbageCollectionNotificationInfo gcNotificationInfo = mock(GarbageCollectionNotificationInfo.class); when(gcNotificationInfo.getGcName()).thenReturn(gcName); when(gcNotificationInfo.getGcAction()).thenReturn(gcAction); + when(gcNotificationInfo.getGcCause()).thenReturn(gcCause); GcInfo gcInfo = mock(GcInfo.class); when(gcInfo.getDuration()).thenReturn(duration); when(gcNotificationInfo.getGcInfo()).thenReturn(gcInfo); From 61db9ea2a040cd93df73e268f22973bd05a31afa Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Tue, 22 Apr 2025 11:44:39 +0800 Subject: [PATCH 02/11] Add the configuration to related README.md --- instrumentation/runtime-telemetry/README.md | 1 + .../java8/GarbageCollector.java | 20 ++++++++++++------- .../java8/GarbageCollectorTest.java | 4 +++- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/instrumentation/runtime-telemetry/README.md b/instrumentation/runtime-telemetry/README.md index 9baab6e1315c..c4ec01c0f272 100644 --- a/instrumentation/runtime-telemetry/README.md +++ b/instrumentation/runtime-telemetry/README.md @@ -5,5 +5,6 @@ | `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Enable the capture of experimental metrics. | | `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Enable the capture of all JFR based metrics. | | `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Enable the capture of JFR based metrics. | +| `otel.instrumentation.runtime-telemetry.jvm-gc-cause-attribute-enabled` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute within the jvm.gc.duration metric. | `otel.instrumentation.runtime-telemetry.package-emitter.enabled` | Boolean | `false` | Enable creating events for JAR libraries used by the application. | | `otel.instrumentation.runtime-telemetry.package-emitter.jars-per-second` | Integer | 10 | The number of JAR files processed per second. | diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java index a505049ecf21..1c6e2b38c5c0 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java @@ -129,14 +129,20 @@ public void handleNotification(Notification notification, Object unused) { String gcAction = notificationInfo.getGcAction(); String gcCause = notificationInfo.getGcCause(); double duration = notificationInfo.getGcInfo().getDuration() / MILLIS_PER_S; - boolean enableJvmGcCauseAttribute = ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.runtime-telemetry.enable-jvm-gc-cause-attribute", false); + boolean enableJvmGcCauseAttribute = + ConfigPropertiesUtil.getBoolean( + "otel.instrumentation.runtime-telemetry.jvm-gc-cause-attribute-enabled", false); Attributes gcAttributes = - enableJvmGcCauseAttribute ? Attributes.of(JvmAttributes.JVM_GC_NAME, gcName, - JvmAttributes.JVM_GC_ACTION, gcAction, - AttributeKey.stringKey("jvm.gc.cause"), gcCause) - : Attributes.of(JvmAttributes.JVM_GC_NAME, gcName, JvmAttributes.JVM_GC_ACTION, - gcAction); + enableJvmGcCauseAttribute + ? Attributes.of( + JvmAttributes.JVM_GC_NAME, + gcName, + JvmAttributes.JVM_GC_ACTION, + gcAction, + AttributeKey.stringKey("jvm.gc.cause"), + gcCause) + : Attributes.of( + JvmAttributes.JVM_GC_NAME, gcName, JvmAttributes.JVM_GC_ACTION, gcAction); gcDuration.record(duration, gcAttributes); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java index 44dcac3baa98..32f79e11faff 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java @@ -49,7 +49,9 @@ class GarbageCollectorTest { @Captor private ArgumentCaptor listenerCaptor; - @SetSystemProperty(key = "otel.instrumentation.runtime-telemetry.enable-jvm-gc-cause-attribute", value = "true") + @SetSystemProperty( + key = "otel.instrumentation.runtime-telemetry.jvm-gc-cause-attribute-enabled", + value = "true") @Test void registerObservers() { GarbageCollector.registerObservers( From 6be7963d2ccf939f1c4979026f98aa0e1f228ee5 Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Thu, 24 Apr 2025 20:50:37 +0800 Subject: [PATCH 03/11] Address review comments --- instrumentation/runtime-telemetry/README.md | 16 ++++++++-------- .../runtimemetrics/java8/GarbageCollector.java | 8 +++----- .../java8/internal/RuntimeMetricsConfigUtil.java | 6 ++++++ .../java8/GarbageCollectorTest.java | 6 ++---- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/instrumentation/runtime-telemetry/README.md b/instrumentation/runtime-telemetry/README.md index c4ec01c0f272..2d07de0baedd 100644 --- a/instrumentation/runtime-telemetry/README.md +++ b/instrumentation/runtime-telemetry/README.md @@ -1,10 +1,10 @@ # Settings for the Runtime Telemetry instrumentation -| System property | Type | Default | Description | -|--------------------------------------------------------------------------|---------|---------|-------------------------------------------------------------------| -| `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Enable the capture of experimental metrics. | -| `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Enable the capture of all JFR based metrics. | -| `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Enable the capture of JFR based metrics. | -| `otel.instrumentation.runtime-telemetry.jvm-gc-cause-attribute-enabled` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute within the jvm.gc.duration metric. -| `otel.instrumentation.runtime-telemetry.package-emitter.enabled` | Boolean | `false` | Enable creating events for JAR libraries used by the application. | -| `otel.instrumentation.runtime-telemetry.package-emitter.jars-per-second` | Integer | 10 | The number of JAR files processed per second. | +| System property | Type | Default | Description | +|--------------------------------------------------------------------------|---------|---------|-------------------------------------------------------------------------------------| +| `otel.instrumentation.runtime-telemetry.capture-gc-cause-enabled` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute within the jvm.gc.duration metric. +| `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Enable the capture of experimental metrics. | +| `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Enable the capture of all JFR based metrics. | +| `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Enable the capture of JFR based metrics. | +| `otel.instrumentation.runtime-telemetry.package-emitter.enabled` | Boolean | `false` | Enable creating events for JAR libraries used by the application. | +| `otel.instrumentation.runtime-telemetry.package-emitter.jars-per-second` | Integer | 10 | The number of JAR files processed per second. | diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java index 1c6e2b38c5c0..fdcdb6969f4e 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java @@ -14,7 +14,6 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil; import io.opentelemetry.semconv.JvmAttributes; import java.lang.management.GarbageCollectorMXBean; @@ -57,6 +56,8 @@ public final class GarbageCollector { static final List GC_DURATION_BUCKETS = unmodifiableList(asList(0.01, 0.1, 1., 10.)); + public static boolean captureGcCauseEnabled = false; + private static final NotificationFilter GC_FILTER = notification -> notification @@ -129,11 +130,8 @@ public void handleNotification(Notification notification, Object unused) { String gcAction = notificationInfo.getGcAction(); String gcCause = notificationInfo.getGcCause(); double duration = notificationInfo.getGcInfo().getDuration() / MILLIS_PER_S; - boolean enableJvmGcCauseAttribute = - ConfigPropertiesUtil.getBoolean( - "otel.instrumentation.runtime-telemetry.jvm-gc-cause-attribute-enabled", false); Attributes gcAttributes = - enableJvmGcCauseAttribute + captureGcCauseEnabled ? Attributes.of( JvmAttributes.JVM_GC_NAME, gcName, diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java index f0059cf7f9d3..20d202fb73c5 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java @@ -6,6 +6,7 @@ package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; +import io.opentelemetry.instrumentation.runtimemetrics.java8.GarbageCollector; import io.opentelemetry.instrumentation.runtimemetrics.java8.RuntimeMetrics; import io.opentelemetry.instrumentation.runtimemetrics.java8.RuntimeMetricsBuilder; import javax.annotation.Nullable; @@ -31,6 +32,11 @@ public static RuntimeMetrics configure( builder.enableExperimentalJmxTelemetry(); } + if (config.getBoolean( + "otel.instrumentation.runtime-telemetry.capture-gc-cause-enabled", false)) { + GarbageCollector.captureGcCauseEnabled = true; + } + return builder.build(); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java index 32f79e11faff..881d8860b6ff 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java @@ -26,7 +26,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.RegisterExtension; -import org.junitpioneer.jupiter.SetSystemProperty; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; @@ -49,9 +48,6 @@ class GarbageCollectorTest { @Captor private ArgumentCaptor listenerCaptor; - @SetSystemProperty( - key = "otel.instrumentation.runtime-telemetry.jvm-gc-cause-attribute-enabled", - value = "true") @Test void registerObservers() { GarbageCollector.registerObservers( @@ -63,6 +59,8 @@ void registerObservers() { verify(notificationEmitter).addNotificationListener(listenerCaptor.capture(), any(), any()); NotificationListener listener = listenerCaptor.getValue(); + GarbageCollector.captureGcCauseEnabled = true; + listener.handleNotification( createTestNotification("G1 Young Generation", "end of minor GC", "Allocation Failure", 10), null); From 05128b582e0af6ffe45e4e2f6fa6d3171a847604 Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Thu, 24 Apr 2025 21:19:52 +0800 Subject: [PATCH 04/11] Address review comments --- .../java17/RuntimeMetricsBuilder.java | 10 +++++++++- .../internal/RuntimeMetricsConfigUtil.java | 5 +++++ .../java8/GarbageCollector.java | 20 +++++++++++-------- .../java8/RuntimeMetricsBuilder.java | 12 ++++++++++- .../internal/JmxRuntimeMetricsFactory.java | 6 ++++-- .../internal/RuntimeMetricsConfigUtil.java | 3 +-- .../java8/GarbageCollectorTest.java | 5 ++--- 7 files changed, 44 insertions(+), 17 deletions(-) diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java index 103a3efef6ca..f03907cc1774 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java @@ -22,6 +22,7 @@ public final class RuntimeMetricsBuilder { private boolean disableJmx = false; private boolean enableExperimentalJmxTelemetry = false; + private boolean enableCaptureGcCause = false; RuntimeMetricsBuilder(OpenTelemetry openTelemetry) { this.openTelemetry = openTelemetry; @@ -81,13 +82,20 @@ public RuntimeMetricsBuilder enableExperimentalJmxTelemetry() { return this; } + /** Enable capture GC cause. */ + @CanIgnoreReturnValue + public RuntimeMetricsBuilder enableCaptureGcCause() { + enableCaptureGcCause = true; + return this; + } + /** Build and start an {@link RuntimeMetrics} with the config from this builder. */ public RuntimeMetrics build() { List observables = disableJmx ? List.of() : JmxRuntimeMetricsFactory.buildObservables( - openTelemetry, enableExperimentalJmxTelemetry); + openTelemetry, enableExperimentalJmxTelemetry, enableCaptureGcCause); RuntimeMetrics.JfrRuntimeMetrics jfrRuntimeMetrics = buildJfrMetrics(); return new RuntimeMetrics(openTelemetry, observables, jfrRuntimeMetrics); } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java index f8ec8a57e05b..409a39ca622a 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java @@ -43,6 +43,11 @@ public static RuntimeMetrics configure( builder.enableExperimentalJmxTelemetry(); } + if (config.getBoolean( + "otel.instrumentation.runtime-telemetry.capture-gc-cause-enabled", false)) { + builder.enableCaptureGcCause(); + } + return builder.build(); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java index fdcdb6969f4e..ef8b58d591d4 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java @@ -56,8 +56,6 @@ public final class GarbageCollector { static final List GC_DURATION_BUCKETS = unmodifiableList(asList(0.01, 0.1, 1., 10.)); - public static boolean captureGcCauseEnabled = false; - private static final NotificationFilter GC_FILTER = notification -> notification @@ -65,7 +63,8 @@ public final class GarbageCollector { .equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION); /** Register observers for java runtime memory metrics. */ - public static List registerObservers(OpenTelemetry openTelemetry) { + public static List registerObservers( + OpenTelemetry openTelemetry, boolean enableCaptureGcCause) { if (!isNotificationClassPresent()) { logger.fine( "The com.sun.management.GarbageCollectionNotificationInfo class is not available;" @@ -76,14 +75,16 @@ public static List registerObservers(OpenTelemetry openTelemetry) return registerObservers( openTelemetry, ManagementFactory.getGarbageCollectorMXBeans(), - GarbageCollector::extractNotificationInfo); + GarbageCollector::extractNotificationInfo, + enableCaptureGcCause); } // Visible for testing static List registerObservers( OpenTelemetry openTelemetry, List gcBeans, - Function notificationInfoExtractor) { + Function notificationInfoExtractor, + boolean captureGcCauseEnabled) { Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); DoubleHistogram gcDuration = @@ -101,7 +102,7 @@ static List registerObservers( } NotificationEmitter notificationEmitter = (NotificationEmitter) gcBean; GcNotificationListener listener = - new GcNotificationListener(gcDuration, notificationInfoExtractor); + new GcNotificationListener(gcDuration, notificationInfoExtractor, captureGcCauseEnabled); notificationEmitter.addNotificationListener(listener, GC_FILTER, null); result.add(() -> notificationEmitter.removeNotificationListener(listener)); } @@ -110,13 +111,16 @@ static List registerObservers( private static final class GcNotificationListener implements NotificationListener { + private final boolean enableCaptureGcCause; private final DoubleHistogram gcDuration; private final Function notificationInfoExtractor; private GcNotificationListener( DoubleHistogram gcDuration, - Function notificationInfoExtractor) { + Function notificationInfoExtractor, + boolean enableCaptureGcCause) { + this.enableCaptureGcCause = enableCaptureGcCause; this.gcDuration = gcDuration; this.notificationInfoExtractor = notificationInfoExtractor; } @@ -131,7 +135,7 @@ public void handleNotification(Notification notification, Object unused) { String gcCause = notificationInfo.getGcCause(); double duration = notificationInfo.getGcInfo().getDuration() / MILLIS_PER_S; Attributes gcAttributes = - captureGcCauseEnabled + enableCaptureGcCause ? Attributes.of( JvmAttributes.JVM_GC_NAME, gcName, diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java index e342626ac377..385e34fb4a57 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java @@ -17,6 +17,8 @@ public final class RuntimeMetricsBuilder { private boolean enableExperimentalJmxTelemetry = false; + private boolean enableCaptureGcCause = false; + RuntimeMetricsBuilder(OpenTelemetry openTelemetry) { this.openTelemetry = openTelemetry; } @@ -28,10 +30,18 @@ public RuntimeMetricsBuilder enableExperimentalJmxTelemetry() { return this; } + /** Enable capture GC cause. */ + @CanIgnoreReturnValue + public RuntimeMetricsBuilder enableCaptureGcCause() { + enableCaptureGcCause = true; + return this; + } + /** Build and start an {@link RuntimeMetrics} with the config from this builder. */ public RuntimeMetrics build() { List observables = - JmxRuntimeMetricsFactory.buildObservables(openTelemetry, enableExperimentalJmxTelemetry); + JmxRuntimeMetricsFactory.buildObservables( + openTelemetry, enableExperimentalJmxTelemetry, enableCaptureGcCause); return new RuntimeMetrics(observables); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java index 2cb1b55b3d72..29c321999fdf 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java @@ -21,12 +21,14 @@ public class JmxRuntimeMetricsFactory { @SuppressWarnings("CatchingUnchecked") public static List buildObservables( - OpenTelemetry openTelemetry, boolean enableExperimentalJmxTelemetry) { + OpenTelemetry openTelemetry, + boolean enableExperimentalJmxTelemetry, + boolean enableCaptureGcCause) { // Set up metrics gathered by JMX List observables = new ArrayList<>(); observables.addAll(Classes.registerObservers(openTelemetry)); observables.addAll(Cpu.registerObservers(openTelemetry)); - observables.addAll(GarbageCollector.registerObservers(openTelemetry)); + observables.addAll(GarbageCollector.registerObservers(openTelemetry, enableCaptureGcCause)); observables.addAll(MemoryPools.registerObservers(openTelemetry)); observables.addAll(Threads.registerObservers(openTelemetry)); if (enableExperimentalJmxTelemetry) { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java index 20d202fb73c5..a24f22348728 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java @@ -6,7 +6,6 @@ package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; import io.opentelemetry.instrumentation.api.incubator.config.internal.InstrumentationConfig; -import io.opentelemetry.instrumentation.runtimemetrics.java8.GarbageCollector; import io.opentelemetry.instrumentation.runtimemetrics.java8.RuntimeMetrics; import io.opentelemetry.instrumentation.runtimemetrics.java8.RuntimeMetricsBuilder; import javax.annotation.Nullable; @@ -34,7 +33,7 @@ public static RuntimeMetrics configure( if (config.getBoolean( "otel.instrumentation.runtime-telemetry.capture-gc-cause-enabled", false)) { - GarbageCollector.captureGcCauseEnabled = true; + builder.enableCaptureGcCause(); } return builder.build(); diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java index 881d8860b6ff..bb9d4ad6921f 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java @@ -53,14 +53,13 @@ void registerObservers() { GarbageCollector.registerObservers( testing.getOpenTelemetry(), singletonList(gcBean), - GarbageCollectorTest::getGcNotificationInfo); + GarbageCollectorTest::getGcNotificationInfo, + true); NotificationEmitter notificationEmitter = (NotificationEmitter) gcBean; verify(notificationEmitter).addNotificationListener(listenerCaptor.capture(), any(), any()); NotificationListener listener = listenerCaptor.getValue(); - GarbageCollector.captureGcCauseEnabled = true; - listener.handleNotification( createTestNotification("G1 Young Generation", "end of minor GC", "Allocation Failure", 10), null); From 1812bd2be88f12ec93cdd559f7ec60bcced1338b Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Thu, 24 Apr 2025 21:21:55 +0800 Subject: [PATCH 05/11] Address review comments --- instrumentation/runtime-telemetry/README.md | 2 +- .../java17/internal/RuntimeMetricsConfigUtil.java | 3 +-- .../java8/internal/RuntimeMetricsConfigUtil.java | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/instrumentation/runtime-telemetry/README.md b/instrumentation/runtime-telemetry/README.md index 2d07de0baedd..ec937a7c7722 100644 --- a/instrumentation/runtime-telemetry/README.md +++ b/instrumentation/runtime-telemetry/README.md @@ -2,7 +2,7 @@ | System property | Type | Default | Description | |--------------------------------------------------------------------------|---------|---------|-------------------------------------------------------------------------------------| -| `otel.instrumentation.runtime-telemetry.capture-gc-cause-enabled` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute within the jvm.gc.duration metric. +| `otel.instrumentation.runtime-telemetry.capture-gc-cause` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute within the jvm.gc.duration metric. | `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Enable the capture of experimental metrics. | | `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Enable the capture of all JFR based metrics. | | `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Enable the capture of JFR based metrics. | diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java index 409a39ca622a..5f8462ee62b8 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java @@ -43,8 +43,7 @@ public static RuntimeMetrics configure( builder.enableExperimentalJmxTelemetry(); } - if (config.getBoolean( - "otel.instrumentation.runtime-telemetry.capture-gc-cause-enabled", false)) { + if (config.getBoolean("otel.instrumentation.runtime-telemetry.capture-gc-cause", false)) { builder.enableCaptureGcCause(); } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java index a24f22348728..8eeacf475885 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java @@ -31,8 +31,7 @@ public static RuntimeMetrics configure( builder.enableExperimentalJmxTelemetry(); } - if (config.getBoolean( - "otel.instrumentation.runtime-telemetry.capture-gc-cause-enabled", false)) { + if (config.getBoolean("otel.instrumentation.runtime-telemetry.capture-gc-cause", false)) { builder.enableCaptureGcCause(); } From a312ef2c82d07417236f98374a2b1e946eae97fd Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Thu, 24 Apr 2025 22:02:52 +0800 Subject: [PATCH 06/11] Address review comments --- instrumentation/runtime-telemetry/README.md | 16 ++++++++-------- .../java17/RuntimeMetricsBuilder.java | 2 +- .../java8/RuntimeMetricsBuilder.java | 3 +-- ...additional-spring-configuration-metadata.json | 6 ++++++ 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/instrumentation/runtime-telemetry/README.md b/instrumentation/runtime-telemetry/README.md index ec937a7c7722..58832c9a9c56 100644 --- a/instrumentation/runtime-telemetry/README.md +++ b/instrumentation/runtime-telemetry/README.md @@ -1,10 +1,10 @@ # Settings for the Runtime Telemetry instrumentation -| System property | Type | Default | Description | -|--------------------------------------------------------------------------|---------|---------|-------------------------------------------------------------------------------------| -| `otel.instrumentation.runtime-telemetry.capture-gc-cause` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute within the jvm.gc.duration metric. -| `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Enable the capture of experimental metrics. | -| `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Enable the capture of all JFR based metrics. | -| `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Enable the capture of JFR based metrics. | -| `otel.instrumentation.runtime-telemetry.package-emitter.enabled` | Boolean | `false` | Enable creating events for JAR libraries used by the application. | -| `otel.instrumentation.runtime-telemetry.package-emitter.jars-per-second` | Integer | 10 | The number of JAR files processed per second. | +| System property | Type | Default | Description | +|--------------------------------------------------------------------------|---------|---------|-----------------------------------------------------------------------------------| +| `otel.instrumentation.runtime-telemetry.capture-gc-cause` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. +| `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Enable the capture of experimental metrics. | +| `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Enable the capture of all JFR based metrics. | +| `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Enable the capture of JFR based metrics. | +| `otel.instrumentation.runtime-telemetry.package-emitter.enabled` | Boolean | `false` | Enable creating events for JAR libraries used by the application. | +| `otel.instrumentation.runtime-telemetry.package-emitter.jars-per-second` | Integer | 10 | The number of JAR files processed per second. | diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java index f03907cc1774..f48c09647611 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java @@ -82,7 +82,7 @@ public RuntimeMetricsBuilder enableExperimentalJmxTelemetry() { return this; } - /** Enable capture GC cause. */ + /** Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. */ @CanIgnoreReturnValue public RuntimeMetricsBuilder enableCaptureGcCause() { enableCaptureGcCause = true; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java index 385e34fb4a57..5f22d848c135 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java @@ -16,7 +16,6 @@ public final class RuntimeMetricsBuilder { private final OpenTelemetry openTelemetry; private boolean enableExperimentalJmxTelemetry = false; - private boolean enableCaptureGcCause = false; RuntimeMetricsBuilder(OpenTelemetry openTelemetry) { @@ -30,7 +29,7 @@ public RuntimeMetricsBuilder enableExperimentalJmxTelemetry() { return this; } - /** Enable capture GC cause. */ + /** Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. */ @CanIgnoreReturnValue public RuntimeMetricsBuilder enableCaptureGcCause() { enableCaptureGcCause = true; diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index e339c3455df8..db72deca72bd 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -482,6 +482,12 @@ "description": "Enables the DB statement sanitization.", "defaultValue": true }, + { + "name": "otel.instrumentation.runtime-telemetry.capture-gc-cause", + "type": "java.lang.Boolean", + "description": "Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric.", + "defaultValue": false + }, { "name": "otel.instrumentation.runtime-telemetry.enabled", "type": "java.lang.Boolean", From 8dc57b960a0af033186524593bb09c6e19746607 Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Thu, 24 Apr 2025 22:19:55 +0800 Subject: [PATCH 07/11] Parameterized test --- instrumentation/runtime-telemetry/README.md | 2 +- .../java8/GarbageCollector.java | 4 +- .../java8/GarbageCollectorTest.java | 38 +++++++++++-------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/instrumentation/runtime-telemetry/README.md b/instrumentation/runtime-telemetry/README.md index 58832c9a9c56..012e97b1be50 100644 --- a/instrumentation/runtime-telemetry/README.md +++ b/instrumentation/runtime-telemetry/README.md @@ -2,7 +2,7 @@ | System property | Type | Default | Description | |--------------------------------------------------------------------------|---------|---------|-----------------------------------------------------------------------------------| -| `otel.instrumentation.runtime-telemetry.capture-gc-cause` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. +| `otel.instrumentation.runtime-telemetry.capture-gc-cause` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. | `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Enable the capture of experimental metrics. | | `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Enable the capture of all JFR based metrics. | | `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Enable the capture of JFR based metrics. | diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java index ef8b58d591d4..9bdf8565dc31 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java @@ -84,7 +84,7 @@ static List registerObservers( OpenTelemetry openTelemetry, List gcBeans, Function notificationInfoExtractor, - boolean captureGcCauseEnabled) { + boolean enableCaptureGcCause) { Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); DoubleHistogram gcDuration = @@ -102,7 +102,7 @@ static List registerObservers( } NotificationEmitter notificationEmitter = (NotificationEmitter) gcBean; GcNotificationListener listener = - new GcNotificationListener(gcDuration, notificationInfoExtractor, captureGcCauseEnabled); + new GcNotificationListener(gcDuration, notificationInfoExtractor, enableCaptureGcCause); notificationEmitter.addNotificationListener(listener, GC_FILTER, null); result.add(() -> notificationEmitter.removeNotificationListener(listener)); } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java index bb9d4ad6921f..de6886573258 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java @@ -16,6 +16,7 @@ import com.sun.management.GarbageCollectionNotificationInfo; import com.sun.management.GcInfo; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; import java.lang.management.GarbageCollectorMXBean; @@ -23,9 +24,10 @@ import javax.management.Notification; import javax.management.NotificationEmitter; import javax.management.NotificationListener; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; @@ -48,13 +50,14 @@ class GarbageCollectorTest { @Captor private ArgumentCaptor listenerCaptor; - @Test - void registerObservers() { + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void registerObservers(boolean enableCaptureGcCause) { GarbageCollector.registerObservers( testing.getOpenTelemetry(), singletonList(gcBean), GarbageCollectorTest::getGcNotificationInfo, - true); + enableCaptureGcCause); NotificationEmitter notificationEmitter = (NotificationEmitter) gcBean; verify(notificationEmitter).addNotificationListener(listenerCaptor.capture(), any(), any()); @@ -69,6 +72,19 @@ void registerObservers() { listener.handleNotification( createTestNotification("G1 Old Generation", "end of major GC", "System.gc()", 11), null); + AttributesBuilder attributesBuilder1 = + Attributes.builder() + .put("jvm.gc.name", "G1 Young Generation") + .put("jvm.gc.action", "end of minor GC"); + AttributesBuilder attributesBuilder2 = + Attributes.builder() + .put("jvm.gc.name", "G1 Old Generation") + .put("jvm.gc.action", "end of major GC"); + if (enableCaptureGcCause) { + attributesBuilder1.put("jvm.gc.cause", "Allocation Failure"); + attributesBuilder2.put("jvm.gc.cause", "System.gc()"); + } + testing.waitAndAssertMetrics( "io.opentelemetry.runtime-telemetry-java8", "jvm.gc.duration", @@ -86,23 +102,13 @@ void registerObservers() { point .hasCount(2) .hasSum(0.022) - .hasAttributes( - Attributes.builder() - .put("jvm.gc.name", "G1 Young Generation") - .put("jvm.gc.action", "end of minor GC") - .put("jvm.gc.cause", "Allocation Failure") - .build()) + .hasAttributes(attributesBuilder1.build()) .hasBucketBoundaries(GC_DURATION_BUCKETS), point -> point .hasCount(1) .hasSum(0.011) - .hasAttributes( - Attributes.builder() - .put("jvm.gc.name", "G1 Old Generation") - .put("jvm.gc.action", "end of major GC") - .put("jvm.gc.cause", "System.gc()") - .build()) + .hasAttributes(attributesBuilder2.build()) .hasBucketBoundaries(GC_DURATION_BUCKETS))))); } From 4c6cc09a56fb444cf596e6e3d210e8d341d853ef Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Thu, 24 Apr 2025 22:32:20 +0800 Subject: [PATCH 08/11] Reformatting table --- instrumentation/runtime-telemetry/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/runtime-telemetry/README.md b/instrumentation/runtime-telemetry/README.md index 012e97b1be50..51a6611f7c08 100644 --- a/instrumentation/runtime-telemetry/README.md +++ b/instrumentation/runtime-telemetry/README.md @@ -2,7 +2,7 @@ | System property | Type | Default | Description | |--------------------------------------------------------------------------|---------|---------|-----------------------------------------------------------------------------------| -| `otel.instrumentation.runtime-telemetry.capture-gc-cause` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. +| `otel.instrumentation.runtime-telemetry.capture-gc-cause` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. | | `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Enable the capture of experimental metrics. | | `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Enable the capture of all JFR based metrics. | | `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Enable the capture of JFR based metrics. | From 3bbfa4f7ed0371a7dfe7b70902aeeed675a924f1 Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Fri, 25 Apr 2025 20:09:30 +0800 Subject: [PATCH 09/11] Address review comments --- .../runtimemetrics/java8/GarbageCollector.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java index 9bdf8565dc31..12a6cbb942b1 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java @@ -56,6 +56,8 @@ public final class GarbageCollector { static final List GC_DURATION_BUCKETS = unmodifiableList(asList(0.01, 0.1, 1., 10.)); + private static final AttributeKey JVM_GC_CAUSE = AttributeKey.stringKey("jvm.gc.cause"); + private static final NotificationFilter GC_FILTER = notification -> notification @@ -141,7 +143,7 @@ public void handleNotification(Notification notification, Object unused) { gcName, JvmAttributes.JVM_GC_ACTION, gcAction, - AttributeKey.stringKey("jvm.gc.cause"), + JVM_GC_CAUSE, gcCause) : Attributes.of( JvmAttributes.JVM_GC_NAME, gcName, JvmAttributes.JVM_GC_ACTION, gcAction); From d84e6973a39c65d03e80eb2ee80bd67646b527d9 Mon Sep 17 00:00:00 2001 From: Steve Rao Date: Sun, 27 Apr 2025 15:32:31 +0800 Subject: [PATCH 10/11] Address review comments --- .../java17/RuntimeMetricsBuilder.java | 8 ++++---- .../internal/RuntimeMetricsConfigUtil.java | 2 +- .../runtimemetrics/java8/GarbageCollector.java | 16 ++++++++-------- .../java8/RuntimeMetricsBuilder.java | 8 ++++---- .../java8/internal/JmxRuntimeMetricsFactory.java | 6 ++---- .../java8/internal/RuntimeMetricsConfigUtil.java | 2 +- .../java8/GarbageCollectorTest.java | 6 +++--- 7 files changed, 23 insertions(+), 25 deletions(-) diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java index f48c09647611..3e9d015d7f23 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java @@ -22,7 +22,7 @@ public final class RuntimeMetricsBuilder { private boolean disableJmx = false; private boolean enableExperimentalJmxTelemetry = false; - private boolean enableCaptureGcCause = false; + private boolean captureGcCause = false; RuntimeMetricsBuilder(OpenTelemetry openTelemetry) { this.openTelemetry = openTelemetry; @@ -84,8 +84,8 @@ public RuntimeMetricsBuilder enableExperimentalJmxTelemetry() { /** Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. */ @CanIgnoreReturnValue - public RuntimeMetricsBuilder enableCaptureGcCause() { - enableCaptureGcCause = true; + public RuntimeMetricsBuilder captureGcCause() { + captureGcCause = true; return this; } @@ -95,7 +95,7 @@ public RuntimeMetrics build() { disableJmx ? List.of() : JmxRuntimeMetricsFactory.buildObservables( - openTelemetry, enableExperimentalJmxTelemetry, enableCaptureGcCause); + openTelemetry, enableExperimentalJmxTelemetry, captureGcCause); RuntimeMetrics.JfrRuntimeMetrics jfrRuntimeMetrics = buildJfrMetrics(); return new RuntimeMetrics(openTelemetry, observables, jfrRuntimeMetrics); } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java index 5f8462ee62b8..804a8071e26e 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java @@ -44,7 +44,7 @@ public static RuntimeMetrics configure( } if (config.getBoolean("otel.instrumentation.runtime-telemetry.capture-gc-cause", false)) { - builder.enableCaptureGcCause(); + builder.captureGcCause(); } return builder.build(); diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java index 12a6cbb942b1..d434bd5479ca 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java @@ -66,7 +66,7 @@ public final class GarbageCollector { /** Register observers for java runtime memory metrics. */ public static List registerObservers( - OpenTelemetry openTelemetry, boolean enableCaptureGcCause) { + OpenTelemetry openTelemetry, boolean captureGcCause) { if (!isNotificationClassPresent()) { logger.fine( "The com.sun.management.GarbageCollectionNotificationInfo class is not available;" @@ -78,7 +78,7 @@ public static List registerObservers( openTelemetry, ManagementFactory.getGarbageCollectorMXBeans(), GarbageCollector::extractNotificationInfo, - enableCaptureGcCause); + captureGcCause); } // Visible for testing @@ -86,7 +86,7 @@ static List registerObservers( OpenTelemetry openTelemetry, List gcBeans, Function notificationInfoExtractor, - boolean enableCaptureGcCause) { + boolean captureGcCause) { Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); DoubleHistogram gcDuration = @@ -104,7 +104,7 @@ static List registerObservers( } NotificationEmitter notificationEmitter = (NotificationEmitter) gcBean; GcNotificationListener listener = - new GcNotificationListener(gcDuration, notificationInfoExtractor, enableCaptureGcCause); + new GcNotificationListener(gcDuration, notificationInfoExtractor, captureGcCause); notificationEmitter.addNotificationListener(listener, GC_FILTER, null); result.add(() -> notificationEmitter.removeNotificationListener(listener)); } @@ -113,7 +113,7 @@ static List registerObservers( private static final class GcNotificationListener implements NotificationListener { - private final boolean enableCaptureGcCause; + private final boolean captureGcCause; private final DoubleHistogram gcDuration; private final Function notificationInfoExtractor; @@ -121,8 +121,8 @@ private static final class GcNotificationListener implements NotificationListene private GcNotificationListener( DoubleHistogram gcDuration, Function notificationInfoExtractor, - boolean enableCaptureGcCause) { - this.enableCaptureGcCause = enableCaptureGcCause; + boolean captureGcCause) { + this.captureGcCause = captureGcCause; this.gcDuration = gcDuration; this.notificationInfoExtractor = notificationInfoExtractor; } @@ -137,7 +137,7 @@ public void handleNotification(Notification notification, Object unused) { String gcCause = notificationInfo.getGcCause(); double duration = notificationInfo.getGcInfo().getDuration() / MILLIS_PER_S; Attributes gcAttributes = - enableCaptureGcCause + captureGcCause ? Attributes.of( JvmAttributes.JVM_GC_NAME, gcName, diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java index 5f22d848c135..99fd24090575 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java @@ -16,7 +16,7 @@ public final class RuntimeMetricsBuilder { private final OpenTelemetry openTelemetry; private boolean enableExperimentalJmxTelemetry = false; - private boolean enableCaptureGcCause = false; + private boolean captureGcCause = false; RuntimeMetricsBuilder(OpenTelemetry openTelemetry) { this.openTelemetry = openTelemetry; @@ -31,8 +31,8 @@ public RuntimeMetricsBuilder enableExperimentalJmxTelemetry() { /** Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. */ @CanIgnoreReturnValue - public RuntimeMetricsBuilder enableCaptureGcCause() { - enableCaptureGcCause = true; + public RuntimeMetricsBuilder captureGcCause() { + captureGcCause = true; return this; } @@ -40,7 +40,7 @@ public RuntimeMetricsBuilder enableCaptureGcCause() { public RuntimeMetrics build() { List observables = JmxRuntimeMetricsFactory.buildObservables( - openTelemetry, enableExperimentalJmxTelemetry, enableCaptureGcCause); + openTelemetry, enableExperimentalJmxTelemetry, captureGcCause); return new RuntimeMetrics(observables); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java index 29c321999fdf..a38a421f98d8 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java @@ -21,14 +21,12 @@ public class JmxRuntimeMetricsFactory { @SuppressWarnings("CatchingUnchecked") public static List buildObservables( - OpenTelemetry openTelemetry, - boolean enableExperimentalJmxTelemetry, - boolean enableCaptureGcCause) { + OpenTelemetry openTelemetry, boolean enableExperimentalJmxTelemetry, boolean captureGcCause) { // Set up metrics gathered by JMX List observables = new ArrayList<>(); observables.addAll(Classes.registerObservers(openTelemetry)); observables.addAll(Cpu.registerObservers(openTelemetry)); - observables.addAll(GarbageCollector.registerObservers(openTelemetry, enableCaptureGcCause)); + observables.addAll(GarbageCollector.registerObservers(openTelemetry, captureGcCause)); observables.addAll(MemoryPools.registerObservers(openTelemetry)); observables.addAll(Threads.registerObservers(openTelemetry)); if (enableExperimentalJmxTelemetry) { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java index 8eeacf475885..37506e83e05f 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java @@ -32,7 +32,7 @@ public static RuntimeMetrics configure( } if (config.getBoolean("otel.instrumentation.runtime-telemetry.capture-gc-cause", false)) { - builder.enableCaptureGcCause(); + builder.captureGcCause(); } return builder.build(); diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java index de6886573258..ca5349016afe 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java @@ -52,12 +52,12 @@ class GarbageCollectorTest { @ParameterizedTest @ValueSource(booleans = {true, false}) - void registerObservers(boolean enableCaptureGcCause) { + void registerObservers(boolean captureGcCause) { GarbageCollector.registerObservers( testing.getOpenTelemetry(), singletonList(gcBean), GarbageCollectorTest::getGcNotificationInfo, - enableCaptureGcCause); + captureGcCause); NotificationEmitter notificationEmitter = (NotificationEmitter) gcBean; verify(notificationEmitter).addNotificationListener(listenerCaptor.capture(), any(), any()); @@ -80,7 +80,7 @@ void registerObservers(boolean enableCaptureGcCause) { Attributes.builder() .put("jvm.gc.name", "G1 Old Generation") .put("jvm.gc.action", "end of major GC"); - if (enableCaptureGcCause) { + if (captureGcCause) { attributesBuilder1.put("jvm.gc.cause", "Allocation Failure"); attributesBuilder2.put("jvm.gc.cause", "System.gc()"); } From 3555002c77cbe3daa2bf5e11e6f9500ed79746a7 Mon Sep 17 00:00:00 2001 From: Lauri Tulmin Date: Mon, 28 Apr 2025 13:18:33 +0300 Subject: [PATCH 11/11] simplify --- .../java8/GarbageCollector.java | 22 +++++-------- .../java8/GarbageCollectorTest.java | 33 +++++++++---------- 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java index d434bd5479ca..b5de4e922ed1 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollector.java @@ -12,6 +12,7 @@ import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.api.metrics.DoubleHistogram; import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil; @@ -134,20 +135,15 @@ public void handleNotification(Notification notification, Object unused) { String gcName = notificationInfo.getGcName(); String gcAction = notificationInfo.getGcAction(); - String gcCause = notificationInfo.getGcCause(); double duration = notificationInfo.getGcInfo().getDuration() / MILLIS_PER_S; - Attributes gcAttributes = - captureGcCause - ? Attributes.of( - JvmAttributes.JVM_GC_NAME, - gcName, - JvmAttributes.JVM_GC_ACTION, - gcAction, - JVM_GC_CAUSE, - gcCause) - : Attributes.of( - JvmAttributes.JVM_GC_NAME, gcName, JvmAttributes.JVM_GC_ACTION, gcAction); - gcDuration.record(duration, gcAttributes); + AttributesBuilder builder = Attributes.builder(); + builder.put(JvmAttributes.JVM_GC_NAME, gcName); + builder.put(JvmAttributes.JVM_GC_ACTION, gcAction); + if (captureGcCause) { + String gcCause = notificationInfo.getGcCause(); + builder.put(JVM_GC_CAUSE, gcCause); + } + gcDuration.record(duration, builder.build()); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java index ca5349016afe..bb5f18a3069e 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/GarbageCollectorTest.java @@ -5,8 +5,12 @@ package io.opentelemetry.instrumentation.runtimemetrics.java8; +import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.instrumentation.runtimemetrics.java8.ScopeUtil.EXPECTED_SCOPE; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.semconv.JvmAttributes.JVM_GC_ACTION; +import static io.opentelemetry.semconv.JvmAttributes.JVM_GC_NAME; import static java.util.Collections.singletonList; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -15,8 +19,6 @@ import com.sun.management.GarbageCollectionNotificationInfo; import com.sun.management.GcInfo; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension; import java.lang.management.GarbageCollectorMXBean; @@ -72,19 +74,6 @@ void registerObservers(boolean captureGcCause) { listener.handleNotification( createTestNotification("G1 Old Generation", "end of major GC", "System.gc()", 11), null); - AttributesBuilder attributesBuilder1 = - Attributes.builder() - .put("jvm.gc.name", "G1 Young Generation") - .put("jvm.gc.action", "end of minor GC"); - AttributesBuilder attributesBuilder2 = - Attributes.builder() - .put("jvm.gc.name", "G1 Old Generation") - .put("jvm.gc.action", "end of major GC"); - if (captureGcCause) { - attributesBuilder1.put("jvm.gc.cause", "Allocation Failure"); - attributesBuilder2.put("jvm.gc.cause", "System.gc()"); - } - testing.waitAndAssertMetrics( "io.opentelemetry.runtime-telemetry-java8", "jvm.gc.duration", @@ -102,13 +91,23 @@ void registerObservers(boolean captureGcCause) { point .hasCount(2) .hasSum(0.022) - .hasAttributes(attributesBuilder1.build()) + .hasAttributesSatisfyingExactly( + equalTo(JVM_GC_NAME, "G1 Young Generation"), + equalTo(JVM_GC_ACTION, "end of minor GC"), + equalTo( + stringKey("jvm.gc.cause"), + captureGcCause ? "Allocation Failure" : null)) .hasBucketBoundaries(GC_DURATION_BUCKETS), point -> point .hasCount(1) .hasSum(0.011) - .hasAttributes(attributesBuilder2.build()) + .hasAttributesSatisfyingExactly( + equalTo(JVM_GC_NAME, "G1 Old Generation"), + equalTo(JVM_GC_ACTION, "end of major GC"), + equalTo( + stringKey("jvm.gc.cause"), + captureGcCause ? "System.gc()" : null)) .hasBucketBoundaries(GC_DURATION_BUCKETS))))); }