Add jvm threads instrumentation (#6070)
* Add jvm threads instrumentation * Use up down counter
This commit is contained in:
parent
6f0f608cbb
commit
1f9de2ed7c
|
@ -11,6 +11,7 @@ import io.opentelemetry.instrumentation.api.config.Config;
|
||||||
import io.opentelemetry.instrumentation.runtimemetrics.Classes;
|
import io.opentelemetry.instrumentation.runtimemetrics.Classes;
|
||||||
import io.opentelemetry.instrumentation.runtimemetrics.GarbageCollector;
|
import io.opentelemetry.instrumentation.runtimemetrics.GarbageCollector;
|
||||||
import io.opentelemetry.instrumentation.runtimemetrics.MemoryPools;
|
import io.opentelemetry.instrumentation.runtimemetrics.MemoryPools;
|
||||||
|
import io.opentelemetry.instrumentation.runtimemetrics.Threads;
|
||||||
import io.opentelemetry.javaagent.extension.AgentListener;
|
import io.opentelemetry.javaagent.extension.AgentListener;
|
||||||
import io.opentelemetry.javaagent.tooling.config.AgentConfig;
|
import io.opentelemetry.javaagent.tooling.config.AgentConfig;
|
||||||
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
|
||||||
|
@ -28,8 +29,9 @@ public class RuntimeMetricsInstaller implements AgentListener {
|
||||||
if (new AgentConfig(config)
|
if (new AgentConfig(config)
|
||||||
.isInstrumentationEnabled(Collections.singleton("runtime-metrics"), DEFAULT_ENABLED)) {
|
.isInstrumentationEnabled(Collections.singleton("runtime-metrics"), DEFAULT_ENABLED)) {
|
||||||
|
|
||||||
MemoryPools.registerObservers(GlobalOpenTelemetry.get());
|
|
||||||
Classes.registerObservers(GlobalOpenTelemetry.get());
|
Classes.registerObservers(GlobalOpenTelemetry.get());
|
||||||
|
MemoryPools.registerObservers(GlobalOpenTelemetry.get());
|
||||||
|
Threads.registerObservers(GlobalOpenTelemetry.get());
|
||||||
|
|
||||||
if (config.getBoolean(
|
if (config.getBoolean(
|
||||||
"otel.instrumentation.runtime-metrics.experimental-metrics.enabled", false)) {
|
"otel.instrumentation.runtime-metrics.experimental-metrics.enabled", false)) {
|
||||||
|
|
|
@ -16,15 +16,16 @@ class RuntimeMetricsTest extends AgentInstrumentationSpecification {
|
||||||
|
|
||||||
then:
|
then:
|
||||||
conditions.eventually {
|
conditions.eventually {
|
||||||
|
assert getMetrics().any { it.name == "process.runtime.jvm.classes.loaded" }
|
||||||
|
assert getMetrics().any { it.name == "process.runtime.jvm.classes.unloaded" }
|
||||||
|
assert getMetrics().any { it.name == "process.runtime.jvm.classes.current_loaded" }
|
||||||
assert getMetrics().any { it.name == "runtime.jvm.gc.time" }
|
assert getMetrics().any { it.name == "runtime.jvm.gc.time" }
|
||||||
assert getMetrics().any { it.name == "runtime.jvm.gc.count" }
|
assert getMetrics().any { it.name == "runtime.jvm.gc.count" }
|
||||||
assert getMetrics().any { it.name == "process.runtime.jvm.memory.init" }
|
assert getMetrics().any { it.name == "process.runtime.jvm.memory.init" }
|
||||||
assert getMetrics().any { it.name == "process.runtime.jvm.memory.usage" }
|
assert getMetrics().any { it.name == "process.runtime.jvm.memory.usage" }
|
||||||
assert getMetrics().any { it.name == "process.runtime.jvm.memory.committed" }
|
assert getMetrics().any { it.name == "process.runtime.jvm.memory.committed" }
|
||||||
assert getMetrics().any { it.name == "process.runtime.jvm.memory.max" }
|
assert getMetrics().any { it.name == "process.runtime.jvm.memory.max" }
|
||||||
assert getMetrics().any { it.name == "process.runtime.jvm.classes.loaded" }
|
assert getMetrics().any { it.name == "process.runtime.jvm.threads.count" }
|
||||||
assert getMetrics().any { it.name == "process.runtime.jvm.classes.unloaded" }
|
|
||||||
assert getMetrics().any { it.name == "process.runtime.jvm.classes.current_loaded" }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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 java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.ThreadMXBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers measurements that generate metrics about JVM threads.
|
||||||
|
*
|
||||||
|
* <p>Example usage:
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* Classes.registerObservers(GlobalOpenTelemetry.get());
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* <p>Example metrics being exported:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* process.runtime.jvm.threads.count 4
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
public final class Threads {
|
||||||
|
|
||||||
|
// Visible for testing
|
||||||
|
static final Threads INSTANCE = new Threads();
|
||||||
|
|
||||||
|
/** Register observers for java runtime class metrics. */
|
||||||
|
public static void registerObservers(OpenTelemetry openTelemetry) {
|
||||||
|
INSTANCE.registerObservers(openTelemetry, ManagementFactory.getThreadMXBean());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visible for testing
|
||||||
|
void registerObservers(OpenTelemetry openTelemetry, ThreadMXBean threadBean) {
|
||||||
|
Meter meter = openTelemetry.getMeter("io.opentelemetry.runtime-metrics");
|
||||||
|
|
||||||
|
meter
|
||||||
|
.upDownCounterBuilder("process.runtime.jvm.threads.count")
|
||||||
|
.setDescription("Number of executing threads")
|
||||||
|
.setUnit("1")
|
||||||
|
.buildWithCallback(
|
||||||
|
observableMeasurement -> observableMeasurement.record(threadBean.getThreadCount()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Threads() {}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.instrumentation.runtimemetrics;
|
||||||
|
|
||||||
|
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.common.Attributes;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||||
|
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
|
||||||
|
import java.lang.management.ThreadMXBean;
|
||||||
|
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.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class ThreadsTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
|
||||||
|
|
||||||
|
@Mock private ThreadMXBean threadBean;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerObservers() {
|
||||||
|
when(threadBean.getThreadCount()).thenReturn(3);
|
||||||
|
|
||||||
|
Threads.INSTANCE.registerObservers(testing.getOpenTelemetry(), threadBean);
|
||||||
|
|
||||||
|
testing.waitAndAssertMetrics(
|
||||||
|
"io.opentelemetry.runtime-metrics",
|
||||||
|
"process.runtime.jvm.threads.count",
|
||||||
|
metrics ->
|
||||||
|
metrics.anySatisfy(
|
||||||
|
metricData ->
|
||||||
|
assertThat(metricData)
|
||||||
|
.hasDescription("Number of executing threads")
|
||||||
|
.hasUnit("1")
|
||||||
|
.hasLongSumSatisfying(
|
||||||
|
sum ->
|
||||||
|
sum.isNotMonotonic()
|
||||||
|
.hasPointsSatisfying(
|
||||||
|
point ->
|
||||||
|
point.hasValue(3).hasAttributes(Attributes.empty())))));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue