Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

metrics: add process metrics #1175

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -22,6 +22,7 @@
*/
module org.openjdk.skara.metrics {
requires java.management;
requires jdk.management;
exports org.openjdk.skara.metrics;
}

@@ -25,17 +25,24 @@
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryType;
import java.lang.management.MemoryUsage;
import com.sun.management.UnixOperatingSystemMXBean;
import com.sun.management.OperatingSystemMXBean;

public final class CollectorRegistry {
private static final CollectorRegistry DEFAULT = new CollectorRegistry(true);
private static final CollectorRegistry DEFAULT = new CollectorRegistry(true, true);
private final ConcurrentLinkedQueue<Collector> collectors = new ConcurrentLinkedQueue<>();
private final boolean includeHotspotMetrics;
private final boolean includeProcessMetrics;

public CollectorRegistry(boolean includeHotspotMetrics) {
public CollectorRegistry(boolean includeHotspotMetrics, boolean includeProcessMetrics) {
this.includeHotspotMetrics = includeHotspotMetrics;
this.includeProcessMetrics = includeProcessMetrics;
}

public void register(Collector c) {
@@ -111,6 +118,77 @@ private static List<Metric> hotspotMetrics() {
return result;
}

private static List<Metric> processMetrics() {
var result = new ArrayList<Metric>();
if (System.getProperty("os.name").toLowerCase().startsWith("linux")) {
List<String> status = List.of();
try {
status = Files.readAllLines(Path.of("/proc/self/status"));
} catch (IOException e) {
// ignore
}
for (var line : status) {
if (line.startsWith("VmRSS:")) {
var parts = line.split("\\s+");
if (parts.length == 3) {
var rssInKb = Long.parseLong(parts[1]);
var rssBytes = rssInKb * 1024;
result.add(new Metric(Metric.Type.GAUGE, "process_resident_memory_bytes", List.of(), rssBytes));
}
} else if (line.startsWith("VmSize:")) {
var parts = line.split("\\s+");
if (parts.length == 3) {
var vmSizeInKb = Long.parseLong(parts[1]);
var vmBytes = vmSizeInKb * 1024;
result.add(new Metric(Metric.Type.GAUGE, "process_virtual_memory_bytes", List.of(), vmBytes));
}
}
}

List<String> maps = List.of();
try {
maps = Files.readAllLines(Path.of("/proc/self/maps"));
} catch (IOException e) {
// ignore
}
var heapBytes = maps.stream()
.filter(l -> l.endsWith("[heap]"))
.map(l -> l.split("\\s+")[0])
.mapToLong(range -> {
var parts = range.split("-");
var start = Long.parseLong(parts[0], 16);
var end = Long.parseLong(parts[1], 16);
return end - start;
})
.sum();
result.add(new Metric(Metric.Type.GAUGE, "process_heap_bytes", List.of(), heapBytes));
}

var bean = ManagementFactory.getOperatingSystemMXBean();
if (bean instanceof UnixOperatingSystemMXBean) {
var osBean = (UnixOperatingSystemMXBean) bean;
var numOpenFds = osBean.getOpenFileDescriptorCount();
result.add(new Metric(Metric.Type.GAUGE, "process_open_fds", List.of(), numOpenFds));
var maxFds = osBean.getMaxFileDescriptorCount();
result.add(new Metric(Metric.Type.GAUGE, "process_max_fds", List.of(), maxFds));
}

if (bean instanceof OperatingSystemMXBean) {
var osBean = (OperatingSystemMXBean) bean;
var vmMaxBytes = osBean.getCommittedVirtualMemorySize();
result.add(new Metric(Metric.Type.GAUGE, "process_virtual_memory_max_bytes", List.of(), vmMaxBytes));

var cpuTimeNs = osBean.getProcessCpuTime();
var cpuTimeSec = cpuTimeNs / 1_000_000_000.0;
result.add(new Metric(Metric.Type.COUNTER, "process_cpu_seconds_total", List.of(), cpuTimeSec));
}

var startTimeMillis = ManagementFactory.getRuntimeMXBean().getStartTime();
result.add(new Metric(Metric.Type.COUNTER, "process_start_time_seconds", List.of(), startTimeMillis / 1000.0));

return result;
}

public List<Metric> scrape() {
var result = new ArrayList<Metric>();
for (var collector : collectors) {
@@ -119,6 +197,9 @@ public List<Metric> scrape() {
if (includeHotspotMetrics) {
result.addAll(hotspotMetrics());
}
if (includeProcessMetrics) {
result.addAll(processMetrics());
}
return result;
}

@@ -32,7 +32,7 @@
class CollectorRegistryTests {
@Test
void register() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("counter").register(registry);
var gauge = Gauge.name("gauge").register(registry);
var metrics = registry.scrape();
@@ -45,7 +45,7 @@ void register() {

@Test
void unregister() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("test").register(registry);
assertEquals(1, registry.scrape().size());
registry.unregister(counter);
@@ -54,7 +54,7 @@ void unregister() {

@Test
void hotspotMetrics() {
var registry = new CollectorRegistry(true);
var registry = new CollectorRegistry(true, false);
var metrics = registry.scrape();
var metricNames = metrics.stream().map(Metric::name).collect(Collectors.toSet());
assertTrue(metricNames.contains("hotspot_memory_max"));
@@ -71,6 +71,13 @@ void hotspotMetrics() {
assertTrue(metricNames.contains("hotspot_memory_pool_init"));
assertTrue(metricNames.contains("hotspot_classes_loaded"));
assertTrue(metricNames.contains("hotspot_classes_unloaded"));
}

@Test
void processMetrics() {
var registry = new CollectorRegistry(false, true);
var metrics = registry.scrape();
var metricNames = metrics.stream().map(Metric::name).collect(Collectors.toSet());
assertTrue(metricNames.contains("process_start_time_seconds"));
}
}
@@ -29,7 +29,7 @@
class CounterTests {
@Test
void inc() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("test").register(registry);
assertEquals(0, counter.collect().get(0).value());
counter.inc();
@@ -38,7 +38,7 @@ void inc() {

@Test
void incTwice() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("test").register(registry);
assertEquals(0, counter.collect().get(0).value());
counter.inc();
@@ -52,7 +52,7 @@ void incTwice() {

@Test
void incWithValue() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("test").register(registry);
assertEquals(0, counter.collect().get(0).value());
counter.inc(17);
@@ -61,7 +61,7 @@ void incWithValue() {

@Test
void incWithValueMixedWithInc() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("test").register(registry);
assertEquals(0, counter.collect().get(0).value());
counter.inc(17);
@@ -74,7 +74,7 @@ void incWithValueMixedWithInc() {

@Test
void incAndReset() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("test").register(registry);
assertEquals(0, counter.collect().get(0).value());
counter.inc(17);
@@ -87,7 +87,7 @@ void incAndReset() {

@Test
void oneLabel() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("test").labels("a").register(registry);
counter.labels("1").inc(17);
assertEquals(1, counter.collect().size());
@@ -99,7 +99,7 @@ void oneLabel() {

@Test
void twoLabels() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("test").labels("a", "b").register(registry);
counter.labels("1", "2").inc(17);
assertEquals(1, counter.collect().size());
@@ -113,7 +113,7 @@ void twoLabels() {

@Test
void threeLabels() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("test").labels("a", "b", "c").register(registry);
counter.labels("1", "2", "3").inc(17);
assertEquals(1, counter.collect().size());
@@ -129,7 +129,7 @@ void threeLabels() {

@Test
void threeLabelsIncAndReset() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("test").labels("a", "b", "c").register(registry);
counter.labels("1", "2", "3").inc();
assertEquals(1, counter.collect().get(0).value());
@@ -143,7 +143,7 @@ void threeLabelsIncAndReset() {

@Test
void oneLabelMultiple() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var counter = Counter.name("test").labels("a").register(registry);
counter.labels("1").inc(17);
counter.labels("2").inc(19);
@@ -29,15 +29,15 @@
class GaugeTests {
@Test
void inc() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").register(registry);
gauge.inc();
assertEquals(1, gauge.collect().get(0).value());
}

@Test
void dec() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").register(registry);
gauge.inc();
assertEquals(1, gauge.collect().get(0).value());
@@ -49,23 +49,23 @@ void dec() {

@Test
void incWithValue() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").register(registry);
gauge.inc(17);
assertEquals(17, gauge.collect().get(0).value());
}

@Test
void decWithValue() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").register(registry);
gauge.dec(17);
assertEquals(-17, gauge.collect().get(0).value());
}

@Test
void incAndDecWithValue() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").register(registry);
gauge.inc(17);
assertEquals(17, gauge.collect().get(0).value());
@@ -75,7 +75,7 @@ void incAndDecWithValue() {

@Test
void set() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").register(registry);
gauge.set(1337);
assertEquals(1337, gauge.collect().get(0).value());
@@ -85,7 +85,7 @@ void set() {

@Test
void oneLabel() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").labels("a").register(registry);
gauge.labels("1").inc();
assertEquals(1, gauge.collect().size());
@@ -97,7 +97,7 @@ void oneLabel() {

@Test
void oneLabelIncDecSet() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").labels("a").register(registry);
gauge.labels("1").inc(17);
assertEquals(1, gauge.collect().size());
@@ -113,7 +113,7 @@ void oneLabelIncDecSet() {

@Test
void twoLabels() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").labels("a", "b").register(registry);
gauge.labels("1", "2").inc();
assertEquals(1, gauge.collect().size());
@@ -127,7 +127,7 @@ void twoLabels() {

@Test
void twoLabelsIncDecSet() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").labels("a", "b").register(registry);
gauge.labels("1", "2").inc(17);
assertEquals(1, gauge.collect().size());
@@ -145,7 +145,7 @@ void twoLabelsIncDecSet() {

@Test
void threeLabels() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").labels("a", "b", "c").register(registry);
gauge.labels("1", "2", "3").inc();
assertEquals(1, gauge.collect().size());
@@ -161,7 +161,7 @@ void threeLabels() {

@Test
void threeLabelsIncDecSet() {
var registry = new CollectorRegistry(false);
var registry = new CollectorRegistry(false, false);
var gauge = Gauge.name("test").labels("a", "b", "c").register(registry);
gauge.labels("1", "2", "3").inc(17);
assertEquals(1, gauge.collect().size());