Add meter version to runtime metrics (#6874)

Runtime metrics doesn't include the meter version. This adds it from the
utility method in the instrumentation-api
`EmbeddedInstrumentationProperties.findVersion`. I know I can read the
properties file for this module, but its repetitive to implement that in
many places.
This commit is contained in:
jack-berg 2022-10-22 20:09:44 -05:00 committed by GitHub
parent d18a05b5a2
commit 015dbf90b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 291 additions and 8 deletions

View File

@ -3,6 +3,8 @@ plugins {
}
dependencies {
implementation(project(":instrumentation-api"))
testImplementation("io.opentelemetry:opentelemetry-sdk-metrics")
testImplementation(project(":testing-common"))
}

View File

@ -39,10 +39,14 @@ public final class BufferPools {
/** Register observers for java runtime buffer pool metrics. */
public static void registerObservers(OpenTelemetry openTelemetry) {
List<BufferPoolMXBean> bufferBeans =
ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
Meter meter = openTelemetry.getMeter("io.opentelemetry.runtime-metrics");
registerObservers(openTelemetry, bufferBeans);
}
// Visible for testing
static void registerObservers(OpenTelemetry openTelemetry, List<BufferPoolMXBean> bufferBeans) {
Meter meter = RuntimeMetricsUtil.getMeter(openTelemetry);
meter
.upDownCounterBuilder("process.runtime.jvm.buffer.usage")
@ -63,6 +67,7 @@ public final class BufferPools {
.buildWithCallback(callback(bufferBeans, BufferPoolMXBean::getCount));
}
// Visible for testing
static Consumer<ObservableLongMeasurement> callback(
List<BufferPoolMXBean> bufferPools, Function<BufferPoolMXBean, Long> extractor) {
List<Attributes> attributeSets = new ArrayList<>(bufferPools.size());

View File

@ -39,7 +39,7 @@ public final class Classes {
// Visible for testing
void registerObservers(OpenTelemetry openTelemetry, ClassLoadingMXBean classBean) {
Meter meter = openTelemetry.getMeter("io.opentelemetry.runtime-metrics");
Meter meter = RuntimeMetricsUtil.getMeter(openTelemetry);
meter
.counterBuilder("process.runtime.jvm.classes.loaded")

View File

@ -80,7 +80,7 @@ public final class Cpu {
OperatingSystemMXBean osBean,
@Nullable Supplier<Double> systemCpuUsage,
@Nullable Supplier<Double> processCpuUsage) {
Meter meter = openTelemetry.getMeter("io.opentelemetry.runtime-metrics");
Meter meter = RuntimeMetricsUtil.getMeter(openTelemetry);
meter
.gaugeBuilder("process.runtime.jvm.system.cpu.load_1m")

View File

@ -36,7 +36,7 @@ public final class GarbageCollector {
/** Register observers for java runtime garbage collector metrics. */
public static void registerObservers(OpenTelemetry openTelemetry) {
List<GarbageCollectorMXBean> garbageCollectors = ManagementFactory.getGarbageCollectorMXBeans();
Meter meter = openTelemetry.getMeterProvider().get(GarbageCollector.class.getName());
Meter meter = RuntimeMetricsUtil.getMeter(openTelemetry);
List<Attributes> labelSets = new ArrayList<>(garbageCollectors.size());
for (GarbageCollectorMXBean gc : garbageCollectors) {
labelSets.add(Attributes.of(GC_KEY, gc.getName()));

View File

@ -50,8 +50,12 @@ public final class MemoryPools {
/** Register observers for java runtime memory metrics. */
public static void registerObservers(OpenTelemetry openTelemetry) {
List<MemoryPoolMXBean> poolBeans = ManagementFactory.getMemoryPoolMXBeans();
Meter meter = openTelemetry.getMeter("io.opentelemetry.runtime-metrics");
registerObservers(openTelemetry, ManagementFactory.getMemoryPoolMXBeans());
}
// Visible for testing
static void registerObservers(OpenTelemetry openTelemetry, List<MemoryPoolMXBean> poolBeans) {
Meter meter = RuntimeMetricsUtil.getMeter(openTelemetry);
meter
.upDownCounterBuilder("process.runtime.jvm.memory.usage")

View File

@ -0,0 +1,31 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.runtimemetrics;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.MeterBuilder;
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
import javax.annotation.Nullable;
class RuntimeMetricsUtil {
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.runtime-metrics";
@Nullable
private static final String INSTRUMENTATION_VERSION =
EmbeddedInstrumentationProperties.findVersion(INSTRUMENTATION_NAME);
static Meter getMeter(OpenTelemetry openTelemetry) {
MeterBuilder meterBuilder = openTelemetry.meterBuilder(INSTRUMENTATION_NAME);
if (INSTRUMENTATION_VERSION != null) {
meterBuilder.setInstrumentationVersion(INSTRUMENTATION_VERSION);
}
return meterBuilder.build();
}
private RuntimeMetricsUtil() {}
}

View File

@ -42,7 +42,7 @@ public final class Threads {
// Visible for testing
void registerObservers(OpenTelemetry openTelemetry, ThreadMXBean threadBean) {
Meter meter = openTelemetry.getMeter("io.opentelemetry.runtime-metrics");
Meter meter = RuntimeMetricsUtil.getMeter(openTelemetry);
meter
.upDownCounterBuilder("process.runtime.jvm.threads.count")

View File

@ -5,14 +5,19 @@
package io.opentelemetry.instrumentation.runtimemetrics;
import static io.opentelemetry.instrumentation.runtimemetrics.ScopeUtil.EXPECTED_SCOPE;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
import java.lang.management.BufferPoolMXBean;
import java.util.Arrays;
import java.util.List;
@ -20,12 +25,17 @@ import java.util.function.Consumer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class BufferPoolsTest {
@RegisterExtension
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
@Spy private ObservableLongMeasurement measurement;
@Mock private BufferPoolMXBean bufferPoolBean;
private List<BufferPoolMXBean> beans;
@ -36,6 +46,74 @@ public class BufferPoolsTest {
beans = Arrays.asList(bufferPoolBean);
}
@Test
void registerObservers() {
when(bufferPoolBean.getMemoryUsed()).thenReturn(10L);
when(bufferPoolBean.getTotalCapacity()).thenReturn(11L);
when(bufferPoolBean.getCount()).thenReturn(12L);
BufferPools.registerObservers(testing.getOpenTelemetry(), beans);
testing.waitAndAssertMetrics(
"io.opentelemetry.runtime-metrics",
"process.runtime.jvm.buffer.usage",
metrics ->
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription(
"Memory that the Java virtual machine is using for this buffer pool")
.hasUnit("By")
.hasLongSumSatisfying(
sum ->
sum.hasPointsSatisfying(
point ->
point
.hasValue(10)
.hasAttribute(
AttributeKey.stringKey("pool"),
"buffer_pool_1")))));
testing.waitAndAssertMetrics(
"io.opentelemetry.runtime-metrics",
"process.runtime.jvm.buffer.limit",
metrics ->
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Total capacity of the buffers in this pool")
.hasUnit("By")
.hasLongSumSatisfying(
sum ->
sum.hasPointsSatisfying(
point ->
point
.hasValue(11)
.hasAttribute(
AttributeKey.stringKey("pool"),
"buffer_pool_1")))));
testing.waitAndAssertMetrics(
"io.opentelemetry.runtime-metrics",
"process.runtime.jvm.buffer.count",
metrics ->
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("The number of buffers in the pool")
.hasUnit("buffers")
.hasLongSumSatisfying(
sum ->
sum.hasPointsSatisfying(
point ->
point
.hasValue(12)
.hasAttribute(
AttributeKey.stringKey("pool"),
"buffer_pool_1")))));
}
@Test
void callback_Records() {
when(bufferPoolBean.getMemoryUsed()).thenReturn(1L);

View File

@ -5,6 +5,7 @@
package io.opentelemetry.instrumentation.runtimemetrics;
import static io.opentelemetry.instrumentation.runtimemetrics.ScopeUtil.EXPECTED_SCOPE;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static org.mockito.Mockito.when;
@ -41,6 +42,7 @@ class ClassesTest {
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Number of classes loaded since JVM start")
.hasUnit("1")
.hasLongSumSatisfying(
@ -56,6 +58,7 @@ class ClassesTest {
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Number of classes unloaded since JVM start")
.hasUnit("1")
.hasLongSumSatisfying(
@ -71,6 +74,7 @@ class ClassesTest {
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Number of classes currently loaded")
.hasUnit("1")
.hasLongSumSatisfying(

View File

@ -5,6 +5,7 @@
package io.opentelemetry.instrumentation.runtimemetrics;
import static io.opentelemetry.instrumentation.runtimemetrics.ScopeUtil.EXPECTED_SCOPE;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static org.mockito.Mockito.when;
@ -42,6 +43,7 @@ class CpuTest {
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Average CPU load of the whole system for the last minute")
.hasUnit("1")
.hasDoubleGaugeSatisfying(
@ -53,6 +55,7 @@ class CpuTest {
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Recent cpu utilization for the whole system")
.hasUnit("1")
.hasDoubleGaugeSatisfying(
@ -64,6 +67,7 @@ class CpuTest {
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Recent cpu utilization for the process")
.hasUnit("1")
.hasDoubleGaugeSatisfying(

View File

@ -5,14 +5,19 @@
package io.opentelemetry.instrumentation.runtimemetrics;
import static io.opentelemetry.instrumentation.runtimemetrics.ScopeUtil.EXPECTED_SCOPE;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryType;
import java.lang.management.MemoryUsage;
@ -22,6 +27,7 @@ import java.util.function.Consumer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
@ -29,6 +35,9 @@ import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class MemoryPoolsTest {
@RegisterExtension
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
@Spy private ObservableLongMeasurement measurement;
@Mock private MemoryPoolMXBean heapPoolBean;
@ -50,6 +59,125 @@ class MemoryPoolsTest {
beans = Arrays.asList(heapPoolBean, nonHeapPoolBean);
}
@Test
void registerObservers() {
when(heapPoolUsage.getInit()).thenReturn(10L);
when(heapPoolUsage.getUsed()).thenReturn(11L);
when(heapPoolUsage.getCommitted()).thenReturn(12L);
when(heapPoolUsage.getMax()).thenReturn(13L);
when(nonHeapUsage.getInit()).thenReturn(14L);
when(nonHeapUsage.getUsed()).thenReturn(15L);
when(nonHeapUsage.getCommitted()).thenReturn(16L);
when(nonHeapUsage.getMax()).thenReturn(17L);
MemoryPools.registerObservers(testing.getOpenTelemetry(), beans);
testing.waitAndAssertMetrics(
"io.opentelemetry.runtime-metrics",
"process.runtime.jvm.memory.init",
metrics ->
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Measure of initial memory requested")
.hasUnit("By")
.hasLongSumSatisfying(
sum ->
sum.hasPointsSatisfying(
point ->
point
.hasValue(10)
.hasAttribute(
AttributeKey.stringKey("pool"), "heap_pool")
.hasAttribute(AttributeKey.stringKey("type"), "heap"),
point ->
point
.hasValue(14)
.hasAttribute(
AttributeKey.stringKey("pool"), "non_heap_pool")
.hasAttribute(
AttributeKey.stringKey("type"), "non_heap")))));
testing.waitAndAssertMetrics(
"io.opentelemetry.runtime-metrics",
"process.runtime.jvm.memory.usage",
metrics ->
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Measure of memory used")
.hasUnit("By")
.hasLongSumSatisfying(
sum ->
sum.hasPointsSatisfying(
point ->
point
.hasValue(11)
.hasAttribute(
AttributeKey.stringKey("pool"), "heap_pool")
.hasAttribute(AttributeKey.stringKey("type"), "heap"),
point ->
point
.hasValue(15)
.hasAttribute(
AttributeKey.stringKey("pool"), "non_heap_pool")
.hasAttribute(
AttributeKey.stringKey("type"), "non_heap")))));
testing.waitAndAssertMetrics(
"io.opentelemetry.runtime-metrics",
"process.runtime.jvm.memory.committed",
metrics ->
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Measure of memory committed")
.hasUnit("By")
.hasLongSumSatisfying(
sum ->
sum.hasPointsSatisfying(
point ->
point
.hasValue(12)
.hasAttribute(
AttributeKey.stringKey("pool"), "heap_pool")
.hasAttribute(AttributeKey.stringKey("type"), "heap"),
point ->
point
.hasValue(16)
.hasAttribute(
AttributeKey.stringKey("pool"), "non_heap_pool")
.hasAttribute(
AttributeKey.stringKey("type"), "non_heap")))));
testing.waitAndAssertMetrics(
"io.opentelemetry.runtime-metrics",
"process.runtime.jvm.memory.limit",
metrics ->
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Measure of max obtainable memory")
.hasUnit("By")
.hasLongSumSatisfying(
sum ->
sum.hasPointsSatisfying(
point ->
point
.hasValue(13)
.hasAttribute(
AttributeKey.stringKey("pool"), "heap_pool")
.hasAttribute(AttributeKey.stringKey("type"), "heap"),
point ->
point
.hasValue(17)
.hasAttribute(
AttributeKey.stringKey("pool"), "non_heap_pool")
.hasAttribute(
AttributeKey.stringKey("type"), "non_heap")))));
}
@Test
void callback_Records() {
when(heapPoolUsage.getUsed()).thenReturn(1L);

View File

@ -0,0 +1,25 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.runtimemetrics;
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import java.util.Optional;
class ScopeUtil {
static final InstrumentationScopeInfo EXPECTED_SCOPE =
InstrumentationScopeInfo.builder("io.opentelemetry.runtime-metrics")
.setVersion(
Optional.ofNullable(
EmbeddedInstrumentationProperties.findVersion(
"io.opentelemetry.runtime-metrics"))
.orElseThrow(
() -> new IllegalStateException("Unable to find instrumentation version")))
.build();
private ScopeUtil() {}
}

View File

@ -5,6 +5,7 @@
package io.opentelemetry.instrumentation.runtimemetrics;
import static io.opentelemetry.instrumentation.runtimemetrics.ScopeUtil.EXPECTED_SCOPE;
import static io.opentelemetry.instrumentation.runtimemetrics.Threads.DAEMON;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
@ -41,6 +42,7 @@ class ThreadsTest {
metrics.anySatisfy(
metricData ->
assertThat(metricData)
.hasInstrumentationScope(EXPECTED_SCOPE)
.hasDescription("Number of executing threads")
.hasUnit("1")
.hasLongSumSatisfying(