From b51a05333b6c2557613055d2138bef9c3e1ed369 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Fri, 4 Nov 2022 14:31:34 -0400 Subject: [PATCH 1/8] add thread count and tests --- .../internal/cpu/ThreadCountHandler.java | 45 +++++++++++ .../jfr/metrics/AbstractMetricsTest.java | 5 ++ .../jfr/metrics/JfrThreadCountTest.java | 74 +++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java create mode 100644 jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java new file mode 100644 index 000000000..224d0e371 --- /dev/null +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java @@ -0,0 +1,45 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.jfr.metrics.internal.cpu; + +import static io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler.defaultMeter; + +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler; +import java.time.Duration; +import java.util.Optional; +import jdk.jfr.consumer.RecordedEvent; + +public final class ThreadCountHandler implements RecordedEventHandler { + private static final String METRIC_NAME = "process.runtime.jvm.cpu.active_threads"; + private static final String EVENT_NAME = "jdk.JavaThreadStatistics"; + + private volatile long value = 0; + + public ThreadCountHandler() { + initializeMeter(defaultMeter()); + } + + @Override + public void accept(RecordedEvent ev) { + value = ev.getLong("activeCount"); + } + + @Override + public String getEventName() { + return EVENT_NAME; + } + + @Override + public void initializeMeter(Meter meter) { + meter.gaugeBuilder(METRIC_NAME).ofLongs().buildWithCallback(codm -> codm.record(value)); + } + + @Override + public Optional getPollingDuration() { + return Optional.of(Duration.ofSeconds(1)); + } +} diff --git a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/AbstractMetricsTest.java b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/AbstractMetricsTest.java index 5271521af..fba0d557b 100644 --- a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/AbstractMetricsTest.java +++ b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/AbstractMetricsTest.java @@ -22,9 +22,14 @@ public class AbstractMetricsTest { static SdkMeterProvider meterProvider; static InMemoryMetricReader metricReader; + static boolean isInitialized = false; @BeforeAll static void initializeOpenTelemetry() { + if (isInitialized) { + return; + } + isInitialized = true; metricReader = InMemoryMetricReader.create(); meterProvider = SdkMeterProvider.builder().registerMetricReader(metricReader).build(); GlobalOpenTelemetry.set(OpenTelemetrySdk.builder().setMeterProvider(meterProvider).build()); diff --git a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java new file mode 100644 index 000000000..ec75f87bf --- /dev/null +++ b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java @@ -0,0 +1,74 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.jfr.metrics; + +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class JfrThreadCountTest extends AbstractMetricsTest { + static class Stressor { + private Stressor() {} + ; + + public static void execute(int numberOfThreads, Runnable task) throws Exception { + List threads = new ArrayList<>(); + for (int n = 0; n < numberOfThreads; ++n) { + Thread t = new Thread(task); + threads.add(t); + t.start(); + } + for (Thread t : threads) { + t.join(); + } + } + } + + private static final int THREADS = 10; + private static final int MILLIS = 50; + + static Object monitor = new Object(); + private static int count = 0; + + private static void doWork(Object obj) throws InterruptedException { + count++; + synchronized (obj) { + // Spin until everyone is at critical section. All threads must be running now. + while (count < THREADS) { + Thread.sleep(MILLIS); + } + } + } + + @Test + public void shouldHaveGcAndLockEvents() throws Exception { + // This should generate some events + + Runnable r = + () -> { + // create contention between threads for one lock + try { + doWork(monitor); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }; + Stressor.execute(THREADS, r); + + waitAndAssertMetrics( + metric -> + metric + .hasName("process.runtime.jvm.cpu.active_threads") + .hasLongGaugeSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> + point.satisfies( + pointData -> + Assertions.assertTrue(pointData.getValue() >= THREADS))))); + } +} From d244f91d5955269b968bc7ffc54573b9b1eba6c6 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Fri, 4 Nov 2022 14:32:05 -0400 Subject: [PATCH 2/8] add handler to registry --- .../io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java index d7a62b46b..7f4af8c24 100644 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java @@ -12,6 +12,7 @@ import io.opentelemetry.contrib.jfr.metrics.internal.cpu.ContextSwitchRateHandler; import io.opentelemetry.contrib.jfr.metrics.internal.cpu.LongLockHandler; import io.opentelemetry.contrib.jfr.metrics.internal.cpu.OverallCPULoadHandler; +import io.opentelemetry.contrib.jfr.metrics.internal.cpu.ThreadCountHandler; import io.opentelemetry.contrib.jfr.metrics.internal.memory.G1HeapSummaryHandler; import io.opentelemetry.contrib.jfr.metrics.internal.memory.GCHeapSummaryHandler; import io.opentelemetry.contrib.jfr.metrics.internal.memory.ObjectAllocationInNewTLABHandler; @@ -68,7 +69,8 @@ static HandlerRegistry createDefault(MeterProvider meterProvider) { new ContextSwitchRateHandler(), new OverallCPULoadHandler(), new ContainerConfigurationHandler(), - new LongLockHandler(grouper)); + new LongLockHandler(grouper), + new ThreadCountHandler()); handlers.addAll(basicHandlers); var meter = From fc24a17c0903f21f312a8e33975b4a47e1bcb5f2 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Fri, 4 Nov 2022 15:10:57 -0400 Subject: [PATCH 3/8] add classes loaded count metric --- .../contrib/jfr/metrics/HandlerRegistry.java | 4 +- .../classLoading/ClassesLoadedHandler.java | 50 +++++++++++++++++++ .../internal/cpu/ThreadCountHandler.java | 7 ++- ...tTest.java => JfrPeriodicMetricsTest.java} | 17 +++++-- 4 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classLoading/ClassesLoadedHandler.java rename jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/{JfrThreadCountTest.java => JfrPeriodicMetricsTest.java} (75%) diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java index 7f4af8c24..ab47b96bd 100644 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java @@ -8,6 +8,7 @@ import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler; import io.opentelemetry.contrib.jfr.metrics.internal.ThreadGrouper; +import io.opentelemetry.contrib.jfr.metrics.internal.classLoading.ClassesLoadedHandler; import io.opentelemetry.contrib.jfr.metrics.internal.container.ContainerConfigurationHandler; import io.opentelemetry.contrib.jfr.metrics.internal.cpu.ContextSwitchRateHandler; import io.opentelemetry.contrib.jfr.metrics.internal.cpu.LongLockHandler; @@ -70,7 +71,8 @@ static HandlerRegistry createDefault(MeterProvider meterProvider) { new OverallCPULoadHandler(), new ContainerConfigurationHandler(), new LongLockHandler(grouper), - new ThreadCountHandler()); + new ThreadCountHandler(), + new ClassesLoadedHandler()); handlers.addAll(basicHandlers); var meter = diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classLoading/ClassesLoadedHandler.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classLoading/ClassesLoadedHandler.java new file mode 100644 index 000000000..efaeb04fa --- /dev/null +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classLoading/ClassesLoadedHandler.java @@ -0,0 +1,50 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.jfr.metrics.internal.classLoading; + +import static io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler.defaultMeter; + +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler; +import java.time.Duration; +import java.util.Optional; +import jdk.jfr.consumer.RecordedEvent; + +public final class ClassesLoadedHandler implements RecordedEventHandler { + private static final String METRIC_NAME = "process.runtime.jvm.cpu.loaded_class_count"; + private static final String EVENT_NAME = "jdk.ClassLoadingStatistics"; + private static final String METRIC_DESCRIPTION = "Number of loaded classes"; + + private volatile long value = 0; + + public ClassesLoadedHandler() { + initializeMeter(defaultMeter()); + } + + @Override + public void accept(RecordedEvent ev) { + value = ev.getLong("loadedClassCount"); + } + + @Override + public String getEventName() { + return EVENT_NAME; + } + + @Override + public void initializeMeter(Meter meter) { + meter + .gaugeBuilder(METRIC_NAME) + .ofLongs() + .setDescription(METRIC_DESCRIPTION) + .buildWithCallback(measurement -> measurement.record(value)); + } + + @Override + public Optional getPollingDuration() { + return Optional.of(Duration.ofSeconds(1)); + } +} diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java index 224d0e371..b30a6eae8 100644 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java @@ -16,6 +16,7 @@ public final class ThreadCountHandler implements RecordedEventHandler { private static final String METRIC_NAME = "process.runtime.jvm.cpu.active_threads"; private static final String EVENT_NAME = "jdk.JavaThreadStatistics"; + private static final String METRIC_DESCRIPTION = "Number of active threads"; private volatile long value = 0; @@ -35,7 +36,11 @@ public String getEventName() { @Override public void initializeMeter(Meter meter) { - meter.gaugeBuilder(METRIC_NAME).ofLongs().buildWithCallback(codm -> codm.record(value)); + meter + .gaugeBuilder(METRIC_NAME) + .ofLongs() + .setDescription(METRIC_DESCRIPTION) + .buildWithCallback(measurement -> measurement.record(value)); } @Override diff --git a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrPeriodicMetricsTest.java similarity index 75% rename from jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java rename to jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrPeriodicMetricsTest.java index ec75f87bf..6c5359ac3 100644 --- a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java +++ b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrPeriodicMetricsTest.java @@ -10,10 +10,9 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class JfrThreadCountTest extends AbstractMetricsTest { +public class JfrPeriodicMetricsTest extends AbstractMetricsTest { static class Stressor { private Stressor() {} - ; public static void execute(int numberOfThreads, Runnable task) throws Exception { List threads = new ArrayList<>(); @@ -45,7 +44,7 @@ private static void doWork(Object obj) throws InterruptedException { } @Test - public void shouldHaveGcAndLockEvents() throws Exception { + public void shouldHaveJfrPeriodicEvents() throws Exception { // This should generate some events Runnable r = @@ -69,6 +68,16 @@ public void shouldHaveGcAndLockEvents() throws Exception { point -> point.satisfies( pointData -> - Assertions.assertTrue(pointData.getValue() >= THREADS))))); + Assertions.assertTrue(pointData.getValue() >= THREADS)))), + metric -> + metric + .hasName("process.runtime.jvm.cpu.loaded_class_count") + .hasLongGaugeSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> + point.satisfies( + pointData -> + Assertions.assertTrue(pointData.getValue() >= 0))))); } } From 931a13000a8c2f6826aba7841328059441a9ed89 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Wed, 9 Nov 2022 14:14:27 -0500 Subject: [PATCH 4/8] Conform to spec. Update tests. --- .../contrib/jfr/metrics/HandlerRegistry.java | 4 +- .../jfr/metrics/internal/Constants.java | 6 ++ .../classLoading/ClassesLoadedHandler.java | 50 ----------- .../classes/ClassesLoadedHandler.java | 68 +++++++++++++++ .../internal/cpu/ThreadCountHandler.java | 50 ----------- .../internal/threads/ThreadCountHandler.java | 62 ++++++++++++++ .../metrics/JfrClassesLoadedCountTest.java | 49 +++++++++++ .../jfr/metrics/JfrPeriodicMetricsTest.java | 83 ------------------- .../jfr/metrics/JfrThreadCountTest.java | 78 +++++++++++++++++ 9 files changed, 265 insertions(+), 185 deletions(-) delete mode 100644 jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classLoading/ClassesLoadedHandler.java create mode 100644 jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classes/ClassesLoadedHandler.java delete mode 100644 jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java create mode 100644 jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java create mode 100644 jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrClassesLoadedCountTest.java delete mode 100644 jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrPeriodicMetricsTest.java create mode 100644 jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java index ab47b96bd..5b3f9b52c 100644 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/HandlerRegistry.java @@ -8,12 +8,11 @@ import io.opentelemetry.api.metrics.MeterProvider; import io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler; import io.opentelemetry.contrib.jfr.metrics.internal.ThreadGrouper; -import io.opentelemetry.contrib.jfr.metrics.internal.classLoading.ClassesLoadedHandler; +import io.opentelemetry.contrib.jfr.metrics.internal.classes.ClassesLoadedHandler; import io.opentelemetry.contrib.jfr.metrics.internal.container.ContainerConfigurationHandler; import io.opentelemetry.contrib.jfr.metrics.internal.cpu.ContextSwitchRateHandler; import io.opentelemetry.contrib.jfr.metrics.internal.cpu.LongLockHandler; import io.opentelemetry.contrib.jfr.metrics.internal.cpu.OverallCPULoadHandler; -import io.opentelemetry.contrib.jfr.metrics.internal.cpu.ThreadCountHandler; import io.opentelemetry.contrib.jfr.metrics.internal.memory.G1HeapSummaryHandler; import io.opentelemetry.contrib.jfr.metrics.internal.memory.GCHeapSummaryHandler; import io.opentelemetry.contrib.jfr.metrics.internal.memory.ObjectAllocationInNewTLABHandler; @@ -21,6 +20,7 @@ import io.opentelemetry.contrib.jfr.metrics.internal.memory.ParallelHeapSummaryHandler; import io.opentelemetry.contrib.jfr.metrics.internal.network.NetworkReadHandler; import io.opentelemetry.contrib.jfr.metrics.internal.network.NetworkWriteHandler; +import io.opentelemetry.contrib.jfr.metrics.internal.threads.ThreadCountHandler; import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.HashSet; diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java index 4cc7cdbf7..b711c6799 100644 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java @@ -27,6 +27,8 @@ private Constants() {} public static final String REGION_COUNT = "region.count"; public static final String COMMITTED = "committed"; public static final String RESERVED = "reserved"; + public static final String TRUE = "true"; + public static final String FALSE = "false"; public static final String METRIC_NAME_NETWORK_BYTES = "process.runtime.jvm.network.io"; public static final String METRIC_DESCRIPTION_NETWORK_BYTES = "Network read/write bytes"; @@ -43,4 +45,8 @@ private Constants() {} public static final AttributeKey ATTR_ARENA_NAME = AttributeKey.stringKey("arena"); public static final AttributeKey ATTR_NETWORK_MODE = AttributeKey.stringKey("mode"); public static final AttributeKey ATTR_USAGE = AttributeKey.stringKey("usage.type"); + public static final AttributeKey ATTR_DAEMON = AttributeKey.stringKey("daemon"); + + public static final String UNIT_CLASSES = "{classes}"; + public static final String UNIT_THREADS = "{threads}"; } diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classLoading/ClassesLoadedHandler.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classLoading/ClassesLoadedHandler.java deleted file mode 100644 index efaeb04fa..000000000 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classLoading/ClassesLoadedHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.jfr.metrics.internal.classLoading; - -import static io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler.defaultMeter; - -import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler; -import java.time.Duration; -import java.util.Optional; -import jdk.jfr.consumer.RecordedEvent; - -public final class ClassesLoadedHandler implements RecordedEventHandler { - private static final String METRIC_NAME = "process.runtime.jvm.cpu.loaded_class_count"; - private static final String EVENT_NAME = "jdk.ClassLoadingStatistics"; - private static final String METRIC_DESCRIPTION = "Number of loaded classes"; - - private volatile long value = 0; - - public ClassesLoadedHandler() { - initializeMeter(defaultMeter()); - } - - @Override - public void accept(RecordedEvent ev) { - value = ev.getLong("loadedClassCount"); - } - - @Override - public String getEventName() { - return EVENT_NAME; - } - - @Override - public void initializeMeter(Meter meter) { - meter - .gaugeBuilder(METRIC_NAME) - .ofLongs() - .setDescription(METRIC_DESCRIPTION) - .buildWithCallback(measurement -> measurement.record(value)); - } - - @Override - public Optional getPollingDuration() { - return Optional.of(Duration.ofSeconds(1)); - } -} diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classes/ClassesLoadedHandler.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classes/ClassesLoadedHandler.java new file mode 100644 index 000000000..2580ec9bd --- /dev/null +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classes/ClassesLoadedHandler.java @@ -0,0 +1,68 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.jfr.metrics.internal.classes; + +import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.UNIT_CLASSES; +import static io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler.defaultMeter; + +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler; +import java.time.Duration; +import java.util.Optional; +import jdk.jfr.consumer.RecordedEvent; + +public final class ClassesLoadedHandler implements RecordedEventHandler { + private static final String METRIC_NAME_LOADED = "process.runtime.jvm.classes.loaded"; + private static final String METRIC_NAME_UNLOADED = "process.runtime.jvm.classes.unloaded"; + private static final String METRIC_NAME_CURRENT = "process.runtime.jvm.classes.current_loaded"; + private static final String EVENT_NAME = "jdk.ClassLoadingStatistics"; + private static final String METRIC_DESCRIPTION_CURRENT = "Number of classes currently loaded"; + private static final String METRIC_DESCRIPTION_LOADED = + "Number of classes loaded since JVM start"; + private static final String METRIC_DESCRIPTION_UNLOADED = + "Number of classes unloaded since JVM start"; + private volatile long loaded = 0; + private volatile long unloaded = 0; + + public ClassesLoadedHandler() { + initializeMeter(defaultMeter()); + } + + @Override + public void accept(RecordedEvent ev) { + loaded = ev.getLong("loadedClassCount"); + unloaded = ev.getLong("unloadedClassCount"); + } + + @Override + public String getEventName() { + return EVENT_NAME; + } + + @Override + public void initializeMeter(Meter meter) { + meter + .upDownCounterBuilder(METRIC_NAME_CURRENT) + .setDescription(METRIC_DESCRIPTION_CURRENT) + .setUnit(UNIT_CLASSES) + .buildWithCallback(measurement -> measurement.record(loaded - unloaded)); + meter + .counterBuilder(METRIC_NAME_LOADED) + .setDescription(METRIC_DESCRIPTION_LOADED) + .setUnit(UNIT_CLASSES) + .buildWithCallback(measurement -> measurement.record(loaded)); + meter + .counterBuilder(METRIC_NAME_UNLOADED) + .setDescription(METRIC_DESCRIPTION_UNLOADED) + .setUnit(UNIT_CLASSES) + .buildWithCallback(measurement -> measurement.record(unloaded)); + } + + @Override + public Optional getPollingDuration() { + return Optional.of(Duration.ofSeconds(1)); + } +} diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java deleted file mode 100644 index b30a6eae8..000000000 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/cpu/ThreadCountHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.jfr.metrics.internal.cpu; - -import static io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler.defaultMeter; - -import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler; -import java.time.Duration; -import java.util.Optional; -import jdk.jfr.consumer.RecordedEvent; - -public final class ThreadCountHandler implements RecordedEventHandler { - private static final String METRIC_NAME = "process.runtime.jvm.cpu.active_threads"; - private static final String EVENT_NAME = "jdk.JavaThreadStatistics"; - private static final String METRIC_DESCRIPTION = "Number of active threads"; - - private volatile long value = 0; - - public ThreadCountHandler() { - initializeMeter(defaultMeter()); - } - - @Override - public void accept(RecordedEvent ev) { - value = ev.getLong("activeCount"); - } - - @Override - public String getEventName() { - return EVENT_NAME; - } - - @Override - public void initializeMeter(Meter meter) { - meter - .gaugeBuilder(METRIC_NAME) - .ofLongs() - .setDescription(METRIC_DESCRIPTION) - .buildWithCallback(measurement -> measurement.record(value)); - } - - @Override - public Optional getPollingDuration() { - return Optional.of(Duration.ofSeconds(1)); - } -} diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java new file mode 100644 index 000000000..1e5eb956f --- /dev/null +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java @@ -0,0 +1,62 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.jfr.metrics.internal.threads; + +import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.ATTR_DAEMON; +import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.FALSE; +import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.TRUE; +import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.UNIT_THREADS; +import static io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler.defaultMeter; + +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler; +import java.time.Duration; +import java.util.Optional; +import jdk.jfr.consumer.RecordedEvent; + +public final class ThreadCountHandler implements RecordedEventHandler { + private static final String METRIC_NAME = "process.runtime.jvm.threads.count"; + private static final String EVENT_NAME = "jdk.JavaThreadStatistics"; + private static final String METRIC_DESCRIPTION = "Number of executing threads"; + private static final Attributes ATTR_DAEMON_TRUE = Attributes.of(ATTR_DAEMON, TRUE); + private static final Attributes ATTR_DAEMON_FALSE = Attributes.of(ATTR_DAEMON, FALSE); + private volatile long activeCount = 0; + private volatile long daemonCount = 0; + + public ThreadCountHandler() { + initializeMeter(defaultMeter()); + } + + @Override + public void accept(RecordedEvent ev) { + activeCount = ev.getLong("activeCount"); + daemonCount = ev.getLong("daemonCount"); + } + + @Override + public String getEventName() { + return EVENT_NAME; + } + + @Override + public void initializeMeter(Meter meter) { + meter + .upDownCounterBuilder(METRIC_NAME) + .setDescription(METRIC_DESCRIPTION) + .setUnit(UNIT_THREADS) + .buildWithCallback( + measurement -> { + measurement.record(daemonCount, ATTR_DAEMON_TRUE); + measurement.record(activeCount - daemonCount, ATTR_DAEMON_FALSE); + }); + } + + @Override + public Optional getPollingDuration() { + return Optional.of(Duration.ofSeconds(1)); + } +} diff --git a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrClassesLoadedCountTest.java b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrClassesLoadedCountTest.java new file mode 100644 index 000000000..d7dbd72bd --- /dev/null +++ b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrClassesLoadedCountTest.java @@ -0,0 +1,49 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.jfr.metrics; + +import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.UNIT_CLASSES; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class JfrClassesLoadedCountTest extends AbstractMetricsTest { + + @Test + void shouldHaveJfrLoadedClassesCountEvents() throws Exception { + Thread.sleep(2000); + + waitAndAssertMetrics( + metric -> + metric + .hasName("process.runtime.jvm.classes.loaded") + .hasDescription("Number of classes loaded since JVM start") + .hasUnit(UNIT_CLASSES) + .hasLongSumSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> + point.satisfies( + pointData -> Assertions.assertTrue(pointData.getValue() > 0)))), + metric -> + metric + .hasName("process.runtime.jvm.classes.current_loaded") + .hasDescription("Number of classes currently loaded") + .hasUnit(UNIT_CLASSES) + .hasLongSumSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> + point.satisfies( + pointData -> + Assertions.assertTrue(pointData.getValue() >= 0)))), + metric -> + metric + .hasName("process.runtime.jvm.classes.unloaded") + .hasDescription("Number of classes unloaded since JVM start") + .hasUnit(UNIT_CLASSES)); + } +} diff --git a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrPeriodicMetricsTest.java b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrPeriodicMetricsTest.java deleted file mode 100644 index 6c5359ac3..000000000 --- a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrPeriodicMetricsTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.contrib.jfr.metrics; - -import java.util.ArrayList; -import java.util.List; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -public class JfrPeriodicMetricsTest extends AbstractMetricsTest { - static class Stressor { - private Stressor() {} - - public static void execute(int numberOfThreads, Runnable task) throws Exception { - List threads = new ArrayList<>(); - for (int n = 0; n < numberOfThreads; ++n) { - Thread t = new Thread(task); - threads.add(t); - t.start(); - } - for (Thread t : threads) { - t.join(); - } - } - } - - private static final int THREADS = 10; - private static final int MILLIS = 50; - - static Object monitor = new Object(); - private static int count = 0; - - private static void doWork(Object obj) throws InterruptedException { - count++; - synchronized (obj) { - // Spin until everyone is at critical section. All threads must be running now. - while (count < THREADS) { - Thread.sleep(MILLIS); - } - } - } - - @Test - public void shouldHaveJfrPeriodicEvents() throws Exception { - // This should generate some events - - Runnable r = - () -> { - // create contention between threads for one lock - try { - doWork(monitor); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - }; - Stressor.execute(THREADS, r); - - waitAndAssertMetrics( - metric -> - metric - .hasName("process.runtime.jvm.cpu.active_threads") - .hasLongGaugeSatisfying( - sum -> - sum.hasPointsSatisfying( - point -> - point.satisfies( - pointData -> - Assertions.assertTrue(pointData.getValue() >= THREADS)))), - metric -> - metric - .hasName("process.runtime.jvm.cpu.loaded_class_count") - .hasLongGaugeSatisfying( - sum -> - sum.hasPointsSatisfying( - point -> - point.satisfies( - pointData -> - Assertions.assertTrue(pointData.getValue() >= 0))))); - } -} diff --git a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java new file mode 100644 index 000000000..3e3ce505d --- /dev/null +++ b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java @@ -0,0 +1,78 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.contrib.jfr.metrics; + +import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.UNIT_THREADS; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.sdk.metrics.data.LongPointData; +import io.opentelemetry.sdk.metrics.data.PointData; +import io.opentelemetry.sdk.metrics.data.SumData; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class JfrThreadCountTest extends AbstractMetricsTest { + private static final int SAMPLING_INTERVAL = 1000; + + private static void doWork() throws InterruptedException { + Thread.sleep(2 * SAMPLING_INTERVAL); + } + + @Test + void shouldHaveJfrThreadCountEvents() throws Exception { + // This should generate some events + Runnable work = + () -> { + // create contention between threads for one lock + try { + doWork(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + }; + Thread userThread = new Thread(work); + userThread.setDaemon(false); + userThread.start(); + + Thread daemonThread = new Thread(work); + daemonThread.setDaemon(true); + daemonThread.start(); + + userThread.join(); + daemonThread.join(); + + waitAndAssertMetrics( + metric -> + metric + .hasName("process.runtime.jvm.threads.count") + .hasUnit(UNIT_THREADS) + .satisfies( + metricData -> { + SumData sumData = metricData.getLongSumData(); + boolean foundDaemon = false; + boolean foundNonDaemon = false; + for (PointData point : sumData.getPoints()) { + LongPointData longPoint = (LongPointData) point; + if (longPoint.getValue() > 0 + && longPoint + .getAttributes() + .asMap() + .get(AttributeKey.stringKey("daemon")) + .equals("false")) { + foundNonDaemon = true; + } else if (longPoint.getValue() > 0 + && longPoint + .getAttributes() + .asMap() + .get(AttributeKey.stringKey("daemon")) + .equals("true")) { + foundDaemon = true; + } + } + Assertions.assertTrue(foundDaemon && foundNonDaemon); + })); + } +} From 4a7602e6467d51ccf550d34f57fb391ee61c1f04 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Wed, 9 Nov 2022 14:29:17 -0500 Subject: [PATCH 5/8] minor touch up --- .../contrib/jfr/metrics/internal/Constants.java | 3 ++- .../jfr/metrics/JfrClassesLoadedCountTest.java | 9 ++++++++- .../contrib/jfr/metrics/JfrThreadCountTest.java | 11 +++++++---- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java index b711c6799..4e720c00d 100644 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java @@ -27,6 +27,7 @@ private Constants() {} public static final String REGION_COUNT = "region.count"; public static final String COMMITTED = "committed"; public static final String RESERVED = "reserved"; + public static final String DAEMON = "daemon"; public static final String TRUE = "true"; public static final String FALSE = "false"; @@ -45,7 +46,7 @@ private Constants() {} public static final AttributeKey ATTR_ARENA_NAME = AttributeKey.stringKey("arena"); public static final AttributeKey ATTR_NETWORK_MODE = AttributeKey.stringKey("mode"); public static final AttributeKey ATTR_USAGE = AttributeKey.stringKey("usage.type"); - public static final AttributeKey ATTR_DAEMON = AttributeKey.stringKey("daemon"); + public static final AttributeKey ATTR_DAEMON = AttributeKey.stringKey(DAEMON); public static final String UNIT_CLASSES = "{classes}"; public static final String UNIT_THREADS = "{threads}"; diff --git a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrClassesLoadedCountTest.java b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrClassesLoadedCountTest.java index d7dbd72bd..ccada633e 100644 --- a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrClassesLoadedCountTest.java +++ b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrClassesLoadedCountTest.java @@ -44,6 +44,13 @@ void shouldHaveJfrLoadedClassesCountEvents() throws Exception { metric .hasName("process.runtime.jvm.classes.unloaded") .hasDescription("Number of classes unloaded since JVM start") - .hasUnit(UNIT_CLASSES)); + .hasUnit(UNIT_CLASSES) + .hasLongSumSatisfying( + sum -> + sum.hasPointsSatisfying( + point -> + point.satisfies( + pointData -> + Assertions.assertTrue(pointData.getValue() >= 0))))); } } diff --git a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java index 3e3ce505d..5c3decca9 100644 --- a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java +++ b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java @@ -5,6 +5,9 @@ package io.opentelemetry.contrib.jfr.metrics; +import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.DAEMON; +import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.FALSE; +import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.TRUE; import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.UNIT_THREADS; import io.opentelemetry.api.common.AttributeKey; @@ -60,15 +63,15 @@ void shouldHaveJfrThreadCountEvents() throws Exception { && longPoint .getAttributes() .asMap() - .get(AttributeKey.stringKey("daemon")) - .equals("false")) { + .get(AttributeKey.stringKey(DAEMON)) + .equals(FALSE)) { foundNonDaemon = true; } else if (longPoint.getValue() > 0 && longPoint .getAttributes() .asMap() - .get(AttributeKey.stringKey("daemon")) - .equals("true")) { + .get(AttributeKey.stringKey(DAEMON)) + .equals(TRUE)) { foundDaemon = true; } } From b02a36d77090d835183c060eea8c61edd1ef0f0d Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Thu, 10 Nov 2022 10:37:56 -0500 Subject: [PATCH 6/8] Update jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java Co-authored-by: Mateusz Rzeszutek --- .../jfr/metrics/internal/threads/ThreadCountHandler.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java index 1e5eb956f..6907f9769 100644 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java @@ -50,8 +50,9 @@ public void initializeMeter(Meter meter) { .setUnit(UNIT_THREADS) .buildWithCallback( measurement -> { - measurement.record(daemonCount, ATTR_DAEMON_TRUE); - measurement.record(activeCount - daemonCount, ATTR_DAEMON_FALSE); + long d = daemonCount; + measurement.record(d, ATTR_DAEMON_TRUE); + measurement.record(activeCount - d, ATTR_DAEMON_FALSE); }); } From 153a743e8c614f4973c2a868c5d197cdf341dfe7 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Thu, 10 Nov 2022 11:23:20 -0500 Subject: [PATCH 7/8] comment. boolean attribute. simplify test case. --- .../jfr/metrics/internal/Constants.java | 5 +-- .../classes/ClassesLoadedHandler.java | 10 ++++++ .../internal/threads/ThreadCountHandler.java | 6 ++-- .../jfr/metrics/JfrThreadCountTest.java | 34 +++++-------------- 4 files changed, 22 insertions(+), 33 deletions(-) diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java index 4e720c00d..00da5621e 100644 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/Constants.java @@ -28,8 +28,6 @@ private Constants() {} public static final String COMMITTED = "committed"; public static final String RESERVED = "reserved"; public static final String DAEMON = "daemon"; - public static final String TRUE = "true"; - public static final String FALSE = "false"; public static final String METRIC_NAME_NETWORK_BYTES = "process.runtime.jvm.network.io"; public static final String METRIC_DESCRIPTION_NETWORK_BYTES = "Network read/write bytes"; @@ -46,8 +44,7 @@ private Constants() {} public static final AttributeKey ATTR_ARENA_NAME = AttributeKey.stringKey("arena"); public static final AttributeKey ATTR_NETWORK_MODE = AttributeKey.stringKey("mode"); public static final AttributeKey ATTR_USAGE = AttributeKey.stringKey("usage.type"); - public static final AttributeKey ATTR_DAEMON = AttributeKey.stringKey(DAEMON); - + public static final AttributeKey ATTR_DAEMON = AttributeKey.booleanKey(DAEMON); public static final String UNIT_CLASSES = "{classes}"; public static final String UNIT_THREADS = "{threads}"; } diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classes/ClassesLoadedHandler.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classes/ClassesLoadedHandler.java index 2580ec9bd..ad577f38b 100644 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classes/ClassesLoadedHandler.java +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/classes/ClassesLoadedHandler.java @@ -15,9 +15,19 @@ import jdk.jfr.consumer.RecordedEvent; public final class ClassesLoadedHandler implements RecordedEventHandler { + /** + * process.runtime.jvm.classes.loaded is the total number of classes loaded since JVM start. See: + * https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/semantic_conventions/runtime-environment-metrics.md#jvm-metrics + */ private static final String METRIC_NAME_LOADED = "process.runtime.jvm.classes.loaded"; + private static final String METRIC_NAME_UNLOADED = "process.runtime.jvm.classes.unloaded"; + /** + * process.runtime.jvm.classes.current_loaded is the number of classes loaded at the time of + * jdk.ClassLoadingStatistics event emission. + */ private static final String METRIC_NAME_CURRENT = "process.runtime.jvm.classes.current_loaded"; + private static final String EVENT_NAME = "jdk.ClassLoadingStatistics"; private static final String METRIC_DESCRIPTION_CURRENT = "Number of classes currently loaded"; private static final String METRIC_DESCRIPTION_LOADED = diff --git a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java index 1e5eb956f..214a7eb83 100644 --- a/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java +++ b/jfr-streaming/src/main/java/io/opentelemetry/contrib/jfr/metrics/internal/threads/ThreadCountHandler.java @@ -6,8 +6,6 @@ package io.opentelemetry.contrib.jfr.metrics.internal.threads; import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.ATTR_DAEMON; -import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.FALSE; -import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.TRUE; import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.UNIT_THREADS; import static io.opentelemetry.contrib.jfr.metrics.internal.RecordedEventHandler.defaultMeter; @@ -22,8 +20,8 @@ public final class ThreadCountHandler implements RecordedEventHandler { private static final String METRIC_NAME = "process.runtime.jvm.threads.count"; private static final String EVENT_NAME = "jdk.JavaThreadStatistics"; private static final String METRIC_DESCRIPTION = "Number of executing threads"; - private static final Attributes ATTR_DAEMON_TRUE = Attributes.of(ATTR_DAEMON, TRUE); - private static final Attributes ATTR_DAEMON_FALSE = Attributes.of(ATTR_DAEMON, FALSE); + private static final Attributes ATTR_DAEMON_TRUE = Attributes.of(ATTR_DAEMON, true); + private static final Attributes ATTR_DAEMON_FALSE = Attributes.of(ATTR_DAEMON, false); private volatile long activeCount = 0; private volatile long daemonCount = 0; diff --git a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java index 5c3decca9..b31d83204 100644 --- a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java +++ b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java @@ -6,15 +6,12 @@ package io.opentelemetry.contrib.jfr.metrics; import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.DAEMON; -import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.FALSE; -import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.TRUE; import static io.opentelemetry.contrib.jfr.metrics.internal.Constants.UNIT_THREADS; +import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.sdk.metrics.data.LongPointData; -import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.data.SumData; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class JfrThreadCountTest extends AbstractMetricsTest { @@ -24,6 +21,10 @@ private static void doWork() throws InterruptedException { Thread.sleep(2 * SAMPLING_INTERVAL); } + private static boolean isDaemon(LongPointData p) { + return p.getAttributes().asMap().get(AttributeKey.booleanKey(DAEMON)).equals(true); + } + @Test void shouldHaveJfrThreadCountEvents() throws Exception { // This should generate some events @@ -55,27 +56,10 @@ void shouldHaveJfrThreadCountEvents() throws Exception { .satisfies( metricData -> { SumData sumData = metricData.getLongSumData(); - boolean foundDaemon = false; - boolean foundNonDaemon = false; - for (PointData point : sumData.getPoints()) { - LongPointData longPoint = (LongPointData) point; - if (longPoint.getValue() > 0 - && longPoint - .getAttributes() - .asMap() - .get(AttributeKey.stringKey(DAEMON)) - .equals(FALSE)) { - foundNonDaemon = true; - } else if (longPoint.getValue() > 0 - && longPoint - .getAttributes() - .asMap() - .get(AttributeKey.stringKey(DAEMON)) - .equals(TRUE)) { - foundDaemon = true; - } - } - Assertions.assertTrue(foundDaemon && foundNonDaemon); + assertThat(sumData.getPoints()) + .map(LongPointData.class::cast) + .anyMatch(p -> p.getValue() > 0 && isDaemon(p)) + .anyMatch(p -> p.getValue() > 0 && !isDaemon(p)); })); } } From 435c02d440fe59cd78a8259e91e45196960a524a Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Thu, 10 Nov 2022 11:50:51 -0500 Subject: [PATCH 8/8] Update jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java Co-authored-by: Mateusz Rzeszutek --- .../opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java index b31d83204..f30c3eeb7 100644 --- a/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java +++ b/jfr-streaming/src/test/java/io/opentelemetry/contrib/jfr/metrics/JfrThreadCountTest.java @@ -22,7 +22,9 @@ private static void doWork() throws InterruptedException { } private static boolean isDaemon(LongPointData p) { - return p.getAttributes().asMap().get(AttributeKey.booleanKey(DAEMON)).equals(true); + Boolean daemon = p.getAttributes().get(AttributeKey.booleanKey(DAEMON)); + assertThat(daemon).isNotNull(); + return daemon; } @Test