diff --git a/CHANGELOG.md b/CHANGELOG.md index c225e6d4f..6ded3f210 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ Changelog ========= -# Next / TBD +# 0.49.1 / TBD +* [FEATURE] Add ZGC Major and Minor Cycles and ZGC Major and Minor Pauses beans support out of the box (Generational ZGC support) [#502][] # 0.49.0 / 2023-11-10 * [FEATURE] Adds more per-instance telemetry data around bean matching @@ -761,6 +762,7 @@ Changelog [#449]: https://github.com/DataDog/jmxfetch/issues/449 [#469]: https://github.com/DataDog/jmxfetch/issues/469 [#477]: https://github.com/DataDog/jmxfetch/issues/477 +[#502]: https://github.com/DataDog/jmxfetch/issues/502 [@alz]: https://github.com/alz [@aoking]: https://github.com/aoking [@arrawatia]: https://github.com/arrawatia diff --git a/src/main/resources/org/datadog/jmxfetch/new-gc-default-jmx-metrics.yaml b/src/main/resources/org/datadog/jmxfetch/new-gc-default-jmx-metrics.yaml index 6b195e9b6..557d1cb44 100644 --- a/src/main/resources/org/datadog/jmxfetch/new-gc-default-jmx-metrics.yaml +++ b/src/main/resources/org/datadog/jmxfetch/new-gc-default-jmx-metrics.yaml @@ -140,6 +140,52 @@ domain: java.lang type: GarbageCollector name: ZGC Pauses + attribute: + CollectionCount: + alias: jvm.gc.zgc_pauses_collection_count + metric_type: counter + CollectionTime: + alias: jvm.gc.zgc_pauses_collection_time + metric_type: counter + +# Z Garbage Collector with ZGenerational +- include: + domain: java.lang + type: GarbageCollector + name: ZGC Major Cycles + attribute: + CollectionCount: + alias: jvm.gc.zgc_cycles_collection_count + metric_type: counter + CollectionTime: + alias: jvm.gc.zgc_cycles_collection_time + metric_type: counter +- include: + domain: java.lang + type: GarbageCollector + name: ZGC Major Pauses + attribute: + CollectionCount: + alias: jvm.gc.zgc_pauses_collection_count + metric_type: counter + CollectionTime: + alias: jvm.gc.zgc_pauses_collection_time + metric_type: counter +- include: + domain: java.lang + type: GarbageCollector + name: ZGC Minor Cycles + attribute: + CollectionCount: + alias: jvm.gc.zgc_cycles_collection_count + metric_type: counter + CollectionTime: + alias: jvm.gc.zgc_cycles_collection_time + metric_type: counter +- include: + domain: java.lang + type: GarbageCollector + name: ZGC Minor Pauses attribute: CollectionCount: alias: jvm.gc.zgc_pauses_collection_count diff --git a/src/test/java/org/datadog/jmxfetch/TestGCMetrics.java b/src/test/java/org/datadog/jmxfetch/TestGCMetrics.java index fdb5f4d45..2f6806865 100644 --- a/src/test/java/org/datadog/jmxfetch/TestGCMetrics.java +++ b/src/test/java/org/datadog/jmxfetch/TestGCMetrics.java @@ -128,6 +128,26 @@ public void testDefaultNewGCMetricsUseZGC() throws IOException { } } + @Test + public void testDefaultNewGCMetricsUseGenerationalZGC() throws IOException { + try (final MisbehavingJMXServer server = new MisbehavingJMXServer.Builder().withJDKImage( + JDK_21).appendJavaOpts("-XX:+UseZGC -XX:+ZGenerational").build()) { + final List> actualMetrics = startAndGetMetrics(server, true); + assertThat(actualMetrics, hasSize(17)); + final List gcCycles = Arrays.asList( + "ZGC Major Cycles", + "ZGC Minor Cycles"); + assertGCMetric(actualMetrics, "jvm.gc.zgc_cycles_collection_count", gcCycles); + assertGCMetric(actualMetrics, "jvm.gc.zgc_cycles_collection_time", gcCycles); + + final List gcPauses = Arrays.asList( + "ZGC Major Pauses", + "ZGC Minor Pauses"); + assertGCMetric(actualMetrics, "jvm.gc.zgc_pauses_collection_count", gcPauses); + assertGCMetric(actualMetrics, "jvm.gc.zgc_pauses_collection_time", gcPauses); + } + } + private List> startAndGetMetrics(final MisbehavingJMXServer server, final boolean newGCMetrics) throws IOException { server.start(); @@ -188,24 +208,27 @@ private static void assertGCMetric(final List> actualMetrics filteredMetrics.add(actualMetric); } } - assertThat(filteredMetrics, hasSize(gcGenerations.size())); + assertThat( + String.format("Asserting filtered metrics for '%s' of metric '%s'", gcGenerations.size(), expectedMetric), + filteredMetrics, hasSize(gcGenerations.size())); for (final String name : gcGenerations) { - log.debug("Asserting for metric '{}'", name); + log.debug("Asserting for expected metric '{}' with tag 'name:{}'", expectedMetric, name); boolean found = false; for (Map filteredMetric : filteredMetrics) { final Set mTags = new HashSet<>( Arrays.asList((String[]) (filteredMetric.get("tags")))); if(mTags.contains(String.format("name:%s", name))) { - assertThat(mTags, not(empty())); - assertThat(mTags, hasSize(5)); - log.debug("mTags '{}' has size: {}\n{}", name, mTags.size(), mTags); - assertThat(mTags, hasItems( + assertThat("Should not be empty", mTags, not(empty())); + assertThat("Should have size 5", mTags, hasSize(5)); + assertThat("Has correct tags", + mTags, hasItems( "instance:jmxint_container", "jmx_domain:java.lang", "type:GarbageCollector", String.format("name:%s", name))); found = true; + break; } } assertThat(String.format("Did not find metric '%s'", name), found, is(true)); diff --git a/src/test/java/org/datadog/jmxfetch/util/server/MisbehavingJMXServer.java b/src/test/java/org/datadog/jmxfetch/util/server/MisbehavingJMXServer.java index 7ebf69dda..e598d1520 100644 --- a/src/test/java/org/datadog/jmxfetch/util/server/MisbehavingJMXServer.java +++ b/src/test/java/org/datadog/jmxfetch/util/server/MisbehavingJMXServer.java @@ -2,9 +2,11 @@ import java.io.IOException; import java.nio.file.Paths; +import java.time.Duration; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.containers.wait.strategy.WaitAllStrategy; import org.testcontainers.images.builder.ImageFromDockerfile; import org.testcontainers.lifecycle.Startable; @@ -49,14 +51,23 @@ public MisbehavingJMXServer( final ImageFromDockerfile img = new ImageFromDockerfile() .withFileFromPath(".", Paths.get("./tools/misbehaving-jmx-server/")) .withBuildArg("FINAL_JRE_IMAGE", this.jdkImage); + final WaitAllStrategy strategy = new WaitAllStrategy() + .withStrategy( + Wait.forLogMessage( + ".*Supervisor HTTP Server Started. Waiting for initialization payload POST to /init.*", + 1) + ) + .withStrategy( + Wait.forHttp("/healthy").forPort(this.supervisorPort).forStatusCode(200) + ) + .withStartupTimeout(Duration.ofSeconds(10)); this.server = new GenericContainer<>(img) + .withExposedPorts(rmiPort, controlPort, supervisorPort) .withEnv(RMI_PORT, String.valueOf(rmiPort)) .withEnv(CONTROL_PORT, String.valueOf(controlPort)) .withEnv(SUPERVISOR_PORT, String.valueOf(supervisorPort)) .withEnv(MISBEHAVING_OPTS, this.javaOpts) - .waitingFor(Wait.forLogMessage( - ".*Supervisor HTTP Server Started. Waiting for initialization payload POST to /init.*", - 1)); + .waitingFor(strategy); } @Override diff --git a/tools/misbehaving-jmx-server/src/main/java/org/datadog/supervisor/App.java b/tools/misbehaving-jmx-server/src/main/java/org/datadog/supervisor/App.java index 312dfc760..e770b601c 100644 --- a/tools/misbehaving-jmx-server/src/main/java/org/datadog/supervisor/App.java +++ b/tools/misbehaving-jmx-server/src/main/java/org/datadog/supervisor/App.java @@ -1,5 +1,6 @@ package org.datadog.supervisor; +import io.javalin.http.HttpStatus; import java.io.File; import java.io.IOException; import java.net.ConnectException; @@ -91,6 +92,10 @@ public static void main(String[] args) throws IOException { }); }); + app.get("/healthy", ctx -> { + ctx.status(HttpStatus.OK); + }); + app.get("/ready", ctx -> { if (started.get()) { ctx.status(200);