From d8bb9a8fcffcc7380fd01af80cec28ce291308cf Mon Sep 17 00:00:00 2001 From: Danny Thomas Date: Wed, 4 Sep 2024 12:51:05 +1000 Subject: [PATCH] Remove internal Hotspot metrics (#1156) They're less of a concern for us now we're on ZGC, and most of the critical work happens in thread local handshakes, not safepoints, and JNI critical/GCLocker is less of a concern. --------- Co-authored-by: brharrington --- .../netflix/spectator/jvm/HotspotRuntime.java | 111 ------------------ .../java/com/netflix/spectator/jvm/Jmx.java | 29 ----- .../spectator/jvm/HotspotRuntimeTest.java | 49 -------- 3 files changed, 189 deletions(-) delete mode 100644 spectator-ext-jvm/src/main/java/com/netflix/spectator/jvm/HotspotRuntime.java delete mode 100644 spectator-ext-jvm/src/test/java/com/netflix/spectator/jvm/HotspotRuntimeTest.java diff --git a/spectator-ext-jvm/src/main/java/com/netflix/spectator/jvm/HotspotRuntime.java b/spectator-ext-jvm/src/main/java/com/netflix/spectator/jvm/HotspotRuntime.java deleted file mode 100644 index 8dd5852b5..000000000 --- a/spectator-ext-jvm/src/main/java/com/netflix/spectator/jvm/HotspotRuntime.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2014-2022 Netflix, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.netflix.spectator.jvm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Method; - -/** - * Helper for accessing the HotspotRuntimeMBean in order to get information about the amount - * of time spent in safepoints. - */ -final class HotspotRuntime { - - private static final Logger LOGGER = LoggerFactory.getLogger(HotspotRuntime.class); - - private HotspotRuntime() { - } - - private static Class runtimeMBeanType; - private static Object runtimeMBean; - - private static Method safepointCount; - private static Method safepointTime; - private static Method safepointSyncTime; - - static { - try { - // The implementation class, sun.management.HotspotRuntime, is package private and - // thus the methods cannot be accessed without setAccessible(true). Use the interface - // type for getting the method handles so all reflective access is via public classes and - // methods. That allows this approach will work with either: - // - // --add-exports java.management/sun.management=ALL-UNNAMED OR - // --add-opens java.management/sun.management=ALL-UNNAMED - runtimeMBeanType = Class.forName("sun.management.HotspotRuntimeMBean"); - runtimeMBean = Class.forName("sun.management.ManagementFactoryHelper") - .getMethod("getHotspotRuntimeMBean") - .invoke(null); - - safepointCount = getMethod("getSafepointCount"); - safepointTime = getMethod("getTotalSafepointTime"); - safepointSyncTime = getMethod("getSafepointSyncTime"); - } catch (Exception e) { - // Not Hotspot or IllegalAccessError from JDK 16+ due sun.management package being inaccessible - LOGGER.debug("unable to access HotspotRuntimeMBean", e); - runtimeMBean = null; - } - } - - /** Get method and double check that we have permissions to invoke it. */ - private static Method getMethod(String name) throws Exception { - Method method = runtimeMBeanType.getMethod(name); - method.invoke(runtimeMBean); // ignore result, just checking access - return method; - } - - private static long getValue(Method method) { - if (runtimeMBean == null) { - throw new UnsupportedOperationException("HotspotRuntime is not supported"); - } - - try { - return (Long) method.invoke(runtimeMBean); - } catch (Exception e) { - throw new IllegalStateException("failed to invoke " + method, e); - } - } - - /** Returns the HotspotRuntimeMBean instance. */ - static Object getRuntimeMBean() { - return runtimeMBean; - } - - /** Returns true if the safepoint checks are supported. */ - static boolean isSupported() { - return runtimeMBean != null; - } - - /** Total number of safepoints since the JVM was started. */ - static long getSafepointCount() { - return getValue(safepointCount); - } - - /** Total time in milliseconds spent in safepoints since the JVM was started. */ - static long getSafepointTime() { - return getValue(safepointTime); - } - - /** - * Total time in milliseconds spent synchronizing in order to get to safepoints since the - * JVM was started. - */ - static long getSafepointSyncTime() { - return getValue(safepointSyncTime); - } -} diff --git a/spectator-ext-jvm/src/main/java/com/netflix/spectator/jvm/Jmx.java b/spectator-ext-jvm/src/main/java/com/netflix/spectator/jvm/Jmx.java index 6e11fa99b..bb0dbc02b 100644 --- a/spectator-ext-jvm/src/main/java/com/netflix/spectator/jvm/Jmx.java +++ b/spectator-ext-jvm/src/main/java/com/netflix/spectator/jvm/Jmx.java @@ -17,7 +17,6 @@ import com.netflix.spectator.api.Gauge; import com.netflix.spectator.api.Registry; -import com.netflix.spectator.api.Statistic; import com.netflix.spectator.api.patterns.PolledMeter; import com.typesafe.config.Config; @@ -57,7 +56,6 @@ public static void registerStandardMXBeans(Registry registry) { monitorThreadMXBean(registry); monitorCompilationMXBean(registry); } - maybeRegisterHotspotInternal(registry); for (MemoryPoolMXBean mbean : ManagementFactory.getMemoryPoolMXBeans()) { registry.register(new MemoryPoolMeter(registry, mbean)); @@ -103,33 +101,6 @@ private static void monitorCompilationMXBean(Registry registry) { } } - private static void maybeRegisterHotspotInternal(Registry registry) { - if (HotspotRuntime.isSupported()) { - // The safepointCount is reported as the count for both the safepointTime and - // safepointSyncTime. This should allow the metrics to work as normal timers and - // for the user to compute the average time spent per operation. - Object mbean = HotspotRuntime.getRuntimeMBean(); - - PolledMeter.using(registry) - .withName("jvm.hotspot.safepointTime") - .withTag(Statistic.count) - .monitorMonotonicCounter(mbean, b -> HotspotRuntime.getSafepointCount()); - PolledMeter.using(registry) - .withName("jvm.hotspot.safepointTime") - .withTag(Statistic.totalTime) - .monitorMonotonicCounterDouble(mbean, b -> HotspotRuntime.getSafepointTime() / 1000.0); - - PolledMeter.using(registry) - .withName("jvm.hotspot.safepointSyncTime") - .withTag(Statistic.count) - .monitorMonotonicCounter(mbean, b -> HotspotRuntime.getSafepointCount()); - PolledMeter.using(registry) - .withName("jvm.hotspot.safepointSyncTime") - .withTag(Statistic.totalTime) - .monitorMonotonicCounterDouble(mbean, b -> HotspotRuntime.getSafepointSyncTime() / 1000.0); - } - } - /** * Add meters based on configured JMX queries. See the {@link JmxConfig} class for more * details. diff --git a/spectator-ext-jvm/src/test/java/com/netflix/spectator/jvm/HotspotRuntimeTest.java b/spectator-ext-jvm/src/test/java/com/netflix/spectator/jvm/HotspotRuntimeTest.java deleted file mode 100644 index 28c72d87e..000000000 --- a/spectator-ext-jvm/src/test/java/com/netflix/spectator/jvm/HotspotRuntimeTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2014-2022 Netflix, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.netflix.spectator.jvm; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Assumptions; -import org.junit.jupiter.api.Test; - -public class HotspotRuntimeTest { - - private void triggerSafepoint() { - // May not always work, but seems to work for the tests... - System.gc(); - } - - @Test - public void safepointCount() { - Assumptions.assumeTrue(HotspotRuntime.isSupported()); - long before = HotspotRuntime.getSafepointCount(); - triggerSafepoint(); - long after = HotspotRuntime.getSafepointCount(); - Assertions.assertTrue(after > before); - } - - @Test - public void safepointTime() { - Assumptions.assumeTrue(HotspotRuntime.isSupported()); - HotspotRuntime.getSafepointTime(); - } - - @Test - public void safepointSyncTime() { - Assumptions.assumeTrue(HotspotRuntime.isSupported()); - HotspotRuntime.getSafepointSyncTime(); - } -}