Skip to content

Commit 8604da3

Browse files
schmikeiotelbot[bot]laurit
authored
Add metric jvm.file_descriptor.count to jvm runtime experimental metrics (#13904)
Co-authored-by: otelbot <[email protected]> Co-authored-by: Lauri Tulmin <[email protected]>
1 parent 783d5e7 commit 8604da3

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.runtimemetrics.java8.internal;
7+
8+
import io.opentelemetry.api.OpenTelemetry;
9+
import io.opentelemetry.api.metrics.Meter;
10+
import java.lang.management.ManagementFactory;
11+
import java.lang.management.OperatingSystemMXBean;
12+
import java.util.ArrayList;
13+
import java.util.List;
14+
15+
/**
16+
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
17+
* any time.
18+
*/
19+
public final class ExperimentalFileDescriptor {
20+
private static final Class<?> unixOperatingSystemMxBeanClass =
21+
loadClass("com.sun.management.UnixOperatingSystemMXBean");
22+
23+
private static Class<?> loadClass(String className) {
24+
try {
25+
return Class.forName(className, false, ExperimentalFileDescriptor.class.getClassLoader());
26+
} catch (ClassNotFoundException | LinkageError e) {
27+
return null;
28+
}
29+
}
30+
31+
/** Register observers for java runtime file descriptor metrics. */
32+
public static List<AutoCloseable> registerObservers(OpenTelemetry openTelemetry) {
33+
return registerObservers(openTelemetry, ManagementFactory.getOperatingSystemMXBean());
34+
}
35+
36+
// Visible for testing
37+
static List<AutoCloseable> registerObservers(
38+
OpenTelemetry openTelemetry, OperatingSystemMXBean osBean) {
39+
Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
40+
List<AutoCloseable> observables = new ArrayList<>();
41+
42+
if (unixOperatingSystemMxBeanClass != null
43+
&& unixOperatingSystemMxBeanClass.isInstance(osBean)) {
44+
observables.add(
45+
meter
46+
.upDownCounterBuilder("jvm.file_descriptor.count")
47+
.setDescription("Number of open file descriptors as reported by the JVM.")
48+
.setUnit("{file_descriptor}")
49+
.buildWithCallback(
50+
observableMeasurement -> {
51+
long openFileDescriptorCount =
52+
((com.sun.management.UnixOperatingSystemMXBean) osBean)
53+
.getOpenFileDescriptorCount();
54+
if (openFileDescriptorCount >= 0) {
55+
observableMeasurement.record(openFileDescriptorCount);
56+
}
57+
}));
58+
}
59+
60+
return observables;
61+
}
62+
63+
private ExperimentalFileDescriptor() {}
64+
}

instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public static List<AutoCloseable> buildObservables(
3333
observables.addAll(ExperimentalBufferPools.registerObservers(openTelemetry));
3434
observables.addAll(ExperimentalCpu.registerObservers(openTelemetry));
3535
observables.addAll(ExperimentalMemoryPools.registerObservers(openTelemetry));
36+
observables.addAll(ExperimentalFileDescriptor.registerObservers(openTelemetry));
3637
}
3738
return observables;
3839
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.runtimemetrics.java8.internal;
7+
8+
import static io.opentelemetry.instrumentation.runtimemetrics.java8.ScopeUtil.EXPECTED_SCOPE;
9+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
10+
import static org.junit.jupiter.api.Assumptions.assumeTrue;
11+
import static org.mockito.Mockito.when;
12+
13+
import com.sun.management.UnixOperatingSystemMXBean;
14+
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
15+
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
16+
import java.lang.management.ManagementFactory;
17+
import java.lang.management.OperatingSystemMXBean;
18+
import org.junit.jupiter.api.BeforeEach;
19+
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.api.extension.ExtendWith;
21+
import org.junit.jupiter.api.extension.RegisterExtension;
22+
import org.mockito.Mock;
23+
import org.mockito.junit.jupiter.MockitoExtension;
24+
25+
@ExtendWith(MockitoExtension.class)
26+
class ExperimentalFileDescriptorTest {
27+
28+
@RegisterExtension
29+
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
30+
31+
@Mock private UnixOperatingSystemMXBean osBean;
32+
33+
@BeforeEach
34+
void setUp() {
35+
// Skip tests on non-Unix systems since UnixOperatingSystemMXBean is only available on Unix
36+
OperatingSystemMXBean realOsBean = ManagementFactory.getOperatingSystemMXBean();
37+
assumeTrue(
38+
realOsBean instanceof UnixOperatingSystemMXBean,
39+
"Skipping test: UnixOperatingSystemMXBean is only available on Unix systems");
40+
}
41+
42+
@Test
43+
// verify that mock is called with the correct value
44+
void registerObservers() {
45+
when(osBean.getOpenFileDescriptorCount()).thenReturn(42L);
46+
ExperimentalFileDescriptor.registerObservers(testing.getOpenTelemetry(), osBean);
47+
48+
testing.waitAndAssertMetrics(
49+
"io.opentelemetry.runtime-telemetry-java8",
50+
"jvm.file_descriptor.count",
51+
metrics ->
52+
metrics.anySatisfy(
53+
metricData ->
54+
assertThat(metricData)
55+
.hasInstrumentationScope(EXPECTED_SCOPE)
56+
.hasDescription("Number of open file descriptors as reported by the JVM.")
57+
.hasUnit("{file_descriptor}")
58+
.hasLongSumSatisfying(
59+
sum -> sum.hasPointsSatisfying(point -> point.hasValue(42)))));
60+
}
61+
62+
@Test
63+
// Verify that no metrics are emitted with non-zero values
64+
void registerObservers_NegativeValue() {
65+
when(osBean.getOpenFileDescriptorCount()).thenReturn(-1L);
66+
ExperimentalFileDescriptor.registerObservers(testing.getOpenTelemetry(), osBean);
67+
68+
testing.waitAndAssertMetrics(
69+
"io.opentelemetry.runtime-telemetry-java8",
70+
"jvm.file_descriptor.count",
71+
metrics ->
72+
metrics.allSatisfy(
73+
metricData ->
74+
assertThat(metricData)
75+
.hasInstrumentationScope(EXPECTED_SCOPE)
76+
.hasDescription("Number of open file descriptors as reported by the JVM.")
77+
.hasUnit("{file_descriptor}")
78+
.hasLongSumSatisfying(
79+
sum -> sum.hasPointsSatisfying(point -> point.hasValue(0)))));
80+
}
81+
}

0 commit comments

Comments
 (0)