From ae99eed923e0cd5ebb255099ddc2f608920df956 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Thu, 21 Jun 2018 10:13:23 +0200 Subject: [PATCH 1/6] Add thread state metrics Signed-off-by: Christian Stein --- .../client/hotspot/ThreadExports.java | 34 +++++++++++++++++-- .../client/hotspot/ThreadExportsTest.java | 3 ++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java index 12ebccad0..194b009c3 100644 --- a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java +++ b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java @@ -5,9 +5,9 @@ import io.prometheus.client.GaugeMetricFamily; import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /** * Exports metrics about JVM thread areas. @@ -73,8 +73,38 @@ void addThreadMetrics(List sampleFamilies) { "jvm_threads_deadlocked_monitor", "Cycles of JVM-threads that are in deadlock waiting to acquire object monitors", nullSafeArrayLength(threadBean.findMonitorDeadlockedThreads()))); + + Map threadStateCounts = getThreadStateCountMap(); + for (Map.Entry entry : threadStateCounts.entrySet()) { + String stateName = entry.getKey().toString().toLowerCase(); + sampleFamilies.add( + new GaugeMetricFamily( + String.format("jvm_threads_%s", stateName), + String.format("Current count of threads in state '%s'", stateName), + entry.getValue().doubleValue())); + } } + private Map getThreadStateCountMap() { + ThreadInfo[] allThreads = threadBean.getThreadInfo(threadBean.getAllThreadIds(), StackTraceDepth); + HashMap threadCounts = new HashMap(); + + for (ThreadInfo curThread : allThreads) { + if (curThread != null) { + Thread.State threadState = curThread.getThreadState(); + if (threadCounts.containsKey(threadState)) { + threadCounts.put(threadState, threadCounts.get(threadState) + 1); + } else { + threadCounts.put(threadState, 1); + } + } + } + + return threadCounts; + } + + private static int StackTraceDepth = 0; // Don't compute any stack traces + private static double nullSafeArrayLength(long[] array) { return null == array ? 0 : array.length; } diff --git a/simpleclient_hotspot/src/test/java/io/prometheus/client/hotspot/ThreadExportsTest.java b/simpleclient_hotspot/src/test/java/io/prometheus/client/hotspot/ThreadExportsTest.java index 78c9951db..47397c12b 100644 --- a/simpleclient_hotspot/src/test/java/io/prometheus/client/hotspot/ThreadExportsTest.java +++ b/simpleclient_hotspot/src/test/java/io/prometheus/client/hotspot/ThreadExportsTest.java @@ -5,6 +5,7 @@ import org.junit.Test; import org.mockito.Mockito; +import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import static org.junit.Assert.assertEquals; @@ -26,6 +27,8 @@ public void setUp() { when(mockThreadsBean.getTotalStartedThreadCount()).thenReturn(503L); when(mockThreadsBean.findDeadlockedThreads()).thenReturn(new long[]{1L,2L,3L}); when(mockThreadsBean.findMonitorDeadlockedThreads()).thenReturn(new long[]{2L,3L,4L}); + when(mockThreadsBean.getAllThreadIds()).thenReturn(new long[]{3L,4L,5L}); + when(mockThreadsBean.getThreadInfo(new long[]{3L,4L,5L}, 0)).thenReturn(new ThreadInfo[] {}); collectorUnderTest = new ThreadExports(mockThreadsBean).register(registry); } From 46052261f9d2c1e07ea80cb26d1363d3567db548 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Thu, 21 Jun 2018 10:48:42 +0200 Subject: [PATCH 2/6] Made imports explicit Signed-off-by: Christian Stein --- .../java/io/prometheus/client/hotspot/ThreadExports.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java index 194b009c3..cb71d67cc 100644 --- a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java +++ b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java @@ -7,7 +7,10 @@ import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Exports metrics about JVM thread areas. From a6b110409adba303af5d4b49495e810f150f78b0 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Thu, 21 Jun 2018 11:01:16 +0200 Subject: [PATCH 3/6] Monitor all thread states Signed-off-by: Christian Stein --- .../client/hotspot/ThreadExports.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java index cb71d67cc..efe77e970 100644 --- a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java +++ b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java @@ -7,10 +7,7 @@ import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Exports metrics about JVM thread areas. @@ -77,14 +74,18 @@ void addThreadMetrics(List sampleFamilies) { "Cycles of JVM-threads that are in deadlock waiting to acquire object monitors", nullSafeArrayLength(threadBean.findMonitorDeadlockedThreads()))); + GaugeMetricFamily threadStateFamily = new GaugeMetricFamily( + "jvm_threads_state", + "Current count of threads by state", + Collections.singletonList("state")); + Map threadStateCounts = getThreadStateCountMap(); - for (Map.Entry entry : threadStateCounts.entrySet()) { - String stateName = entry.getKey().toString().toLowerCase(); - sampleFamilies.add( - new GaugeMetricFamily( - String.format("jvm_threads_%s", stateName), - String.format("Current count of threads in state '%s'", stateName), - entry.getValue().doubleValue())); + for (Thread.State state : Thread.State.values()) { + String stateName = state.toString().toLowerCase(); + threadStateFamily.addMetric( + Collections.singletonList(stateName), + (threadStateCounts.containsKey(stateName)) ? threadStateCounts.get(stateName) : 0.0d + ); } } From 7f0e875884088f8c79cc7841c607dbbd045233af Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Thu, 21 Jun 2018 11:03:50 +0200 Subject: [PATCH 4/6] Made imports explicit Signed-off-by: Christian Stein --- .../java/io/prometheus/client/hotspot/ThreadExports.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java index efe77e970..2e7abdae7 100644 --- a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java +++ b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java @@ -7,7 +7,11 @@ import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Exports metrics about JVM thread areas. From ca1bfdccf797a8aa33e1aec2e1e11c17120ae7db Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Thu, 21 Jun 2018 11:20:26 +0200 Subject: [PATCH 5/6] Simplify code Signed-off-by: Christian Stein --- .../client/hotspot/ThreadExports.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java index 2e7abdae7..db4a0aca3 100644 --- a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java +++ b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java @@ -84,27 +84,28 @@ void addThreadMetrics(List sampleFamilies) { Collections.singletonList("state")); Map threadStateCounts = getThreadStateCountMap(); - for (Thread.State state : Thread.State.values()) { - String stateName = state.toString().toLowerCase(); + for (Map.Entry entry : threadStateCounts.entrySet()) { threadStateFamily.addMetric( - Collections.singletonList(stateName), - (threadStateCounts.containsKey(stateName)) ? threadStateCounts.get(stateName) : 0.0d + Collections.singletonList(entry.getKey().toString()), + entry.getValue() ); } } private Map getThreadStateCountMap() { ThreadInfo[] allThreads = threadBean.getThreadInfo(threadBean.getAllThreadIds(), StackTraceDepth); + + // Initialize the map with all thread states HashMap threadCounts = new HashMap(); + for (Thread.State state : Thread.State.values()) { + threadCounts.put(state, 0); + } + // Collect the actual thread counts for (ThreadInfo curThread : allThreads) { if (curThread != null) { Thread.State threadState = curThread.getThreadState(); - if (threadCounts.containsKey(threadState)) { - threadCounts.put(threadState, threadCounts.get(threadState) + 1); - } else { - threadCounts.put(threadState, 1); - } + threadCounts.put(threadState, threadCounts.get(threadState) + 1); } } From f631b8108c0a0084cf3403c430944c1132444518 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Thu, 21 Jun 2018 11:27:59 +0200 Subject: [PATCH 6/6] Use stack depth counter directly Signed-off-by: Christian Stein --- .../java/io/prometheus/client/hotspot/ThreadExports.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java index db4a0aca3..2128310b8 100644 --- a/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java +++ b/simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java @@ -93,7 +93,8 @@ void addThreadMetrics(List sampleFamilies) { } private Map getThreadStateCountMap() { - ThreadInfo[] allThreads = threadBean.getThreadInfo(threadBean.getAllThreadIds(), StackTraceDepth); + // Get thread information without computing any stack traces + ThreadInfo[] allThreads = threadBean.getThreadInfo(threadBean.getAllThreadIds(), 0); // Initialize the map with all thread states HashMap threadCounts = new HashMap(); @@ -112,8 +113,6 @@ private Map getThreadStateCountMap() { return threadCounts; } - private static int StackTraceDepth = 0; // Don't compute any stack traces - private static double nullSafeArrayLength(long[] array) { return null == array ? 0 : array.length; }