8203359: Container level resources events

Reviewed-by: sgehwolf, egahlin
This commit is contained in:
Jaroslav Bachorik 2021-05-21 09:44:45 +00:00
parent b5d32bbfc7
commit ee2651b9e5
14 changed files with 594 additions and 16 deletions

View File

@ -218,7 +218,8 @@ module java.base {
jdk.management.agent,
jdk.internal.jvmstat;
exports jdk.internal.platform to
jdk.management;
jdk.management,
jdk.jfr;
exports jdk.internal.ref to
java.desktop,
jdk.incubator.foreign;

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, DataDog. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr.events;
import jdk.jfr.Category;
import jdk.jfr.DataAmount;
import jdk.jfr.Description;
import jdk.jfr.Enabled;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.Period;
import jdk.jfr.StackTrace;
import jdk.jfr.Threshold;
import jdk.jfr.Timespan;
import jdk.jfr.internal.Type;
@Name(Type.EVENT_NAME_PREFIX + "ContainerCPUThrottling")
@Label("CPU Throttling")
@Category({"Operating System", "Processor"})
@Description("Container CPU throttling related information")
public class ContainerCPUThrottlingEvent extends AbstractJDKEvent {
@Label("CPU Elapsed Slices")
@Description("Number of time-slice periods that have elapsed if a CPU quota has been setup for the container")
public long cpuElapsedSlices;
@Label("CPU Throttled Slices")
@Description("Number of time-slice periods that the CPU has been throttled or limited due to exceeding CPU quota")
public long cpuThrottledSlices;
@Label("CPU Throttled Time")
@Description("Total time duration, in nanoseconds, that the CPU has been throttled or limited due to exceeding CPU quota")
@Timespan
public long cpuThrottledTime;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, DataDog. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr.events;
import jdk.jfr.Category;
import jdk.jfr.DataAmount;
import jdk.jfr.Description;
import jdk.jfr.Enabled;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.Period;
import jdk.jfr.StackTrace;
import jdk.jfr.Threshold;
import jdk.jfr.Timespan;
import jdk.jfr.internal.Type;
@Name(Type.EVENT_NAME_PREFIX + "ContainerCPUUsage")
@Label("CPU Usage")
@Category({"Operating System", "Processor"})
@Description("Container CPU usage related information")
public class ContainerCPUUsageEvent extends AbstractJDKEvent {
@Label("CPU Time")
@Description("Aggregate time consumed by all tasks in the container")
@Timespan
public long cpuTime;
@Label("CPU User Time")
@Description("Aggregate user time consumed by all tasks in the container")
@Timespan
public long cpuUserTime;
@Label("CPU System Time")
@Description("Aggregate system time consumed by all tasks in the container")
@Timespan
public long cpuSystemTime;
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, DataDog. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr.events;
import jdk.jfr.Category;
import jdk.jfr.DataAmount;
import jdk.jfr.Description;
import jdk.jfr.Enabled;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.Period;
import jdk.jfr.StackTrace;
import jdk.jfr.Threshold;
import jdk.jfr.Timespan;
import jdk.jfr.internal.Type;
@Name(Type.EVENT_NAME_PREFIX + "ContainerConfiguration")
@Label("Container Configuration")
@Category({"Operating System"})
@Description("A set of container specific attributes")
public final class ContainerConfigurationEvent extends AbstractJDKEvent {
@Label("Container Type")
@Description("Container type information")
public String containerType;
@Label("CPU Slice Period")
@Description("Length of the scheduling period for processes within the container")
@Timespan(Timespan.MICROSECONDS)
public long cpuSlicePeriod;
@Label("CPU Quota")
@Description("Total available run-time allowed during each scheduling period for all tasks in the container")
@Timespan(Timespan.MICROSECONDS)
public long cpuQuota;
@Label("CPU Shares")
@Description("Relative weighting of processes with the container used for prioritizing the scheduling of processes across " +
"all containers running on a host")
public long cpuShares;
@Label("Effective CPU Count")
@Description("Number of effective processors that this container has available to it")
public long effectiveCpuCount;
@Label("Memory Soft Limit")
@Description("Hint to the operating system that allows groups to specify the minimum required amount of physical memory")
@DataAmount
public long memorySoftLimit;
@Label("Memory Limit")
@Description("Maximum amount of physical memory that can be allocated in the container")
@DataAmount
public long memoryLimit;
@Label("Memory and Swap Limit")
@Description("Maximum amount of physical memory and swap space, in bytes, that can be allocated in the container")
@DataAmount
public long swapMemoryLimit;
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, DataDog. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr.events;
import jdk.jfr.Category;
import jdk.jfr.DataAmount;
import jdk.jfr.Description;
import jdk.jfr.Enabled;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.Period;
import jdk.jfr.StackTrace;
import jdk.jfr.Threshold;
import jdk.jfr.Timespan;
import jdk.jfr.internal.Type;
@Name(Type.EVENT_NAME_PREFIX + "ContainerIOUsage")
@Label("Container IO Usage")
@Category({"Operating System", "File System"})
@Description("Container IO usage related information")
public class ContainerIOUsageEvent extends AbstractJDKEvent {
@Label("Block IO Request Count")
@Description("Number of block IO requests to the disk that have been issued by the container")
public long serviceRequests;
@Label("Block IO Transfer")
@Description("Number of block IO bytes that have been transferred to/from the disk by the container")
@DataAmount
public long dataTransferred;
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, DataDog. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.jfr.events;
import jdk.jfr.Category;
import jdk.jfr.DataAmount;
import jdk.jfr.Description;
import jdk.jfr.Enabled;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.Period;
import jdk.jfr.StackTrace;
import jdk.jfr.Threshold;
import jdk.jfr.Timespan;
import jdk.jfr.internal.Type;
@Name(Type.EVENT_NAME_PREFIX + "ContainerMemoryUsage")
@Label("Container Memory Usage")
@Category({"Operating System", "Memory"})
@Description("Container memory usage related information")
public final class ContainerMemoryUsageEvent extends AbstractJDKEvent {
@Label("Memory Fail Count")
@Description("Number of times that user memory requests in the container have exceeded the memory limit")
public long memoryFailCount;
@Label("Memory Usage")
@Description("Amount of physical memory, in bytes, that is currently allocated in the current container")
@DataAmount
public long memoryUsage;
@Label("Memory and Swap Usage")
@Description("Amount of physical memory and swap space, in bytes, that is currently allocated in the current container")
@DataAmount
public long swapMemoryUsage;
}

View File

@ -56,6 +56,7 @@ import java.util.Objects;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
import jdk.internal.platform.Metrics;
import jdk.jfr.Event;
import jdk.jfr.FlightRecorderPermission;
import jdk.jfr.Recording;
@ -90,6 +91,11 @@ public final class Utils {
private static final int BASE = 10;
private static long THROTTLE_OFF = -2;
/*
* This field will be lazily initialized and the access is not synchronized.
* The possible data race is benign and is worth of not introducing any contention here.
*/
private static Metrics[] metrics;
public static void checkAccessFlightRecorder() throws SecurityException {
SecurityManager sm = System.getSecurityManager();
@ -720,6 +726,20 @@ public final class Utils {
}
}
public static boolean shouldSkipBytecode(String eventName, Class<?> superClass) {
if (superClass.getClassLoader() != null || !superClass.getName().equals("jdk.jfr.events.AbstractJDKEvent")) {
return false;
}
return eventName.startsWith("jdk.Container") && getMetrics() == null;
}
private static Metrics getMetrics() {
if (metrics == null) {
metrics = new Metrics[]{Metrics.systemMetrics()};
}
return metrics[0];
}
private static String formatPositiveDuration(Duration d){
if (d.compareTo(MICRO_SECOND) < 0) {
// 0.000001 ms - 0.000999 ms

View File

@ -27,10 +27,16 @@ package jdk.jfr.internal.instrument;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import jdk.jfr.Event;
import jdk.jfr.events.ActiveRecordingEvent;
import jdk.jfr.events.ActiveSettingEvent;
import jdk.jfr.events.ContainerIOUsageEvent;
import jdk.jfr.events.ContainerConfigurationEvent;
import jdk.jfr.events.ContainerCPUUsageEvent;
import jdk.jfr.events.ContainerCPUThrottlingEvent;
import jdk.jfr.events.ContainerMemoryUsageEvent;
import jdk.jfr.events.DirectBufferStatisticsEvent;
import jdk.jfr.events.ErrorThrownEvent;
import jdk.jfr.events.ExceptionStatisticsEvent;
@ -53,8 +59,10 @@ import jdk.jfr.internal.Logger;
import jdk.jfr.internal.RequestEngine;
import jdk.jfr.internal.SecuritySupport;
public final class JDKEvents {
import jdk.internal.platform.Container;
import jdk.internal.platform.Metrics;
public final class JDKEvents {
private static final Class<?>[] mirrorEventClasses = {
DeserializationEvent.class,
ProcessStartEvent.class,
@ -100,6 +108,12 @@ public final class JDKEvents {
private static final JVM jvm = JVM.getJVM();
private static final Runnable emitExceptionStatistics = JDKEvents::emitExceptionStatistics;
private static final Runnable emitDirectBufferStatistics = JDKEvents::emitDirectBufferStatistics;
private static final Runnable emitContainerConfiguration = JDKEvents::emitContainerConfiguration;
private static final Runnable emitContainerCPUUsage = JDKEvents::emitContainerCPUUsage;
private static final Runnable emitContainerCPUThrottling = JDKEvents::emitContainerCPUThrottling;
private static final Runnable emitContainerMemoryUsage = JDKEvents::emitContainerMemoryUsage;
private static final Runnable emitContainerIOUsage = JDKEvents::emitContainerIOUsage;
private static Metrics containerMetrics = null;
private static boolean initializationTriggered;
@SuppressWarnings("unchecked")
@ -112,9 +126,12 @@ public final class JDKEvents {
for (Class<?> eventClass : eventClasses) {
SecuritySupport.registerEvent((Class<? extends Event>) eventClass);
}
initializationTriggered = true;
RequestEngine.addTrustedJDKHook(ExceptionStatisticsEvent.class, emitExceptionStatistics);
RequestEngine.addTrustedJDKHook(DirectBufferStatisticsEvent.class, emitDirectBufferStatistics);
initializeContainerEvents();
initializationTriggered = true;
}
} catch (Exception e) {
Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Could not initialize JDK events. " + e.getMessage());
@ -141,12 +158,84 @@ public final class JDKEvents {
}
}
private static void initializeContainerEvents() {
containerMetrics = Container.metrics();
SecuritySupport.registerEvent(ContainerConfigurationEvent.class);
SecuritySupport.registerEvent(ContainerCPUUsageEvent.class);
SecuritySupport.registerEvent(ContainerCPUThrottlingEvent.class);
SecuritySupport.registerEvent(ContainerMemoryUsageEvent.class);
SecuritySupport.registerEvent(ContainerIOUsageEvent.class);
RequestEngine.addTrustedJDKHook(ContainerConfigurationEvent.class, emitContainerConfiguration);
RequestEngine.addTrustedJDKHook(ContainerCPUUsageEvent.class, emitContainerCPUUsage);
RequestEngine.addTrustedJDKHook(ContainerCPUThrottlingEvent.class, emitContainerCPUThrottling);
RequestEngine.addTrustedJDKHook(ContainerMemoryUsageEvent.class, emitContainerMemoryUsage);
RequestEngine.addTrustedJDKHook(ContainerIOUsageEvent.class, emitContainerIOUsage);
}
private static void emitExceptionStatistics() {
ExceptionStatisticsEvent t = new ExceptionStatisticsEvent();
t.throwables = ThrowableTracer.numThrowables();
t.commit();
}
private static void emitContainerConfiguration() {
if (containerMetrics != null) {
ContainerConfigurationEvent t = new ContainerConfigurationEvent();
t.containerType = containerMetrics.getProvider();
t.cpuSlicePeriod = containerMetrics.getCpuPeriod();
t.cpuQuota = containerMetrics.getCpuQuota();
t.cpuShares = containerMetrics.getCpuShares();
t.effectiveCpuCount = containerMetrics.getEffectiveCpuCount();
t.memorySoftLimit = containerMetrics.getMemorySoftLimit();
t.memoryLimit = containerMetrics.getMemoryLimit();
t.swapMemoryLimit = containerMetrics.getMemoryAndSwapLimit();
t.commit();
}
}
private static void emitContainerCPUUsage() {
if (containerMetrics != null) {
ContainerCPUUsageEvent event = new ContainerCPUUsageEvent();
event.cpuTime = containerMetrics.getCpuUsage();
event.cpuSystemTime = containerMetrics.getCpuSystemUsage();
event.cpuUserTime = containerMetrics.getCpuUserUsage();
event.commit();
}
}
private static void emitContainerMemoryUsage() {
if (containerMetrics != null) {
ContainerMemoryUsageEvent event = new ContainerMemoryUsageEvent();
event.memoryFailCount = containerMetrics.getMemoryFailCount();
event.memoryUsage = containerMetrics.getMemoryUsage();
event.swapMemoryUsage = containerMetrics.getMemoryAndSwapUsage();
event.commit();
}
}
private static void emitContainerIOUsage() {
if (containerMetrics != null) {
ContainerIOUsageEvent event = new ContainerIOUsageEvent();
event.serviceRequests = containerMetrics.getBlkIOServiceCount();
event.dataTransferred = containerMetrics.getBlkIOServiced();
event.commit();
}
}
private static void emitContainerCPUThrottling() {
if (containerMetrics != null) {
ContainerCPUThrottlingEvent event = new ContainerCPUThrottlingEvent();
event.cpuElapsedSlices = containerMetrics.getCpuNumPeriods();
event.cpuThrottledSlices = containerMetrics.getCpuNumThrottled();
event.cpuThrottledTime = containerMetrics.getCpuThrottledTime();
event.commit();
}
}
@SuppressWarnings("deprecation")
public static byte[] retransformCallback(Class<?> klass, byte[] oldBytes) throws Throwable {
if (java.lang.Throwable.class == klass) {
@ -172,8 +261,14 @@ public final class JDKEvents {
}
public static void remove() {
RequestEngine.removeHook(JDKEvents::emitExceptionStatistics);
RequestEngine.removeHook(emitExceptionStatistics);
RequestEngine.removeHook(emitDirectBufferStatistics);
RequestEngine.removeHook(emitContainerConfiguration);
RequestEngine.removeHook(emitContainerCPUUsage);
RequestEngine.removeHook(emitContainerCPUThrottling);
RequestEngine.removeHook(emitContainerMemoryUsage);
RequestEngine.removeHook(emitContainerIOUsage);
}
private static void emitDirectBufferStatistics() {

View File

@ -554,6 +554,31 @@
<setting name="period">beginChunk</setting>
</event>
<event name="jdk.ContainerConfiguration">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>
<event name="jdk.ContainerCPUUsage">
<setting name="enabled">true</setting>
<setting name="period">30 s</setting>
</event>
<event name="jdk.ContainerCPUThrottling">
<setting name="enabled">true</setting>
<setting name="period">30 s</setting>
</event>
<event name="jdk.ContainerMemoryUsage">
<setting name="enabled">true</setting>
<setting name="period">30 s</setting>
</event>
<event name="jdk.ContainerIOUsage">
<setting name="enabled">true</setting>
<setting name="period">30 s</setting>
</event>
<event name="jdk.CPUInformation">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>

View File

@ -554,6 +554,31 @@
<setting name="period">beginChunk</setting>
</event>
<event name="jdk.ContainerConfiguration">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>
</event>
<event name="jdk.ContainerCPUUsage">
<setting name="enabled">true</setting>
<setting name="period">30 s</setting>
</event>
<event name="jdk.ContainerCPUThrottling">
<setting name="enabled">true</setting>
<setting name="period">30 s</setting>
</event>
<event name="jdk.ContainerMemoryUsage">
<setting name="enabled">true</setting>
<setting name="period">30 s</setting>
</event>
<event name="jdk.ContainerIOUsage">
<setting name="enabled">true</setting>
<setting name="period">30 s</setting>
</event>
<event name="jdk.CPUInformation">
<setting name="enabled">true</setting>
<setting name="period">beginChunk</setting>

View File

@ -25,6 +25,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import jdk.jfr.Recording;
import jdk.jfr.EventSettings;
import jdk.jfr.ValueDescriptor;
import jdk.jfr.consumer.RecordedEvent;
import jdk.jfr.consumer.RecordingFile;
@ -34,7 +35,11 @@ public class JfrReporter {
public static void main(String[] args) throws Exception {
String eventName = args[0];
try(Recording r = new Recording()) {
r.enable(eventName);
EventSettings es = r.enable(eventName);
for (int i = 1; i < args.length; i++) {
String[] kv = args[i].split("=");
es = es.with(kv[0], kv[1]);
}
r.start();
r.stop();
Path p = Paths.get("/", "tmp", eventName + ".jfr");

View File

@ -70,31 +70,114 @@ public class TestJFREvents {
testProcessInfo();
testEnvironmentVariables();
containerInfoTestCase();
testCpuUsage();
testCpuThrottling();
testMemoryUsage();
testIOUsage();
} finally {
DockerTestUtils.removeDockerImage(imageName);
}
}
// This test case is currently not in use.
// Once new Container events are available, this test case can be used to test
// processor-related configuration such as active processor count (see JDK-8203359).
private static void cpuTestCase() throws Exception {
private static void containerInfoTestCase() throws Exception {
// leave one CPU for system and tools, otherwise this test may be unstable
int maxNrOfAvailableCpus = availableCPUs - 1;
for (int i=1; i < maxNrOfAvailableCpus; i = i * 2) {
testCPUInfo("jdk.ContainerConfiguration", i, i);
for (int j=64; j <= 256; j *= 2) {
testContainerInfo(i, j);
}
}
}
private static void testCPUInfo(String eventName, int valueToSet, int expectedValue) throws Exception {
Common.logNewTestCase("CPUInfo: --cpus = " + valueToSet);
String fieldName = "activeProcessorCount";
private static void testContainerInfo(int expectedCPUs, int expectedMemoryMB) throws Exception {
Common.logNewTestCase("ContainerInfo: --cpus = " + expectedCPUs + " --memory=" + expectedMemoryMB + "m");
String eventName = "jdk.ContainerConfiguration";
long expectedSlicePeriod = 100000; // default slice period
long expectedMemoryLimit = expectedMemoryMB * 1024 * 1024;
String cpuCountFld = "effectiveCpuCount";
String cpuQuotaFld = "cpuQuota";
String cpuSlicePeriodFld = "cpuSlicePeriod";
String memoryLimitFld = "memoryLimit";
DockerTestUtils.dockerRunJava(
commonDockerOpts()
.addDockerOpts("--cpus=" + valueToSet)
.addDockerOpts("--cpus=" + expectedCPUs)
.addDockerOpts("--memory=" + expectedMemoryMB + "m")
.addClassOptions(eventName))
.shouldHaveExitValue(0)
.shouldContain(fieldName + " = " + expectedValue);
.shouldContain(cpuCountFld + " = " + expectedCPUs)
.shouldContain(cpuSlicePeriodFld + " = " + expectedSlicePeriod)
.shouldContain(cpuQuotaFld + " = " + expectedCPUs * expectedSlicePeriod)
.shouldContain(memoryLimitFld + " = " + expectedMemoryLimit);
}
private static void testCpuUsage() throws Exception {
Common.logNewTestCase("CPU Usage");
String eventName = "jdk.ContainerCPUUsage";
String cpuTimeFld = "cpuTime";
String cpuUserTimeFld = "cpuUserTime";
String cpuSystemTimeFld = "cpuSystemTime";
DockerTestUtils.dockerRunJava(
commonDockerOpts()
.addClassOptions(eventName, "period=endChunk"))
.shouldHaveExitValue(0)
.shouldNotContain(cpuTimeFld + " = " + 0)
.shouldNotContain(cpuUserTimeFld + " = " + 0)
.shouldNotContain(cpuSystemTimeFld + " = " + 0);
}
private static void testMemoryUsage() throws Exception {
Common.logNewTestCase("Memory Usage");
String eventName = "jdk.ContainerMemoryUsage";
String memoryFailCountFld = "memoryFailCount";
String memoryUsageFld = "memoryUsage";
String swapMemoryUsageFld = "swapMemoryUsage";
DockerTestUtils.dockerRunJava(
commonDockerOpts()
.addClassOptions(eventName, "period=endChunk"))
.shouldHaveExitValue(0)
.shouldContain(memoryFailCountFld)
.shouldContain(memoryUsageFld)
.shouldContain(swapMemoryUsageFld);
}
private static void testIOUsage() throws Exception {
Common.logNewTestCase("I/O Usage");
String eventName = "jdk.ContainerIOUsage";
String serviceRequestsFld = "serviceRequests";
String dataTransferredFld = "dataTransferred";
DockerTestUtils.dockerRunJava(
commonDockerOpts()
.addClassOptions(eventName, "period=endChunk"))
.shouldHaveExitValue(0)
.shouldContain(serviceRequestsFld)
.shouldContain(dataTransferredFld);
}
private static void testCpuThrottling() throws Exception {
Common.logNewTestCase("CPU Throttling");
String eventName = "jdk.ContainerCPUThrottling";
String cpuElapsedSlicesFld = "cpuElapsedSlices";
String cpuThrottledSlicesFld = "cpuThrottledSlices";
String cpuThrottledTimeFld = "cpuThrottledTime";
DockerTestUtils.dockerRunJava(
commonDockerOpts()
.addClassOptions(eventName, "period=endChunk"))
.shouldHaveExitValue(0)
.shouldContain(cpuElapsedSlicesFld)
.shouldContain(cpuThrottledSlicesFld)
.shouldContain(cpuThrottledTimeFld);
}
@ -118,7 +201,6 @@ public class TestJFREvents {
.shouldContain("pid = 1");
}
private static DockerRunOptions commonDockerOpts() {
return new DockerRunOptions(imageName, "/jdk/bin/java", "JfrReporter")
.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/")

View File

@ -71,6 +71,13 @@ public class TestLookForUntestedEvents {
"GCPhasePauseLevel4")
);
// Container events are tested in hotspot/jtreg/containers/docker/TestJFREvents.java
private static final Set<String> coveredContainerEvents = new HashSet<>(
Arrays.asList(
"ContainerConfiguration", "ContainerCPUUsage", "ContainerCPUThrottling",
"ContainerMemoryUsage", "ContainerIOUsage")
);
// This is a "known failure list" for this test.
// NOTE: if the event is not covered, a bug should be open, and bug number
// noted in the comments for this set.
@ -115,6 +122,7 @@ public class TestLookForUntestedEvents {
// Account for hard-to-test, experimental and GC tested events
eventsNotCoveredByTest.removeAll(hardToTestEvents);
eventsNotCoveredByTest.removeAll(coveredGcEvents);
eventsNotCoveredByTest.removeAll(coveredContainerEvents);
eventsNotCoveredByTest.removeAll(knownNotCoveredEvents);
if (!eventsNotCoveredByTest.isEmpty()) {

View File

@ -201,6 +201,12 @@ public class EventNames {
public final static String DirectBufferStatistics = PREFIX + "DirectBufferStatistics";
public final static String Deserialization = PREFIX + "Deserialization";
// Containers
public static final String ContainerConfiguration = PREFIX + "ContainerConfiguration";
public static final String ContainerCPUUsage = PREFIX + "ContainerCPUUsage";
public static final String ContainerCPUThrottling = PREFIX + "ContainerCPUThrottling";
public static final String ContainerMemoryUsage = PREFIX + "ContainerMemoryUsage";
public static final String ContainerIOUsage = PREFIX + "ContainerIOUsage";
// Flight Recorder
public final static String DumpReason = PREFIX + "DumpReason";