Skip to content

Commit 1140823

Browse files
Christian Steinbrian-brazil
authored andcommitted
Extend JVM metrics with thread states (#391)
Signed-off-by: Christian Stein <[email protected]>
1 parent 16e5be3 commit 1140823

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

simpleclient_hotspot/src/main/java/io/prometheus/client/hotspot/ThreadExports.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
import io.prometheus.client.GaugeMetricFamily;
66

77
import java.lang.management.ManagementFactory;
8+
import java.lang.management.ThreadInfo;
89
import java.lang.management.ThreadMXBean;
910
import java.util.ArrayList;
11+
import java.util.Collections;
12+
import java.util.HashMap;
1013
import java.util.List;
14+
import java.util.Map;
1115

1216
/**
1317
* Exports metrics about JVM thread areas.
@@ -73,6 +77,40 @@ void addThreadMetrics(List<MetricFamilySamples> sampleFamilies) {
7377
"jvm_threads_deadlocked_monitor",
7478
"Cycles of JVM-threads that are in deadlock waiting to acquire object monitors",
7579
nullSafeArrayLength(threadBean.findMonitorDeadlockedThreads())));
80+
81+
GaugeMetricFamily threadStateFamily = new GaugeMetricFamily(
82+
"jvm_threads_state",
83+
"Current count of threads by state",
84+
Collections.singletonList("state"));
85+
86+
Map<Thread.State, Integer> threadStateCounts = getThreadStateCountMap();
87+
for (Map.Entry<Thread.State, Integer> entry : threadStateCounts.entrySet()) {
88+
threadStateFamily.addMetric(
89+
Collections.singletonList(entry.getKey().toString()),
90+
entry.getValue()
91+
);
92+
}
93+
}
94+
95+
private Map<Thread.State, Integer> getThreadStateCountMap() {
96+
// Get thread information without computing any stack traces
97+
ThreadInfo[] allThreads = threadBean.getThreadInfo(threadBean.getAllThreadIds(), 0);
98+
99+
// Initialize the map with all thread states
100+
HashMap<Thread.State, Integer> threadCounts = new HashMap<Thread.State, Integer>();
101+
for (Thread.State state : Thread.State.values()) {
102+
threadCounts.put(state, 0);
103+
}
104+
105+
// Collect the actual thread counts
106+
for (ThreadInfo curThread : allThreads) {
107+
if (curThread != null) {
108+
Thread.State threadState = curThread.getThreadState();
109+
threadCounts.put(threadState, threadCounts.get(threadState) + 1);
110+
}
111+
}
112+
113+
return threadCounts;
76114
}
77115

78116
private static double nullSafeArrayLength(long[] array) {

simpleclient_hotspot/src/test/java/io/prometheus/client/hotspot/ThreadExportsTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.junit.Test;
66
import org.mockito.Mockito;
77

8+
import java.lang.management.ThreadInfo;
89
import java.lang.management.ThreadMXBean;
910

1011
import static org.junit.Assert.assertEquals;
@@ -26,6 +27,8 @@ public void setUp() {
2627
when(mockThreadsBean.getTotalStartedThreadCount()).thenReturn(503L);
2728
when(mockThreadsBean.findDeadlockedThreads()).thenReturn(new long[]{1L,2L,3L});
2829
when(mockThreadsBean.findMonitorDeadlockedThreads()).thenReturn(new long[]{2L,3L,4L});
30+
when(mockThreadsBean.getAllThreadIds()).thenReturn(new long[]{3L,4L,5L});
31+
when(mockThreadsBean.getThreadInfo(new long[]{3L,4L,5L}, 0)).thenReturn(new ThreadInfo[] {});
2932
collectorUnderTest = new ThreadExports(mockThreadsBean).register(registry);
3033
}
3134

0 commit comments

Comments
 (0)