Fix memory pool metrics (#2075)

This commit is contained in:
Devin Smith 2020-11-16 10:29:52 -06:00 committed by GitHub
parent eb02713006
commit 42483b5726
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 104 additions and 20 deletions

View File

@ -45,6 +45,18 @@ public final class MemoryPools {
private static final String HEAP = "heap";
private static final String NON_HEAP = "non_heap";
private static final Labels COMMITTED_HEAP =
Labels.of(TYPE_LABEL_KEY, COMMITTED, AREA_LABEL_KEY, HEAP);
private static final Labels USED_HEAP = Labels.of(TYPE_LABEL_KEY, USED, AREA_LABEL_KEY, HEAP);
private static final Labels MAX_HEAP = Labels.of(TYPE_LABEL_KEY, MAX, AREA_LABEL_KEY, HEAP);
private static final Labels COMMITTED_NON_HEAP =
Labels.of(TYPE_LABEL_KEY, COMMITTED, AREA_LABEL_KEY, NON_HEAP);
private static final Labels USED_NON_HEAP =
Labels.of(TYPE_LABEL_KEY, USED, AREA_LABEL_KEY, NON_HEAP);
private static final Labels MAX_NON_HEAP =
Labels.of(TYPE_LABEL_KEY, MAX, AREA_LABEL_KEY, NON_HEAP);
private final MemoryMXBean memoryBean;
private final List<MemoryPoolMXBean> poolBeans;
private final Meter meter;
@ -64,25 +76,12 @@ public final class MemoryPools {
.setDescription("Bytes of a given JVM memory area.")
.setUnit("By")
.build();
final Labels usedHeap = Labels.of(TYPE_LABEL_KEY, USED, AREA_LABEL_KEY, HEAP);
final Labels usedNonHeap = Labels.of(TYPE_LABEL_KEY, USED, AREA_LABEL_KEY, NON_HEAP);
final Labels committedHeap = Labels.of(TYPE_LABEL_KEY, COMMITTED, AREA_LABEL_KEY, HEAP);
final Labels committedNonHeap = Labels.of(TYPE_LABEL_KEY, COMMITTED, AREA_LABEL_KEY, NON_HEAP);
// TODO: Decide if max is needed or not. May be derived with some approximation from max(used).
final Labels maxHeap = Labels.of(TYPE_LABEL_KEY, MAX, AREA_LABEL_KEY, HEAP);
final Labels maxNonHeap = Labels.of(TYPE_LABEL_KEY, MAX, AREA_LABEL_KEY, NON_HEAP);
areaMetric.setCallback(
new AsynchronousInstrument.Callback<LongResult>() {
@Override
public void update(LongResult resultLongObserver) {
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
MemoryUsage nonHeapUsage = memoryBean.getNonHeapMemoryUsage();
resultLongObserver.observe(heapUsage.getUsed(), usedHeap);
resultLongObserver.observe(nonHeapUsage.getUsed(), usedNonHeap);
resultLongObserver.observe(heapUsage.getUsed(), committedHeap);
resultLongObserver.observe(nonHeapUsage.getUsed(), committedNonHeap);
resultLongObserver.observe(heapUsage.getUsed(), maxHeap);
resultLongObserver.observe(nonHeapUsage.getUsed(), maxNonHeap);
observeHeap(resultLongObserver, memoryBean.getHeapMemoryUsage());
observeNonHeap(resultLongObserver, memoryBean.getNonHeapMemoryUsage());
}
});
}
@ -109,11 +108,14 @@ public final class MemoryPools {
public void update(LongResult resultLongObserver) {
for (int i = 0; i < poolBeans.size(); i++) {
MemoryUsage poolUsage = poolBeans.get(i).getUsage();
resultLongObserver.observe(poolUsage.getUsed(), usedLabelSets.get(i));
resultLongObserver.observe(poolUsage.getCommitted(), committedLabelSets.get(i));
// TODO: Decide if max is needed or not. May be derived with some approximation from
// max(used).
resultLongObserver.observe(poolUsage.getMax(), maxLabelSets.get(i));
if (poolUsage != null) {
observe(
resultLongObserver,
poolUsage,
usedLabelSets.get(i),
committedLabelSets.get(i),
maxLabelSets.get(i));
}
}
}
});
@ -124,4 +126,30 @@ public final class MemoryPools {
exportMemoryAreaMetric();
exportMemoryPoolMetric();
}
static void observeHeap(LongResult observer, MemoryUsage usage) {
observe(observer, usage, USED_HEAP, COMMITTED_HEAP, MAX_HEAP);
}
static void observeNonHeap(LongResult observer, MemoryUsage usage) {
observe(observer, usage, USED_NON_HEAP, COMMITTED_NON_HEAP, MAX_NON_HEAP);
}
private static void observe(
LongResult observer,
MemoryUsage usage,
Labels usedLabels,
Labels committedLabels,
Labels maxLabels) {
// TODO: Decide if init is needed or not. It is a constant that can be queried once on startup.
// if (usage.getInit() != -1) {
// observer.observe(usage.getInit(), ...);
// }
observer.observe(usage.getUsed(), usedLabels);
observer.observe(usage.getCommitted(), committedLabels);
// TODO: Decide if max is needed or not. It is a constant that can be queried once on startup.
if (usage.getMax() != -1) {
observer.observe(usage.getMax(), maxLabels);
}
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.extension.metrics.runtime;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import io.opentelemetry.api.common.Labels;
import io.opentelemetry.api.metrics.AsynchronousInstrument;
import java.lang.management.MemoryUsage;
import org.junit.jupiter.api.Test;
class MemoryPoolsTest {
@Test
void observeHeap() {
AsynchronousInstrument.LongResult observer = mock(AsynchronousInstrument.LongResult.class);
MemoryPools.observeHeap(observer, new MemoryUsage(-1, 1, 2, 3));
verify(observer).observe(1, Labels.of("type", "used", "area", "heap"));
verify(observer).observe(2, Labels.of("type", "committed", "area", "heap"));
verify(observer).observe(3, Labels.of("type", "max", "area", "heap"));
verifyNoMoreInteractions(observer);
}
@Test
void observeHeapNoMax() {
AsynchronousInstrument.LongResult observer = mock(AsynchronousInstrument.LongResult.class);
MemoryPools.observeHeap(observer, new MemoryUsage(-1, 1, 2, -1));
verify(observer).observe(1, Labels.of("type", "used", "area", "heap"));
verify(observer).observe(2, Labels.of("type", "committed", "area", "heap"));
verifyNoMoreInteractions(observer);
}
@Test
void observeNonHeap() {
AsynchronousInstrument.LongResult observer = mock(AsynchronousInstrument.LongResult.class);
MemoryPools.observeNonHeap(observer, new MemoryUsage(-1, 4, 5, 6));
verify(observer).observe(4, Labels.of("type", "used", "area", "non_heap"));
verify(observer).observe(5, Labels.of("type", "committed", "area", "non_heap"));
verify(observer).observe(6, Labels.of("type", "max", "area", "non_heap"));
verifyNoMoreInteractions(observer);
}
@Test
void observeNonHeapNoMax() {
AsynchronousInstrument.LongResult observer = mock(AsynchronousInstrument.LongResult.class);
MemoryPools.observeNonHeap(observer, new MemoryUsage(-1, 4, 5, -1));
verify(observer).observe(4, Labels.of("type", "used", "area", "non_heap"));
verify(observer).observe(5, Labels.of("type", "committed", "area", "non_heap"));
verifyNoMoreInteractions(observer);
}
}