Enable stable JVM semconv by default (#9963)
Co-authored-by: Mateusz Rzeszutek <mrzeszutek@splunk.com>
This commit is contained in:
parent
5522a23a82
commit
bdeec9fc0d
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.api.internal;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
|
||||
* any time.
|
||||
*/
|
||||
public final class SemconvStability {
|
||||
|
||||
private static final boolean emitOldJvmSemconv;
|
||||
private static final boolean emitStableJvmSemconv;
|
||||
|
||||
static {
|
||||
boolean oldJvm = true;
|
||||
boolean stableJvm = false;
|
||||
|
||||
String value = ConfigPropertiesUtil.getString("otel.semconv-stability.opt-in");
|
||||
if (value != null) {
|
||||
Set<String> values = new HashSet<>(asList(value.split(",")));
|
||||
if (values.contains("jvm")) {
|
||||
oldJvm = false;
|
||||
stableJvm = true;
|
||||
}
|
||||
if (values.contains("jvm/dup")) {
|
||||
oldJvm = true;
|
||||
stableJvm = true;
|
||||
}
|
||||
}
|
||||
|
||||
emitOldJvmSemconv = oldJvm;
|
||||
emitStableJvmSemconv = stableJvm;
|
||||
}
|
||||
|
||||
public static boolean emitOldJvmSemconv() {
|
||||
return emitOldJvmSemconv;
|
||||
}
|
||||
|
||||
public static boolean emitStableJvmSemconv() {
|
||||
return emitStableJvmSemconv;
|
||||
}
|
||||
|
||||
private SemconvStability() {}
|
||||
}
|
|
@ -22,21 +22,17 @@ class JmxRuntimeMetricsTest {
|
|||
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
metric -> metric.hasName("process.runtime.jvm.classes.loaded"),
|
||||
metric -> metric.hasName("process.runtime.jvm.classes.unloaded"),
|
||||
metric -> metric.hasName("process.runtime.jvm.classes.current_loaded"),
|
||||
metric -> metric.hasName("process.runtime.jvm.system.cpu.load_1m"),
|
||||
metric -> metric.hasName("process.runtime.jvm.system.cpu.utilization"),
|
||||
metric -> metric.hasName("process.runtime.jvm.cpu.utilization"),
|
||||
metric -> metric.hasName("process.runtime.jvm.gc.duration"),
|
||||
metric -> metric.hasName("process.runtime.jvm.memory.init"),
|
||||
metric -> metric.hasName("process.runtime.jvm.memory.usage"),
|
||||
metric -> metric.hasName("process.runtime.jvm.memory.committed"),
|
||||
metric -> metric.hasName("process.runtime.jvm.memory.limit"),
|
||||
metric -> metric.hasName("process.runtime.jvm.memory.usage_after_last_gc"),
|
||||
metric -> metric.hasName("process.runtime.jvm.threads.count"),
|
||||
metric -> metric.hasName("process.runtime.jvm.buffer.limit"),
|
||||
metric -> metric.hasName("process.runtime.jvm.buffer.count"),
|
||||
metric -> metric.hasName("process.runtime.jvm.buffer.usage"));
|
||||
metric -> metric.hasName("jvm.class.loaded"),
|
||||
metric -> metric.hasName("jvm.class.unloaded"),
|
||||
metric -> metric.hasName("jvm.class.count"),
|
||||
metric -> metric.hasName("jvm.cpu.time"),
|
||||
metric -> metric.hasName("jvm.cpu.count"),
|
||||
metric -> metric.hasName("jvm.cpu.recent_utilization"),
|
||||
metric -> metric.hasName("jvm.gc.duration"),
|
||||
metric -> metric.hasName("jvm.memory.used"),
|
||||
metric -> metric.hasName("jvm.memory.committed"),
|
||||
metric -> metric.hasName("jvm.memory.limit"),
|
||||
metric -> metric.hasName("jvm.memory.used_after_last_gc"),
|
||||
metric -> metric.hasName("jvm.thread.count"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ package io.opentelemetry.instrumentation.runtimemetrics.java17;
|
|||
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.BufferPools;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.Classes;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.Cpu;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.GarbageCollector;
|
||||
|
@ -106,7 +105,6 @@ public final class RuntimeMetricsBuilder {
|
|||
try {
|
||||
// Set up metrics gathered by JMX
|
||||
List<AutoCloseable> observables = new ArrayList<>();
|
||||
observables.addAll(BufferPools.registerObservers(openTelemetry));
|
||||
observables.addAll(Classes.registerObservers(openTelemetry));
|
||||
observables.addAll(Cpu.registerObservers(openTelemetry));
|
||||
observables.addAll(GarbageCollector.registerObservers(openTelemetry));
|
||||
|
|
|
@ -8,7 +8,6 @@ package io.opentelemetry.instrumentation.javaagent.runtimemetrics.java8;
|
|||
import com.google.auto.service.AutoService;
|
||||
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.BufferPools;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.Classes;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.Cpu;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.GarbageCollector;
|
||||
|
@ -41,7 +40,6 @@ public class Java8RuntimeMetricsInstaller implements AgentListener {
|
|||
|
||||
OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
|
||||
List<AutoCloseable> observables = new ArrayList<>();
|
||||
observables.addAll(BufferPools.registerObservers(openTelemetry));
|
||||
observables.addAll(Classes.registerObservers(openTelemetry));
|
||||
observables.addAll(Cpu.registerObservers(openTelemetry));
|
||||
observables.addAll(GarbageCollector.registerObservers(openTelemetry));
|
||||
|
|
|
@ -41,64 +41,45 @@ Threads.registerObservers(openTelemetry);
|
|||
GarbageCollector.registerObservers(openTelemetry);
|
||||
```
|
||||
|
||||
## Stable JVM metrics preview
|
||||
|
||||
If you want to enable the preview of the stable JVM semantic conventions, you need to set either
|
||||
the `otel.semconv-stability.opt-in` system property or the `OTEL_SEMCONV_STABILITY_OPT_IN`
|
||||
environment variable to one of the following values:
|
||||
|
||||
- `jvm` - this will make the runtime metrics emit only the new, stable conventions, and stop
|
||||
emitting the old experimental conventions that the instrumentation emitted previously.
|
||||
- `jvm/dup` - emit both the old and the stable JVM conventions, allowing for a seamless transition.
|
||||
|
||||
Note that the `otel.semconv-stability.opt-in` setting is a comma-separated list, and you can specify
|
||||
more than one value, e.g. `-Dotel.semconv-stability.opt-in=http,jvm`.
|
||||
|
||||
## Garbage Collector Dependent Metrics
|
||||
|
||||
The attributes reported on the memory metrics (`process.runtime.jvm.memory.*`) and gc metrics (`process.runtime.jvm.gc.*`) are dependent on the garbage collector used by the application, since each garbage collector organizes memory pools differently and has different strategies for reclaiming memory during garbage collection.
|
||||
The attributes reported on the memory metrics (`jvm.memory.*`) and gc metrics (`jvm.gc.*`) are dependent on the garbage collector used by the application, since each garbage collector organizes memory pools differently and has different strategies for reclaiming memory during garbage collection.
|
||||
|
||||
The following lists attributes reported for a variety of garbage collectors. Notice that attributes are not necessarily constant across `*.init`, `*.usage`, `*.committed`, and `*.limit` since not all memory pools report a limit.
|
||||
The following lists attributes reported for a variety of garbage collectors. Notice that attributes are not necessarily constant across `*.used`, `*.committed`, and `*.limit` since not all memory pools report a limit.
|
||||
|
||||
- CMS Garbage Collector
|
||||
- `process.runtime.jvm.memory.init`: {pool=Compressed Class Space,type=non_heap}, {pool=Par Eden Space,type=heap}, {pool=Tenured Gen,type=heap}, {pool=Par Survivor Space,type=heap}, {pool=Code Cache,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage`: {pool=Compressed Class Space,type=non_heap}, {pool=Par Eden Space,type=heap}, {pool=Tenured Gen,type=heap}, {pool=Par Survivor Space,type=heap}, {pool=Code Cache,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.committed`: {pool=Compressed Class Space,type=non_heap}, {pool=Par Eden Space,type=heap}, {pool=Tenured Gen,type=heap}, {pool=Par Survivor Space,type=heap}, {pool=Code Cache,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.limit`: {pool=Compressed Class Space,type=non_heap}, {pool=Par Eden Space,type=heap}, {pool=Tenured Gen,type=heap}, {pool=Par Survivor Space,type=heap}, {pool=Code Cache,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage_after_last_gc`: {pool=Par Eden Space,type=heap}, {pool=Tenured Gen,type=heap}, {pool=Par Survivor Space,type=heap}
|
||||
- `process.runtime.jvm.gc.duration`: {action=end of minor GC,gc=ParNew}, {action=end of major GC,gc=MarkSweepCompact}
|
||||
- `jvm.memory.used`: {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Par Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Tenured Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=Par Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Code Cache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.committed`: {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Par Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Tenured Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=Par Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Code Cache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.limit`: {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Par Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Tenured Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=Par Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Code Cache,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.used_after_last_gc`: {jvm.memory.pool.name=Par Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Tenured Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=Par Survivor Space,jvm.memory.type=heap}
|
||||
- `jvm.gc.duration`: {jvm.gc.action=end of minor GC,jvm.gc.name=ParNew}, {jvm.gc.action=end of major GC,jvm.gc.name=MarkSweepCompact}
|
||||
- G1 Garbage Collector
|
||||
- `process.runtime.jvm.memory.init`: {pool=G1 Survivor Space,type=heap}, {pool=G1 Eden Space,type=heap}, {pool=CodeCache,type=non_heap}, {pool=G1 Old Gen,type=heap}, {pool=Compressed Class Space,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage`: {pool=G1 Survivor Space,type=heap}, {pool=G1 Eden Space,type=heap}, {pool=CodeCache,type=non_heap}, {pool=G1 Old Gen,type=heap}, {pool=Compressed Class Space,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.committed`: {pool=G1 Survivor Space,type=heap}, {pool=G1 Eden Space,type=heap}, {pool=CodeCache,type=non_heap}, {pool=G1 Old Gen,type=heap}, {pool=Compressed Class Space,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.limit`: {pool=CodeCache,type=non_heap}, {pool=G1 Old Gen,type=heap}, {pool=Compressed Class Space,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage_after_last_gc`: {pool=G1 Survivor Space,type=heap}, {pool=G1 Eden Space,type=heap}, {pool=G1 Old Gen,type=heap}
|
||||
- `process.runtime.jvm.gc.duration`: {action=end of minor GC,gc=G1 Young Generation}, {action=end of major GC,gc=G1 Old Generation}
|
||||
- `jvm.memory.used`: {jvm.memory.pool.name=G1 Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=G1 Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=G1 Old Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.committed`: {jvm.memory.pool.name=G1 Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=G1 Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=G1 Old Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.limit`: {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=G1 Old Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.used_after_last_gc`: {jvm.memory.pool.name=G1 Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=G1 Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=G1 Old Gen,jvm.memory.type=heap}
|
||||
- `jvm.gc.duration`: {jvm.gc.action=end of minor GC,jvm.gc.name=G1 Young Generation}, {jvm.gc.action=end of major GC,jvm.gc.name=G1 Old Generation}
|
||||
- Parallel Garbage Collector
|
||||
- `process.runtime.jvm.memory.init`: {pool=CodeCache,type=non_heap}, {pool=PS Survivor Space,type=heap}, {pool=PS Old Gen,type=heap}, {pool=PS Eden Space,type=heap}, {pool=Compressed Class Space,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage`: {pool=CodeCache,type=non_heap}, {pool=PS Survivor Space,type=heap}, {pool=PS Old Gen,type=heap}, {pool=PS Eden Space,type=heap}, {pool=Compressed Class Space,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.committed`: {pool=CodeCache,type=non_heap}, {pool=PS Survivor Space,type=heap}, {pool=PS Old Gen,type=heap}, {pool=PS Eden Space,type=heap}, {pool=Compressed Class Space,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.limit`: {pool=CodeCache,type=non_heap}, {pool=PS Survivor Space,type=heap}, {pool=PS Old Gen,type=heap}, {pool=PS Eden Space,type=heap}, {pool=Compressed Class Space,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage_after_last_gc`: {pool=PS Survivor Space,type=heap}, {pool=PS Old Gen,type=heap}, {pool=PS Eden Space,type=heap}
|
||||
- `process.runtime.jvm.gc.duration`: {action=end of major GC,gc=PS MarkSweep}, {action=end of minor GC,gc=PS Scavenge}
|
||||
- `jvm.memory.used`: {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=PS Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=PS Old Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=PS Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.committed`: {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=PS Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=PS Old Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=PS Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.limit`: {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=PS Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=PS Old Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=PS Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.used_after_last_gc`: {jvm.memory.pool.name=PS Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=PS Old Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=PS Eden Space,jvm.memory.type=heap}
|
||||
- `jvm.gc.duration`: {jvm.gc.action=end of major GC,jvm.gc.name=PS MarkSweep}, {jvm.gc.action=end of minor GC,jvm.gc.name=PS Scavenge}
|
||||
- Serial Garbage Collector
|
||||
- `process.runtime.jvm.memory.init`: {pool=CodeCache,type=non_heap}, {pool=Tenured Gen,type=heap}, {pool=Eden Space,type=heap}, {pool=Survivor Space,type=heap}, {pool=Compressed Class Space,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage`: {pool=CodeCache,type=non_heap}, {pool=Tenured Gen,type=heap}, {pool=Eden Space,type=heap}, {pool=Survivor Space,type=heap}, {pool=Compressed Class Space,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.committed`: {pool=CodeCache,type=non_heap}, {pool=Tenured Gen,type=heap}, {pool=Eden Space,type=heap}, {pool=Survivor Space,type=heap}, {pool=Compressed Class Space,type=non_heap}, {pool=Metaspace,type=non_heap}
|
||||
- `process.runtime.jvm.memory.limit`: {pool=CodeCache,type=non_heap}, {pool=Tenured Gen,type=heap}, {pool=Eden Space,type=heap}, {pool=Survivor Space,type=heap}, {pool=Compressed Class Space,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage_after_last_gc`: {pool=Tenured Gen,type=heap}, {pool=Eden Space,type=heap}, {pool=Survivor Space,type=heap}
|
||||
- `process.runtime.jvm.gc.duration`: {action=end of minor GC,gc=Copy}, {action=end of major GC,gc=MarkSweepCompact}
|
||||
- `jvm.memory.used`: {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Tenured Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.committed`: {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Tenured Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.limit`: {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Tenured Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Survivor Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.used_after_last_gc`: {jvm.memory.pool.name=Tenured Gen,jvm.memory.type=heap}, {jvm.memory.pool.name=Eden Space,jvm.memory.type=heap}, {jvm.memory.pool.name=Survivor Space,jvm.memory.type=heap}
|
||||
- `jvm.gc.duration`: {jvm.gc.action=end of minor GC,jvm.gc.name=Copy}, {jvm.gc.action=end of major GC,jvm.gc.name=MarkSweepCompact}
|
||||
- Shenandoah Garbage Collector
|
||||
- `process.runtime.jvm.memory.init`: {pool=Metaspace,type=non_heap}, {pool=CodeCache,type=non_heap}, {pool=Shenandoah,type=heap}, {pool=Compressed Class Space,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage`: {pool=Metaspace,type=non_heap}, {pool=CodeCache,type=non_heap}, {pool=Shenandoah,type=heap}, {pool=Compressed Class Space,type=non_heap}
|
||||
- `process.runtime.jvm.memory.committed`: {pool=Metaspace,type=non_heap}, {pool=CodeCache,type=non_heap}, {pool=Shenandoah,type=heap}, {pool=Compressed Class Space,type=non_heap}
|
||||
- `process.runtime.jvm.memory.limit`: {pool=CodeCache,type=non_heap}, {pool=Shenandoah,type=heap}, {pool=Compressed Class Space,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage_after_last_gc`: {pool=Shenandoah,type=heap}
|
||||
- `process.runtime.jvm.gc.duration`: {action=end of GC cycle,gc=Shenandoah Cycles}, {action=end of GC pause,gc=Shenandoah Pauses}
|
||||
- `jvm.memory.used`: {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}, {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Shenandoah,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.committed`: {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}, {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Shenandoah,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.limit`: {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=Shenandoah,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.used_after_last_gc`: {jvm.memory.pool.name=Shenandoah,jvm.memory.type=heap}
|
||||
- `jvm.gc.duration`: {jvm.gc.action=end of GC cycle,jvm.gc.name=Shenandoah Cycles}, {jvm.gc.action=end of GC pause,jvm.gc.name=Shenandoah Pauses}
|
||||
- Z Garbage Collector
|
||||
- `process.runtime.jvm.memory.init`: {pool=Metaspace,type=non_heap}, {pool=CodeCache,type=non_heap}, {pool=ZHeap,type=heap}, {pool=Compressed Class Space,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage`: {pool=Metaspace,type=non_heap}, {pool=CodeCache,type=non_heap}, {pool=ZHeap,type=heap}, {pool=Compressed Class Space,type=non_heap}
|
||||
- `process.runtime.jvm.memory.committed`: {pool=Metaspace,type=non_heap}, {pool=CodeCache,type=non_heap}, {pool=ZHeap,type=heap}, {pool=Compressed Class Space,type=non_heap}
|
||||
- `process.runtime.jvm.memory.limit`: {pool=CodeCache,type=non_heap}, {pool=ZHeap,type=heap}, {pool=Compressed Class Space,type=non_heap}
|
||||
- `process.runtime.jvm.memory.usage_after_last_gc`: {pool=ZHeap,type=heap}
|
||||
- `process.runtime.jvm.gc.duration`: {action=end of GC cycle,gc=ZGC Cycles}, {action=end of GC pause,gc=ZGC Pauses}
|
||||
- `jvm.memory.used`: {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}, {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=ZHeap,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.committed`: {jvm.memory.pool.name=Metaspace,jvm.memory.type=non_heap}, {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=ZHeap,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.limit`: {jvm.memory.pool.name=CodeCache,jvm.memory.type=non_heap}, {jvm.memory.pool.name=ZHeap,jvm.memory.type=heap}, {jvm.memory.pool.name=Compressed Class Space,jvm.memory.type=non_heap}
|
||||
- `jvm.memory.used_after_last_gc`: {jvm.memory.pool.name=ZHeap,jvm.memory.type=heap}
|
||||
- `jvm.gc.duration`: {jvm.gc.action=end of GC cycle,jvm.gc.name=ZGC Cycles}, {jvm.gc.action=end of GC pause,jvm.gc.name=ZGC Pauses}
|
||||
|
|
|
@ -8,27 +8,3 @@ dependencies {
|
|||
|
||||
testImplementation(project(":testing-common"))
|
||||
}
|
||||
|
||||
testing {
|
||||
suites {
|
||||
val testStableSemconv by registering(JvmTestSuite::class) {
|
||||
dependencies {
|
||||
implementation(project())
|
||||
implementation(project(":testing-common"))
|
||||
}
|
||||
targets {
|
||||
all {
|
||||
testTask.configure {
|
||||
jvmArgs("-Dotel.semconv-stability.opt-in=jvm")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
check {
|
||||
dependsOn(testing.suites)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
|
||||
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil;
|
||||
import java.lang.management.BufferPoolMXBean;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Registers measurements that generate metrics about buffer pools.
|
||||
*
|
||||
* <p>Example usage:
|
||||
*
|
||||
* <pre>{@code
|
||||
* BufferPools.registerObservers(GlobalOpenTelemetry.get());
|
||||
* }</pre>
|
||||
*
|
||||
* <p>Example metrics being exported:
|
||||
*
|
||||
* <pre>
|
||||
* process.runtime.jvm.buffer.usage.usage{pool="buffer_pool"} 500
|
||||
* process.runtime.jvm.buffer.usage.max{pool="buffer_pool"} 1500
|
||||
* process.runtime.jvm.buffer.usage.count{pool="buffer_pool"} 15
|
||||
* </pre>
|
||||
*/
|
||||
public final class BufferPools {
|
||||
private static final AttributeKey<String> POOL_KEY = AttributeKey.stringKey("pool");
|
||||
|
||||
/** Register observers for java runtime buffer pool metrics. */
|
||||
public static List<AutoCloseable> registerObservers(OpenTelemetry openTelemetry) {
|
||||
List<BufferPoolMXBean> bufferBeans =
|
||||
ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
|
||||
return registerObservers(openTelemetry, bufferBeans);
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
static List<AutoCloseable> registerObservers(
|
||||
OpenTelemetry openTelemetry, List<BufferPoolMXBean> bufferBeans) {
|
||||
|
||||
// buffer pool metrics are experimental in the new semconv
|
||||
if (!SemconvStability.emitOldJvmSemconv()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<AutoCloseable> observables = new ArrayList<>();
|
||||
Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("process.runtime.jvm.buffer.usage")
|
||||
.setDescription("Memory that the Java virtual machine is using for this buffer pool")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(callback(bufferBeans, BufferPoolMXBean::getMemoryUsed)));
|
||||
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("process.runtime.jvm.buffer.limit")
|
||||
.setDescription("Total capacity of the buffers in this pool")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(callback(bufferBeans, BufferPoolMXBean::getTotalCapacity)));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("process.runtime.jvm.buffer.count")
|
||||
.setDescription("The number of buffers in the pool")
|
||||
.setUnit("{buffers}")
|
||||
.buildWithCallback(callback(bufferBeans, BufferPoolMXBean::getCount)));
|
||||
return observables;
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
static Consumer<ObservableLongMeasurement> callback(
|
||||
List<BufferPoolMXBean> bufferPools, Function<BufferPoolMXBean, Long> extractor) {
|
||||
List<Attributes> attributeSets = new ArrayList<>(bufferPools.size());
|
||||
for (BufferPoolMXBean pool : bufferPools) {
|
||||
attributeSets.add(Attributes.builder().put(POOL_KEY, pool.getName()).build());
|
||||
}
|
||||
return measurement -> {
|
||||
for (int i = 0; i < bufferPools.size(); i++) {
|
||||
Attributes attributes = attributeSets.get(i);
|
||||
long value = extractor.apply(bufferPools.get(i));
|
||||
if (value != -1) {
|
||||
measurement.record(value, attributes);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private BufferPools() {}
|
||||
}
|
|
@ -7,7 +7,6 @@ package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
|||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil;
|
||||
import java.lang.management.ClassLoadingMXBean;
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
@ -15,7 +14,10 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Registers measurements that generate metrics about JVM classes.
|
||||
* Registers measurements that generate metrics about JVM classes. The metrics generated by this
|
||||
* class follow <a
|
||||
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md">the
|
||||
* stable JVM metrics semantic conventions</a>.
|
||||
*
|
||||
* <p>Example usage:
|
||||
*
|
||||
|
@ -26,19 +28,6 @@ import java.util.List;
|
|||
* <p>Example metrics being exported:
|
||||
*
|
||||
* <pre>
|
||||
* process.runtime.jvm.classes.loaded 100
|
||||
* process.runtime.jvm.classes.unloaded 2
|
||||
* process.runtime.jvm.classes.current_loaded 98
|
||||
* </pre>
|
||||
*
|
||||
* <p>In case you enable the preview of stable JVM semantic conventions (e.g. by setting the {@code
|
||||
* otel.semconv-stability.opt-in} system property to {@code jvm}), the metrics being exported will
|
||||
* follow <a
|
||||
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md">the
|
||||
* most recent JVM semantic conventions</a>. This is how the example above looks when stable JVM
|
||||
* semconv is enabled:
|
||||
*
|
||||
* <pre>
|
||||
* jvm.class.loaded 100
|
||||
* jvm.class.unloaded 2
|
||||
* jvm.class.count 98
|
||||
|
@ -59,59 +48,30 @@ public final class Classes {
|
|||
Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
|
||||
List<AutoCloseable> observables = new ArrayList<>();
|
||||
|
||||
if (SemconvStability.emitOldJvmSemconv()) {
|
||||
observables.add(
|
||||
meter
|
||||
.counterBuilder("process.runtime.jvm.classes.loaded")
|
||||
.setDescription("Number of classes loaded since JVM start")
|
||||
.setUnit("{class}")
|
||||
.buildWithCallback(
|
||||
observableMeasurement ->
|
||||
observableMeasurement.record(classBean.getTotalLoadedClassCount())));
|
||||
observables.add(
|
||||
meter
|
||||
.counterBuilder("process.runtime.jvm.classes.unloaded")
|
||||
.setDescription("Number of classes unloaded since JVM start")
|
||||
.setUnit("{class}")
|
||||
.buildWithCallback(
|
||||
observableMeasurement ->
|
||||
observableMeasurement.record(classBean.getUnloadedClassCount())));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("process.runtime.jvm.classes.current_loaded")
|
||||
.setDescription("Number of classes currently loaded")
|
||||
.setUnit("{class}")
|
||||
.buildWithCallback(
|
||||
observableMeasurement ->
|
||||
observableMeasurement.record(classBean.getLoadedClassCount())));
|
||||
}
|
||||
|
||||
if (SemconvStability.emitStableJvmSemconv()) {
|
||||
observables.add(
|
||||
meter
|
||||
.counterBuilder("jvm.class.loaded")
|
||||
.setDescription("Number of classes loaded since JVM start.")
|
||||
.setUnit("{class}")
|
||||
.buildWithCallback(
|
||||
observableMeasurement ->
|
||||
observableMeasurement.record(classBean.getTotalLoadedClassCount())));
|
||||
observables.add(
|
||||
meter
|
||||
.counterBuilder("jvm.class.unloaded")
|
||||
.setDescription("Number of classes unloaded since JVM start.")
|
||||
.setUnit("{class}")
|
||||
.buildWithCallback(
|
||||
observableMeasurement ->
|
||||
observableMeasurement.record(classBean.getUnloadedClassCount())));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.class.count")
|
||||
.setDescription("Number of classes currently loaded.")
|
||||
.setUnit("{class}")
|
||||
.buildWithCallback(
|
||||
observableMeasurement ->
|
||||
observableMeasurement.record(classBean.getLoadedClassCount())));
|
||||
}
|
||||
observables.add(
|
||||
meter
|
||||
.counterBuilder("jvm.class.loaded")
|
||||
.setDescription("Number of classes loaded since JVM start.")
|
||||
.setUnit("{class}")
|
||||
.buildWithCallback(
|
||||
observableMeasurement ->
|
||||
observableMeasurement.record(classBean.getTotalLoadedClassCount())));
|
||||
observables.add(
|
||||
meter
|
||||
.counterBuilder("jvm.class.unloaded")
|
||||
.setDescription("Number of classes unloaded since JVM start.")
|
||||
.setUnit("{class}")
|
||||
.buildWithCallback(
|
||||
observableMeasurement ->
|
||||
observableMeasurement.record(classBean.getUnloadedClassCount())));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.class.count")
|
||||
.setDescription("Number of classes currently loaded.")
|
||||
.setUnit("{class}")
|
||||
.buildWithCallback(
|
||||
observableMeasurement ->
|
||||
observableMeasurement.record(classBean.getLoadedClassCount())));
|
||||
|
||||
return observables;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,8 @@ package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
|||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.CpuMethods;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -20,7 +17,10 @@ import java.util.function.Supplier;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Registers measurements that generate metrics about CPU.
|
||||
* Registers measurements that generate metrics about CPU. The metrics generated by this class
|
||||
* follow <a
|
||||
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md">the
|
||||
* stable JVM metrics semantic conventions</a>.
|
||||
*
|
||||
* <p>Example usage:
|
||||
*
|
||||
|
@ -31,19 +31,6 @@ import javax.annotation.Nullable;
|
|||
* <p>Example metrics being exported:
|
||||
*
|
||||
* <pre>
|
||||
* process.runtime.jvm.system.cpu.load_1m 2.2
|
||||
* process.runtime.jvm.system.cpu.utilization 0.15
|
||||
* process.runtime.jvm.cpu.utilization 0.1
|
||||
* </pre>
|
||||
*
|
||||
* <p>In case you enable the preview of stable JVM semantic conventions (e.g. by setting the {@code
|
||||
* otel.semconv-stability.opt-in} system property to {@code jvm}), the metrics being exported will
|
||||
* follow <a
|
||||
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md">the
|
||||
* most recent JVM semantic conventions</a>. This is how the example above looks when stable JVM
|
||||
* semconv is enabled:
|
||||
*
|
||||
* <pre>
|
||||
* jvm.cpu.time 20.42
|
||||
* jvm.cpu.count 8
|
||||
* jvm.cpu.recent_utilization 0.1
|
||||
|
@ -60,105 +47,58 @@ public final class Cpu {
|
|||
public static List<AutoCloseable> registerObservers(OpenTelemetry openTelemetry) {
|
||||
return INSTANCE.registerObservers(
|
||||
openTelemetry,
|
||||
ManagementFactory.getOperatingSystemMXBean(),
|
||||
Runtime.getRuntime()::availableProcessors,
|
||||
CpuMethods.processCpuTime(),
|
||||
CpuMethods.systemCpuUtilization(),
|
||||
CpuMethods.processCpuUtilization());
|
||||
}
|
||||
|
||||
// Visible for testing
|
||||
List<AutoCloseable> registerObservers(
|
||||
OpenTelemetry openTelemetry,
|
||||
OperatingSystemMXBean osBean,
|
||||
IntSupplier availableProcessors,
|
||||
@Nullable Supplier<Long> processCpuTime,
|
||||
@Nullable Supplier<Double> systemCpuUtilization,
|
||||
@Nullable Supplier<Double> processCpuUtilization) {
|
||||
Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
|
||||
List<AutoCloseable> observables = new ArrayList<>();
|
||||
|
||||
if (SemconvStability.emitOldJvmSemconv()) {
|
||||
if (processCpuTime != null) {
|
||||
observables.add(
|
||||
meter
|
||||
.gaugeBuilder("process.runtime.jvm.system.cpu.load_1m")
|
||||
.setDescription("Average CPU load of the whole system for the last minute")
|
||||
.setUnit("{run_queue_item}")
|
||||
.counterBuilder("jvm.cpu.time")
|
||||
.ofDoubles()
|
||||
.setDescription("CPU time used by the process as reported by the JVM.")
|
||||
.setUnit("s")
|
||||
.buildWithCallback(
|
||||
observableMeasurement -> {
|
||||
double loadAverage = osBean.getSystemLoadAverage();
|
||||
if (loadAverage >= 0) {
|
||||
observableMeasurement.record(loadAverage);
|
||||
Long cpuTimeNanos = processCpuTime.get();
|
||||
if (cpuTimeNanos != null && cpuTimeNanos >= 0) {
|
||||
observableMeasurement.record(cpuTimeNanos / NANOS_PER_S);
|
||||
}
|
||||
}));
|
||||
if (systemCpuUtilization != null) {
|
||||
observables.add(
|
||||
meter
|
||||
.gaugeBuilder("process.runtime.jvm.system.cpu.utilization")
|
||||
.setDescription("Recent cpu utilization for the whole system")
|
||||
.setUnit("1")
|
||||
.buildWithCallback(
|
||||
observableMeasurement -> {
|
||||
Double cpuUsage = systemCpuUtilization.get();
|
||||
if (cpuUsage != null && cpuUsage >= 0) {
|
||||
observableMeasurement.record(cpuUsage);
|
||||
}
|
||||
}));
|
||||
}
|
||||
if (processCpuUtilization != null) {
|
||||
observables.add(
|
||||
meter
|
||||
.gaugeBuilder("process.runtime.jvm.cpu.utilization")
|
||||
.setDescription("Recent cpu utilization for the process")
|
||||
.setUnit("1")
|
||||
.buildWithCallback(
|
||||
observableMeasurement -> {
|
||||
Double cpuUsage = processCpuUtilization.get();
|
||||
if (cpuUsage != null && cpuUsage >= 0) {
|
||||
observableMeasurement.record(cpuUsage);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
if (SemconvStability.emitStableJvmSemconv()) {
|
||||
if (processCpuTime != null) {
|
||||
observables.add(
|
||||
meter
|
||||
.counterBuilder("jvm.cpu.time")
|
||||
.ofDoubles()
|
||||
.setDescription("CPU time used by the process as reported by the JVM.")
|
||||
.setUnit("s")
|
||||
.buildWithCallback(
|
||||
observableMeasurement -> {
|
||||
Long cpuTimeNanos = processCpuTime.get();
|
||||
if (cpuTimeNanos != null && cpuTimeNanos >= 0) {
|
||||
observableMeasurement.record(cpuTimeNanos / NANOS_PER_S);
|
||||
}
|
||||
}));
|
||||
}
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.cpu.count")
|
||||
.setDescription("Number of processors available to the Java virtual machine.")
|
||||
.setUnit("{cpu}")
|
||||
.buildWithCallback(
|
||||
observableMeasurement ->
|
||||
observableMeasurement.record(availableProcessors.getAsInt())));
|
||||
if (processCpuUtilization != null) {
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.cpu.count")
|
||||
.setDescription("Number of processors available to the Java virtual machine.")
|
||||
.setUnit("{cpu}")
|
||||
.gaugeBuilder("jvm.cpu.recent_utilization")
|
||||
.setDescription("Recent CPU utilization for the process as reported by the JVM.")
|
||||
.setUnit("1")
|
||||
.buildWithCallback(
|
||||
observableMeasurement ->
|
||||
observableMeasurement.record(availableProcessors.getAsInt())));
|
||||
if (processCpuUtilization != null) {
|
||||
observables.add(
|
||||
meter
|
||||
.gaugeBuilder("jvm.cpu.recent_utilization")
|
||||
.setDescription("Recent CPU utilization for the process as reported by the JVM.")
|
||||
.setUnit("1")
|
||||
.buildWithCallback(
|
||||
observableMeasurement -> {
|
||||
Double cpuUsage = processCpuUtilization.get();
|
||||
if (cpuUsage != null && cpuUsage >= 0) {
|
||||
observableMeasurement.record(cpuUsage);
|
||||
}
|
||||
}));
|
||||
}
|
||||
observableMeasurement -> {
|
||||
Double cpuUsage = processCpuUtilization.get();
|
||||
if (cpuUsage != null && cpuUsage >= 0) {
|
||||
observableMeasurement.record(cpuUsage);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
return observables;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
|||
|
||||
import static io.opentelemetry.api.common.AttributeKey.stringKey;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
|
||||
import com.sun.management.GarbageCollectionNotificationInfo;
|
||||
|
@ -16,7 +15,6 @@ import io.opentelemetry.api.common.AttributeKey;
|
|||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.DoubleHistogram;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil;
|
||||
import java.lang.management.GarbageCollectorMXBean;
|
||||
import java.lang.management.ManagementFactory;
|
||||
|
@ -26,7 +24,6 @@ import java.util.List;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationEmitter;
|
||||
import javax.management.NotificationFilter;
|
||||
|
@ -34,7 +31,10 @@ import javax.management.NotificationListener;
|
|||
import javax.management.openmbean.CompositeData;
|
||||
|
||||
/**
|
||||
* Registers instruments that generate metrics about JVM garbage collection.
|
||||
* Registers instruments that generate metrics about JVM garbage collection. The metrics generated
|
||||
* by this class follow <a
|
||||
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md">the
|
||||
* stable JVM metrics semantic conventions</a>.
|
||||
*
|
||||
* <p>Example usage:
|
||||
*
|
||||
|
@ -45,17 +45,6 @@ import javax.management.openmbean.CompositeData;
|
|||
* <p>Example metrics being exported:
|
||||
*
|
||||
* <pre>
|
||||
* process.runtime.jvm.gc.duration{gc="G1 Young Generation",action="end of minor GC"} 0.022
|
||||
* </pre>
|
||||
*
|
||||
* <p>In case you enable the preview of stable JVM semantic conventions (e.g. by setting the {@code
|
||||
* otel.semconv-stability.opt-in} system property to {@code jvm}), the metrics being exported will
|
||||
* follow <a
|
||||
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md">the
|
||||
* most recent JVM semantic conventions</a>. This is how the example above looks when stable JVM
|
||||
* semconv is enabled:
|
||||
*
|
||||
* <pre>
|
||||
* jvm.gc.duration{jvm.gc.name="G1 Young Generation",jvm.gc.action="end of minor GC"} 0.022
|
||||
* </pre>
|
||||
*/
|
||||
|
@ -65,9 +54,6 @@ public final class GarbageCollector {
|
|||
|
||||
private static final double MILLIS_PER_S = TimeUnit.SECONDS.toMillis(1);
|
||||
|
||||
private static final AttributeKey<String> GC_KEY = stringKey("gc");
|
||||
private static final AttributeKey<String> ACTION_KEY = stringKey("action");
|
||||
|
||||
// TODO: use the opentelemetry-semconv classes once we have metrics attributes there
|
||||
private static final AttributeKey<String> JVM_GC_NAME = stringKey("jvm.gc.name");
|
||||
private static final AttributeKey<String> JVM_GC_ACTION = stringKey("jvm.gc.action");
|
||||
|
@ -101,27 +87,13 @@ public final class GarbageCollector {
|
|||
Function<Notification, GarbageCollectionNotificationInfo> notificationInfoExtractor) {
|
||||
Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
|
||||
|
||||
DoubleHistogram oldGcDuration = null;
|
||||
DoubleHistogram stableGcDuration = null;
|
||||
|
||||
if (SemconvStability.emitOldJvmSemconv()) {
|
||||
oldGcDuration =
|
||||
meter
|
||||
.histogramBuilder("process.runtime.jvm.gc.duration")
|
||||
.setDescription("Duration of JVM garbage collection actions")
|
||||
.setUnit("s")
|
||||
.setExplicitBucketBoundariesAdvice(emptyList())
|
||||
.build();
|
||||
}
|
||||
if (SemconvStability.emitStableJvmSemconv()) {
|
||||
stableGcDuration =
|
||||
meter
|
||||
.histogramBuilder("jvm.gc.duration")
|
||||
.setDescription("Duration of JVM garbage collection actions.")
|
||||
.setUnit("s")
|
||||
.setExplicitBucketBoundariesAdvice(GC_DURATION_BUCKETS)
|
||||
.build();
|
||||
}
|
||||
DoubleHistogram gcDuration =
|
||||
meter
|
||||
.histogramBuilder("jvm.gc.duration")
|
||||
.setDescription("Duration of JVM garbage collection actions.")
|
||||
.setUnit("s")
|
||||
.setExplicitBucketBoundariesAdvice(GC_DURATION_BUCKETS)
|
||||
.build();
|
||||
|
||||
List<AutoCloseable> result = new ArrayList<>();
|
||||
for (GarbageCollectorMXBean gcBean : gcBeans) {
|
||||
|
@ -130,7 +102,7 @@ public final class GarbageCollector {
|
|||
}
|
||||
NotificationEmitter notificationEmitter = (NotificationEmitter) gcBean;
|
||||
GcNotificationListener listener =
|
||||
new GcNotificationListener(oldGcDuration, stableGcDuration, notificationInfoExtractor);
|
||||
new GcNotificationListener(gcDuration, notificationInfoExtractor);
|
||||
notificationEmitter.addNotificationListener(listener, GC_FILTER, null);
|
||||
result.add(() -> notificationEmitter.removeNotificationListener(listener));
|
||||
}
|
||||
|
@ -139,17 +111,14 @@ public final class GarbageCollector {
|
|||
|
||||
private static final class GcNotificationListener implements NotificationListener {
|
||||
|
||||
@Nullable private final DoubleHistogram oldGcDuration;
|
||||
@Nullable private final DoubleHistogram stableGcDuration;
|
||||
private final DoubleHistogram gcDuration;
|
||||
private final Function<Notification, GarbageCollectionNotificationInfo>
|
||||
notificationInfoExtractor;
|
||||
|
||||
private GcNotificationListener(
|
||||
@Nullable DoubleHistogram oldGcDuration,
|
||||
@Nullable DoubleHistogram stableGcDuration,
|
||||
DoubleHistogram gcDuration,
|
||||
Function<Notification, GarbageCollectionNotificationInfo> notificationInfoExtractor) {
|
||||
this.oldGcDuration = oldGcDuration;
|
||||
this.stableGcDuration = stableGcDuration;
|
||||
this.gcDuration = gcDuration;
|
||||
this.notificationInfoExtractor = notificationInfoExtractor;
|
||||
}
|
||||
|
||||
|
@ -162,13 +131,7 @@ public final class GarbageCollector {
|
|||
String gcAction = notificationInfo.getGcAction();
|
||||
double duration = notificationInfo.getGcInfo().getDuration() / MILLIS_PER_S;
|
||||
|
||||
if (oldGcDuration != null) {
|
||||
oldGcDuration.record(duration, Attributes.of(GC_KEY, gcName, ACTION_KEY, gcAction));
|
||||
}
|
||||
if (stableGcDuration != null) {
|
||||
stableGcDuration.record(
|
||||
duration, Attributes.of(JVM_GC_NAME, gcName, JVM_GC_ACTION, gcAction));
|
||||
}
|
||||
gcDuration.record(duration, Attributes.of(JVM_GC_NAME, gcName, JVM_GC_ACTION, gcAction));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import io.opentelemetry.api.common.AttributeKey;
|
|||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
|
||||
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryPoolMXBean;
|
||||
|
@ -24,7 +23,10 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Registers measurements that generate metrics about JVM memory pools.
|
||||
* Registers measurements that generate metrics about JVM memory pools. The metrics generated by
|
||||
* this class follow <a
|
||||
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md">the
|
||||
* stable JVM metrics semantic conventions</a>.
|
||||
*
|
||||
* <p>Example usage:
|
||||
*
|
||||
|
@ -32,25 +34,7 @@ import java.util.function.Function;
|
|||
* MemoryPools.registerObservers(GlobalOpenTelemetry.get());
|
||||
* }</pre>
|
||||
*
|
||||
* <p>Example metrics being exported: Component
|
||||
*
|
||||
* <pre>
|
||||
* process.runtime.jvm.memory.init{type="heap",pool="G1 Eden Space"} 1000000
|
||||
* process.runtime.jvm.memory.usage{type="heap",pool="G1 Eden Space"} 2500000
|
||||
* process.runtime.jvm.memory.committed{type="heap",pool="G1 Eden Space"} 3000000
|
||||
* process.runtime.jvm.memory.limit{type="heap",pool="G1 Eden Space"} 4000000
|
||||
* process.runtime.jvm.memory.usage_after_last_gc{type="heap",pool="G1 Eden Space"} 1500000
|
||||
* process.runtime.jvm.memory.init{type="non_heap",pool="Metaspace"} 200
|
||||
* process.runtime.jvm.memory.usage{type="non_heap",pool="Metaspace"} 400
|
||||
* process.runtime.jvm.memory.committed{type="non_heap",pool="Metaspace"} 500
|
||||
* </pre>
|
||||
*
|
||||
* <p>In case you enable the preview of stable JVM semantic conventions (e.g. by setting the {@code
|
||||
* otel.semconv-stability.opt-in} system property to {@code jvm}), the metrics being exported will
|
||||
* follow <a
|
||||
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md">the
|
||||
* most recent JVM semantic conventions</a>. This is how the example above looks when stable JVM
|
||||
* semconv is enabled:
|
||||
* <p>Example metrics being exported:
|
||||
*
|
||||
* <pre>
|
||||
* jvm.memory.used{type="heap",pool="G1 Eden Space"} 2500000
|
||||
|
@ -63,9 +47,6 @@ import java.util.function.Function;
|
|||
*/
|
||||
public final class MemoryPools {
|
||||
|
||||
private static final AttributeKey<String> TYPE_KEY = stringKey("type");
|
||||
private static final AttributeKey<String> POOL_KEY = stringKey("pool");
|
||||
|
||||
// TODO: use the opentelemetry-semconv classes once we have metrics attributes there
|
||||
private static final AttributeKey<String> JVM_MEMORY_POOL_NAME =
|
||||
stringKey("jvm.memory.pool.name");
|
||||
|
@ -85,121 +66,55 @@ public final class MemoryPools {
|
|||
Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
|
||||
List<AutoCloseable> observables = new ArrayList<>();
|
||||
|
||||
if (SemconvStability.emitOldJvmSemconv()) {
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("process.runtime.jvm.memory.usage")
|
||||
.setDescription("Measure of memory used")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
POOL_KEY,
|
||||
TYPE_KEY,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getUsed)));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("process.runtime.jvm.memory.init")
|
||||
.setDescription("Measure of initial memory requested")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
POOL_KEY,
|
||||
TYPE_KEY,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getInit)));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("process.runtime.jvm.memory.committed")
|
||||
.setDescription("Measure of memory committed")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
POOL_KEY,
|
||||
TYPE_KEY,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getCommitted)));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("process.runtime.jvm.memory.limit")
|
||||
.setDescription("Measure of max obtainable memory")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
POOL_KEY,
|
||||
TYPE_KEY,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getMax)));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("process.runtime.jvm.memory.usage_after_last_gc")
|
||||
.setDescription(
|
||||
"Measure of memory used after the most recent garbage collection event on this pool")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
POOL_KEY,
|
||||
TYPE_KEY,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getCollectionUsage,
|
||||
MemoryUsage::getUsed)));
|
||||
}
|
||||
|
||||
if (SemconvStability.emitStableJvmSemconv()) {
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.memory.used")
|
||||
.setDescription("Measure of memory used.")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
JVM_MEMORY_POOL_NAME,
|
||||
JVM_MEMORY_TYPE,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getUsed)));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.memory.committed")
|
||||
.setDescription("Measure of memory committed.")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
JVM_MEMORY_POOL_NAME,
|
||||
JVM_MEMORY_TYPE,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getCommitted)));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.memory.limit")
|
||||
.setDescription("Measure of max obtainable memory.")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
JVM_MEMORY_POOL_NAME,
|
||||
JVM_MEMORY_TYPE,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getMax)));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.memory.used_after_last_gc")
|
||||
.setDescription(
|
||||
"Measure of memory used, as measured after the most recent garbage collection event on this pool.")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
JVM_MEMORY_POOL_NAME,
|
||||
JVM_MEMORY_TYPE,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getCollectionUsage,
|
||||
MemoryUsage::getUsed)));
|
||||
}
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.memory.used")
|
||||
.setDescription("Measure of memory used.")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
JVM_MEMORY_POOL_NAME,
|
||||
JVM_MEMORY_TYPE,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getUsed)));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.memory.committed")
|
||||
.setDescription("Measure of memory committed.")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
JVM_MEMORY_POOL_NAME,
|
||||
JVM_MEMORY_TYPE,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getCommitted)));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.memory.limit")
|
||||
.setDescription("Measure of max obtainable memory.")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
JVM_MEMORY_POOL_NAME,
|
||||
JVM_MEMORY_TYPE,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getMax)));
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.memory.used_after_last_gc")
|
||||
.setDescription(
|
||||
"Measure of memory used, as measured after the most recent garbage collection event on this pool.")
|
||||
.setUnit("By")
|
||||
.buildWithCallback(
|
||||
callback(
|
||||
JVM_MEMORY_POOL_NAME,
|
||||
JVM_MEMORY_TYPE,
|
||||
poolBeans,
|
||||
MemoryPoolMXBean::getCollectionUsage,
|
||||
MemoryUsage::getUsed)));
|
||||
|
||||
return observables;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import io.opentelemetry.api.common.AttributeKey;
|
|||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
|
||||
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
|
||||
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
@ -31,7 +30,10 @@ import java.util.function.Consumer;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Registers measurements that generate metrics about JVM threads.
|
||||
* Registers measurements that generate metrics about JVM threads. The metrics generated by this
|
||||
* class follow <a
|
||||
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md">the
|
||||
* stable JVM metrics semantic conventions</a>.
|
||||
*
|
||||
* <p>Example usage:
|
||||
*
|
||||
|
@ -42,18 +44,6 @@ import javax.annotation.Nullable;
|
|||
* <p>Example metrics being exported:
|
||||
*
|
||||
* <pre>
|
||||
* process.runtime.jvm.threads.count{daemon=true} 2
|
||||
* process.runtime.jvm.threads.count{daemon=false} 5
|
||||
* </pre>
|
||||
*
|
||||
* <p>In case you enable the preview of stable JVM semantic conventions (e.g. by setting the {@code
|
||||
* otel.semconv-stability.opt-in} system property to {@code jvm}), the metrics being exported will
|
||||
* follow <a
|
||||
* href="https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md">the
|
||||
* most recent JVM semantic conventions</a>. This is how the example above looks when stable JVM
|
||||
* semconv is enabled:
|
||||
*
|
||||
* <pre>
|
||||
* jvm.thread.count{jvm.thread.daemon=true,jvm.thread.state="waiting"} 1
|
||||
* jvm.thread.count{jvm.thread.daemon=true,jvm.thread.state="runnable"} 2
|
||||
* jvm.thread.count{jvm.thread.daemon=false,jvm.thread.state="waiting"} 2
|
||||
|
@ -65,8 +55,6 @@ public final class Threads {
|
|||
// Visible for testing
|
||||
static final Threads INSTANCE = new Threads();
|
||||
|
||||
static final AttributeKey<Boolean> DAEMON = booleanKey("daemon");
|
||||
|
||||
// TODO: use the opentelemetry-semconv classes once we have metrics attributes there
|
||||
static final AttributeKey<Boolean> JVM_THREAD_DAEMON = booleanKey("jvm.thread.daemon");
|
||||
static final AttributeKey<String> JVM_THREAD_STATE = stringKey("jvm.thread.state");
|
||||
|
@ -81,34 +69,13 @@ public final class Threads {
|
|||
Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
|
||||
List<AutoCloseable> observables = new ArrayList<>();
|
||||
|
||||
if (SemconvStability.emitOldJvmSemconv()) {
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("process.runtime.jvm.threads.count")
|
||||
.setDescription("Number of executing threads")
|
||||
.setUnit("{thread}")
|
||||
.buildWithCallback(
|
||||
observableMeasurement -> {
|
||||
int daemonThreadCount = threadBean.getDaemonThreadCount();
|
||||
observableMeasurement.record(
|
||||
daemonThreadCount, Attributes.builder().put(DAEMON, true).build());
|
||||
observableMeasurement.record(
|
||||
threadBean.getThreadCount() - daemonThreadCount,
|
||||
Attributes.builder().put(DAEMON, false).build());
|
||||
}));
|
||||
}
|
||||
|
||||
if (SemconvStability.emitStableJvmSemconv()) {
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.thread.count")
|
||||
.setDescription("Number of executing platform threads.")
|
||||
.setUnit("{thread}")
|
||||
.buildWithCallback(
|
||||
isJava9OrNewer()
|
||||
? java9AndNewerCallback(threadBean)
|
||||
: java8Callback(threadBean)));
|
||||
}
|
||||
observables.add(
|
||||
meter
|
||||
.upDownCounterBuilder("jvm.thread.count")
|
||||
.setDescription("Number of executing platform threads.")
|
||||
.setUnit("{thread}")
|
||||
.buildWithCallback(
|
||||
isJava9OrNewer() ? java9AndNewerCallback(threadBean) : java8Callback(threadBean)));
|
||||
|
||||
return observables;
|
||||
}
|
||||
|
|
|
@ -12,11 +12,9 @@ import io.opentelemetry.api.common.AttributeKey;
|
|||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
|
||||
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
|
||||
import java.lang.management.BufferPoolMXBean;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
@ -45,9 +43,6 @@ public final class ExperimentalBufferPools {
|
|||
static List<AutoCloseable> registerObservers(
|
||||
OpenTelemetry openTelemetry, List<BufferPoolMXBean> bufferBeans) {
|
||||
|
||||
if (!SemconvStability.emitStableJvmSemconv()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<AutoCloseable> observables = new ArrayList<>();
|
||||
Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
|
||||
observables.add(
|
||||
|
|
|
@ -5,11 +5,8 @@
|
|||
|
||||
package io.opentelemetry.instrumentation.runtimemetrics.java8.internal;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.util.ArrayList;
|
||||
|
@ -41,9 +38,6 @@ public final class ExperimentalCpu {
|
|||
OperatingSystemMXBean osBean,
|
||||
@Nullable Supplier<Double> systemCpuUtilization) {
|
||||
|
||||
if (!SemconvStability.emitStableJvmSemconv()) {
|
||||
return emptyList();
|
||||
}
|
||||
Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
|
||||
List<AutoCloseable> observables = new ArrayList<>();
|
||||
observables.add(
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package io.opentelemetry.instrumentation.runtimemetrics.java8.internal;
|
||||
|
||||
import static io.opentelemetry.api.common.AttributeKey.stringKey;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
import io.opentelemetry.api.OpenTelemetry;
|
||||
|
@ -14,7 +13,6 @@ import io.opentelemetry.api.common.AttributeKey;
|
|||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.api.metrics.Meter;
|
||||
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
|
||||
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryPoolMXBean;
|
||||
import java.lang.management.MemoryType;
|
||||
|
@ -50,10 +48,6 @@ public final class ExperimentalMemoryPools {
|
|||
static List<AutoCloseable> registerObservers(
|
||||
OpenTelemetry openTelemetry, List<MemoryPoolMXBean> poolBeans) {
|
||||
|
||||
if (!SemconvStability.emitStableJvmSemconv()) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
|
||||
return singletonList(
|
||||
meter
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
||||
|
||||
import static io.opentelemetry.instrumentation.runtimemetrics.java8.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;
|
||||
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)
|
||||
class BufferPoolsTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
|
||||
|
||||
@Spy private ObservableLongMeasurement measurement;
|
||||
@Mock private BufferPoolMXBean bufferPoolBean;
|
||||
private List<BufferPoolMXBean> beans;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
when(bufferPoolBean.getName()).thenReturn("buffer_pool_1");
|
||||
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-telemetry-java8",
|
||||
"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-telemetry-java8",
|
||||
"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-telemetry-java8",
|
||||
"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);
|
||||
Consumer<ObservableLongMeasurement> callback =
|
||||
BufferPools.callback(beans, BufferPoolMXBean::getMemoryUsed);
|
||||
callback.accept(measurement);
|
||||
verify(measurement).record(1, Attributes.builder().put("pool", "buffer_pool_1").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
void callback_SkipRecord() {
|
||||
when(bufferPoolBean.getMemoryUsed()).thenReturn(-1L);
|
||||
Consumer<ObservableLongMeasurement> callback =
|
||||
BufferPools.callback(beans, BufferPoolMXBean::getMemoryUsed);
|
||||
callback.accept(measurement);
|
||||
verify(measurement, never()).record(eq(-1), any());
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
||||
|
||||
import static io.opentelemetry.instrumentation.runtimemetrics.java8.ScopeUtil.EXPECTED_SCOPE;
|
||||
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.ClassLoadingMXBean;
|
||||
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 ClassesTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
|
||||
|
||||
@Mock private ClassLoadingMXBean classBean;
|
||||
|
||||
@Test
|
||||
void registerObservers() {
|
||||
when(classBean.getTotalLoadedClassCount()).thenReturn(3L);
|
||||
when(classBean.getUnloadedClassCount()).thenReturn(2L);
|
||||
when(classBean.getLoadedClassCount()).thenReturn(1);
|
||||
|
||||
Classes.INSTANCE.registerObservers(testing.getOpenTelemetry(), classBean);
|
||||
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"process.runtime.jvm.classes.loaded",
|
||||
metrics ->
|
||||
metrics.anySatisfy(
|
||||
metricData ->
|
||||
assertThat(metricData)
|
||||
.hasInstrumentationScope(EXPECTED_SCOPE)
|
||||
.hasDescription("Number of classes loaded since JVM start")
|
||||
.hasUnit("{class}")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasValue(3).hasAttributes(Attributes.empty())))));
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"process.runtime.jvm.classes.unloaded",
|
||||
metrics ->
|
||||
metrics.anySatisfy(
|
||||
metricData ->
|
||||
assertThat(metricData)
|
||||
.hasInstrumentationScope(EXPECTED_SCOPE)
|
||||
.hasDescription("Number of classes unloaded since JVM start")
|
||||
.hasUnit("{class}")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasValue(2).hasAttributes(Attributes.empty())))));
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"process.runtime.jvm.classes.current_loaded",
|
||||
metrics ->
|
||||
metrics.anySatisfy(
|
||||
metricData ->
|
||||
assertThat(metricData)
|
||||
.hasInstrumentationScope(EXPECTED_SCOPE)
|
||||
.hasDescription("Number of classes currently loaded")
|
||||
.hasUnit("{class}")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point.hasValue(1).hasAttributes(Attributes.empty())))));
|
||||
}
|
||||
}
|
|
@ -28,12 +28,7 @@ class CpuStableSemconvTest {
|
|||
Supplier<Double> processCpuUtilization = () -> 0.05;
|
||||
|
||||
Cpu.INSTANCE.registerObservers(
|
||||
testing.getOpenTelemetry(),
|
||||
null,
|
||||
availableProcessors,
|
||||
processCpuTime,
|
||||
() -> null,
|
||||
processCpuUtilization);
|
||||
testing.getOpenTelemetry(), availableProcessors, processCpuTime, processCpuUtilization);
|
||||
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
||||
|
||||
import static io.opentelemetry.instrumentation.runtimemetrics.java8.ScopeUtil.EXPECTED_SCOPE;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.util.function.Supplier;
|
||||
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 CpuTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
|
||||
|
||||
@Mock private OperatingSystemMXBean osBean;
|
||||
|
||||
@Test
|
||||
void registerObservers() {
|
||||
when(osBean.getSystemLoadAverage()).thenReturn(2.2);
|
||||
Supplier<Double> systemCpuUsage = () -> 0.11;
|
||||
Supplier<Double> processCpuUsage = () -> 0.05;
|
||||
|
||||
Cpu.INSTANCE.registerObservers(
|
||||
testing.getOpenTelemetry(), osBean, () -> 0, () -> null, systemCpuUsage, processCpuUsage);
|
||||
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"process.runtime.jvm.system.cpu.load_1m",
|
||||
metrics ->
|
||||
metrics.anySatisfy(
|
||||
metricData ->
|
||||
assertThat(metricData)
|
||||
.hasInstrumentationScope(EXPECTED_SCOPE)
|
||||
.hasDescription("Average CPU load of the whole system for the last minute")
|
||||
.hasUnit("{run_queue_item}")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge -> gauge.hasPointsSatisfying(point -> point.hasValue(2.2)))));
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"process.runtime.jvm.system.cpu.utilization",
|
||||
metrics ->
|
||||
metrics.anySatisfy(
|
||||
metricData ->
|
||||
assertThat(metricData)
|
||||
.hasInstrumentationScope(EXPECTED_SCOPE)
|
||||
.hasDescription("Recent cpu utilization for the whole system")
|
||||
.hasUnit("1")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge -> gauge.hasPointsSatisfying(point -> point.hasValue(0.11)))));
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"process.runtime.jvm.cpu.utilization",
|
||||
metrics ->
|
||||
metrics.anySatisfy(
|
||||
metricData ->
|
||||
assertThat(metricData)
|
||||
.hasInstrumentationScope(EXPECTED_SCOPE)
|
||||
.hasDescription("Recent cpu utilization for the process")
|
||||
.hasUnit("1")
|
||||
.hasDoubleGaugeSatisfying(
|
||||
gauge -> gauge.hasPointsSatisfying(point -> point.hasValue(0.05)))));
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
|||
|
||||
import static io.opentelemetry.instrumentation.runtimemetrics.java8.ScopeUtil.EXPECTED_SCOPE;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
@ -18,7 +19,6 @@ import io.opentelemetry.api.common.Attributes;
|
|||
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
|
||||
import java.lang.management.GarbageCollectorMXBean;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationEmitter;
|
||||
|
@ -37,6 +37,9 @@ import org.mockito.quality.Strictness;
|
|||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
class GarbageCollectorTest {
|
||||
|
||||
static final double[] GC_DURATION_BUCKETS =
|
||||
GarbageCollector.GC_DURATION_BUCKETS.stream().mapToDouble(d -> d).toArray();
|
||||
|
||||
@RegisterExtension
|
||||
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
|
||||
|
||||
|
@ -49,7 +52,7 @@ class GarbageCollectorTest {
|
|||
void registerObservers() {
|
||||
GarbageCollector.registerObservers(
|
||||
testing.getOpenTelemetry(),
|
||||
Collections.singletonList(gcBean),
|
||||
singletonList(gcBean),
|
||||
GarbageCollectorTest::getGcNotificationInfo);
|
||||
|
||||
NotificationEmitter notificationEmitter = (NotificationEmitter) gcBean;
|
||||
|
@ -65,13 +68,13 @@ class GarbageCollectorTest {
|
|||
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"process.runtime.jvm.gc.duration",
|
||||
"jvm.gc.duration",
|
||||
metrics ->
|
||||
metrics.anySatisfy(
|
||||
metricData ->
|
||||
assertThat(metricData)
|
||||
.hasInstrumentationScope(EXPECTED_SCOPE)
|
||||
.hasDescription("Duration of JVM garbage collection actions")
|
||||
.hasDescription("Duration of JVM garbage collection actions.")
|
||||
.hasUnit("s")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
|
@ -82,20 +85,20 @@ class GarbageCollectorTest {
|
|||
.hasSum(0.022)
|
||||
.hasAttributes(
|
||||
Attributes.builder()
|
||||
.put("gc", "G1 Young Generation")
|
||||
.put("action", "end of minor GC")
|
||||
.put("jvm.gc.name", "G1 Young Generation")
|
||||
.put("jvm.gc.action", "end of minor GC")
|
||||
.build())
|
||||
.hasBucketBoundaries(),
|
||||
.hasBucketBoundaries(GC_DURATION_BUCKETS),
|
||||
point ->
|
||||
point
|
||||
.hasCount(1)
|
||||
.hasSum(0.011)
|
||||
.hasAttributes(
|
||||
Attributes.builder()
|
||||
.put("gc", "G1 Old Generation")
|
||||
.put("action", "end of major GC")
|
||||
.put("jvm.gc.name", "G1 Old Generation")
|
||||
.put("jvm.gc.action", "end of major GC")
|
||||
.build())
|
||||
.hasBucketBoundaries()))));
|
||||
.hasBucketBoundaries(GC_DURATION_BUCKETS)))));
|
||||
}
|
||||
|
||||
private static Notification createTestNotification(
|
||||
|
|
|
@ -1,257 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
||||
|
||||
import static io.opentelemetry.api.common.AttributeKey.stringKey;
|
||||
import static io.opentelemetry.instrumentation.runtimemetrics.java8.ScopeUtil.EXPECTED_SCOPE;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
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.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;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
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;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
class MemoryPoolsTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
|
||||
|
||||
@Spy private ObservableLongMeasurement measurement;
|
||||
|
||||
@Mock private MemoryPoolMXBean heapPoolBean;
|
||||
@Mock private MemoryPoolMXBean nonHeapPoolBean;
|
||||
|
||||
@Mock private MemoryUsage heapPoolUsage;
|
||||
@Mock private MemoryUsage nonHeapUsage;
|
||||
@Mock private MemoryUsage heapCollectionUsage;
|
||||
@Mock private MemoryUsage nonHeapCollectionUsage;
|
||||
|
||||
private List<MemoryPoolMXBean> beans;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
when(heapPoolBean.getName()).thenReturn("heap_pool");
|
||||
when(heapPoolBean.getType()).thenReturn(MemoryType.HEAP);
|
||||
when(heapPoolBean.getUsage()).thenReturn(heapPoolUsage);
|
||||
when(heapPoolBean.getCollectionUsage()).thenReturn(heapCollectionUsage);
|
||||
when(nonHeapPoolBean.getName()).thenReturn("non_heap_pool");
|
||||
when(nonHeapPoolBean.getType()).thenReturn(MemoryType.NON_HEAP);
|
||||
when(nonHeapPoolBean.getUsage()).thenReturn(nonHeapUsage);
|
||||
when(nonHeapPoolBean.getCollectionUsage()).thenReturn(nonHeapCollectionUsage);
|
||||
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);
|
||||
when(heapCollectionUsage.getUsed()).thenReturn(18L);
|
||||
when(nonHeapCollectionUsage.getUsed()).thenReturn(19L);
|
||||
MemoryPools.registerObservers(testing.getOpenTelemetry(), beans);
|
||||
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"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(stringKey("pool"), "heap_pool")
|
||||
.hasAttribute(stringKey("type"), "heap"),
|
||||
point ->
|
||||
point
|
||||
.hasValue(14)
|
||||
.hasAttribute(stringKey("pool"), "non_heap_pool")
|
||||
.hasAttribute(stringKey("type"), "non_heap")))));
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"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(stringKey("pool"), "heap_pool")
|
||||
.hasAttribute(stringKey("type"), "heap"),
|
||||
point ->
|
||||
point
|
||||
.hasValue(15)
|
||||
.hasAttribute(stringKey("pool"), "non_heap_pool")
|
||||
.hasAttribute(stringKey("type"), "non_heap")))));
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"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(stringKey("pool"), "heap_pool")
|
||||
.hasAttribute(stringKey("type"), "heap"),
|
||||
point ->
|
||||
point
|
||||
.hasValue(16)
|
||||
.hasAttribute(stringKey("pool"), "non_heap_pool")
|
||||
.hasAttribute(stringKey("type"), "non_heap")))));
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"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(stringKey("pool"), "heap_pool")
|
||||
.hasAttribute(stringKey("type"), "heap"),
|
||||
point ->
|
||||
point
|
||||
.hasValue(17)
|
||||
.hasAttribute(stringKey("pool"), "non_heap_pool")
|
||||
.hasAttribute(stringKey("type"), "non_heap")))));
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"process.runtime.jvm.memory.usage_after_last_gc",
|
||||
metrics ->
|
||||
metrics.anySatisfy(
|
||||
metricData ->
|
||||
assertThat(metricData)
|
||||
.hasInstrumentationScope(EXPECTED_SCOPE)
|
||||
.hasDescription(
|
||||
"Measure of memory used after the most recent garbage collection event on this pool")
|
||||
.hasUnit("By")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(18)
|
||||
.hasAttribute(stringKey("pool"), "heap_pool")
|
||||
.hasAttribute(stringKey("type"), "heap"),
|
||||
point ->
|
||||
point
|
||||
.hasValue(19)
|
||||
.hasAttribute(stringKey("pool"), "non_heap_pool")
|
||||
.hasAttribute(stringKey("type"), "non_heap")))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void callback_Records() {
|
||||
when(heapPoolUsage.getUsed()).thenReturn(1L);
|
||||
when(nonHeapUsage.getUsed()).thenReturn(2L);
|
||||
|
||||
Consumer<ObservableLongMeasurement> callback =
|
||||
MemoryPools.callback(
|
||||
stringKey("pool"),
|
||||
stringKey("type"),
|
||||
beans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getUsed);
|
||||
callback.accept(measurement);
|
||||
|
||||
verify(measurement)
|
||||
.record(1, Attributes.builder().put("pool", "heap_pool").put("type", "heap").build());
|
||||
verify(measurement)
|
||||
.record(
|
||||
2, Attributes.builder().put("pool", "non_heap_pool").put("type", "non_heap").build());
|
||||
}
|
||||
|
||||
@Test
|
||||
void callback_SkipRecord() {
|
||||
when(heapPoolUsage.getMax()).thenReturn(1L);
|
||||
when(nonHeapUsage.getMax()).thenReturn(-1L);
|
||||
|
||||
Consumer<ObservableLongMeasurement> callback =
|
||||
MemoryPools.callback(
|
||||
stringKey("pool"),
|
||||
stringKey("type"),
|
||||
beans,
|
||||
MemoryPoolMXBean::getUsage,
|
||||
MemoryUsage::getMax);
|
||||
callback.accept(measurement);
|
||||
|
||||
verify(measurement)
|
||||
.record(1, Attributes.builder().put("pool", "heap_pool").put("type", "heap").build());
|
||||
verify(measurement, never()).record(eq(-1), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void callback_NullUsage() {
|
||||
when(heapPoolBean.getCollectionUsage()).thenReturn(null);
|
||||
|
||||
Consumer<ObservableLongMeasurement> callback =
|
||||
MemoryPools.callback(
|
||||
stringKey("pool"),
|
||||
stringKey("type"),
|
||||
singletonList(heapPoolBean),
|
||||
MemoryPoolMXBean::getCollectionUsage,
|
||||
MemoryUsage::getUsed);
|
||||
callback.accept(measurement);
|
||||
verify(measurement, never()).record(anyLong(), any());
|
||||
}
|
||||
}
|
|
@ -10,14 +10,15 @@ import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
|||
import io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
class ScopeUtil {
|
||||
public final class ScopeUtil {
|
||||
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.runtime-telemetry-java8";
|
||||
|
||||
@Nullable
|
||||
private static final String INSTRUMENTATION_VERSION =
|
||||
EmbeddedInstrumentationProperties.findVersion(INSTRUMENTATION_NAME);
|
||||
|
||||
static final InstrumentationScopeInfo EXPECTED_SCOPE;
|
||||
public static final InstrumentationScopeInfo EXPECTED_SCOPE;
|
||||
|
||||
static {
|
||||
InstrumentationScopeInfoBuilder builder =
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
||||
|
||||
import static io.opentelemetry.instrumentation.runtimemetrics.java8.ScopeUtil.EXPECTED_SCOPE;
|
||||
import static io.opentelemetry.instrumentation.runtimemetrics.java8.Threads.DAEMON;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
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(7);
|
||||
when(threadBean.getDaemonThreadCount()).thenReturn(2);
|
||||
|
||||
Threads.INSTANCE.registerObservers(testing.getOpenTelemetry(), threadBean);
|
||||
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"process.runtime.jvm.threads.count",
|
||||
metrics ->
|
||||
metrics.anySatisfy(
|
||||
metricData ->
|
||||
assertThat(metricData)
|
||||
.hasInstrumentationScope(EXPECTED_SCOPE)
|
||||
.hasDescription("Number of executing threads")
|
||||
.hasUnit("{thread}")
|
||||
.hasLongSumSatisfying(
|
||||
sum ->
|
||||
sum.isNotMonotonic()
|
||||
.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasValue(2)
|
||||
.hasAttributesSatisfying(equalTo(DAEMON, true)),
|
||||
point ->
|
||||
point
|
||||
.hasValue(5)
|
||||
.hasAttributesSatisfying(
|
||||
equalTo(DAEMON, false))))));
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
||||
|
||||
import static io.opentelemetry.instrumentation.runtimemetrics.java8.ScopeUtil.EXPECTED_SCOPE;
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.sun.management.GarbageCollectionNotificationInfo;
|
||||
import com.sun.management.GcInfo;
|
||||
import io.opentelemetry.api.common.Attributes;
|
||||
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
|
||||
import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
|
||||
import java.lang.management.GarbageCollectorMXBean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationEmitter;
|
||||
import javax.management.NotificationListener;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
class GarbageCollectorTest {
|
||||
|
||||
static final double[] GC_DURATION_BUCKETS =
|
||||
GarbageCollector.GC_DURATION_BUCKETS.stream().mapToDouble(d -> d).toArray();
|
||||
|
||||
@RegisterExtension
|
||||
static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
|
||||
|
||||
@Mock(extraInterfaces = NotificationEmitter.class)
|
||||
private GarbageCollectorMXBean gcBean;
|
||||
|
||||
@Captor private ArgumentCaptor<NotificationListener> listenerCaptor;
|
||||
|
||||
@Test
|
||||
void registerObservers() {
|
||||
GarbageCollector.registerObservers(
|
||||
testing.getOpenTelemetry(),
|
||||
singletonList(gcBean),
|
||||
GarbageCollectorTest::getGcNotificationInfo);
|
||||
|
||||
NotificationEmitter notificationEmitter = (NotificationEmitter) gcBean;
|
||||
verify(notificationEmitter).addNotificationListener(listenerCaptor.capture(), any(), any());
|
||||
NotificationListener listener = listenerCaptor.getValue();
|
||||
|
||||
listener.handleNotification(
|
||||
createTestNotification("G1 Young Generation", "end of minor GC", 10), null);
|
||||
listener.handleNotification(
|
||||
createTestNotification("G1 Young Generation", "end of minor GC", 12), null);
|
||||
listener.handleNotification(
|
||||
createTestNotification("G1 Old Generation", "end of major GC", 11), null);
|
||||
|
||||
testing.waitAndAssertMetrics(
|
||||
"io.opentelemetry.runtime-telemetry-java8",
|
||||
"jvm.gc.duration",
|
||||
metrics ->
|
||||
metrics.anySatisfy(
|
||||
metricData ->
|
||||
assertThat(metricData)
|
||||
.hasInstrumentationScope(EXPECTED_SCOPE)
|
||||
.hasDescription("Duration of JVM garbage collection actions.")
|
||||
.hasUnit("s")
|
||||
.hasHistogramSatisfying(
|
||||
histogram ->
|
||||
histogram.hasPointsSatisfying(
|
||||
point ->
|
||||
point
|
||||
.hasCount(2)
|
||||
.hasSum(0.022)
|
||||
.hasAttributes(
|
||||
Attributes.builder()
|
||||
.put("jvm.gc.name", "G1 Young Generation")
|
||||
.put("jvm.gc.action", "end of minor GC")
|
||||
.build())
|
||||
.hasBucketBoundaries(GC_DURATION_BUCKETS),
|
||||
point ->
|
||||
point
|
||||
.hasCount(1)
|
||||
.hasSum(0.011)
|
||||
.hasAttributes(
|
||||
Attributes.builder()
|
||||
.put("jvm.gc.name", "G1 Old Generation")
|
||||
.put("jvm.gc.action", "end of major GC")
|
||||
.build())
|
||||
.hasBucketBoundaries(GC_DURATION_BUCKETS)))));
|
||||
}
|
||||
|
||||
private static Notification createTestNotification(
|
||||
String gcName, String gcAction, long duration) {
|
||||
GarbageCollectionNotificationInfo gcNotificationInfo =
|
||||
mock(GarbageCollectionNotificationInfo.class);
|
||||
when(gcNotificationInfo.getGcName()).thenReturn(gcName);
|
||||
when(gcNotificationInfo.getGcAction()).thenReturn(gcAction);
|
||||
GcInfo gcInfo = mock(GcInfo.class);
|
||||
when(gcInfo.getDuration()).thenReturn(duration);
|
||||
when(gcNotificationInfo.getGcInfo()).thenReturn(gcInfo);
|
||||
return new TestNotification(gcNotificationInfo);
|
||||
}
|
||||
|
||||
private static GarbageCollectionNotificationInfo getGcNotificationInfo(
|
||||
Notification notification) {
|
||||
return ((TestNotification) notification).gcNotificationInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link Notification} when is initialized with a mock {@link
|
||||
* GarbageCollectionNotificationInfo}.
|
||||
*/
|
||||
private static class TestNotification extends Notification {
|
||||
|
||||
private static final AtomicLong sequence = new AtomicLong(0);
|
||||
|
||||
private final GarbageCollectionNotificationInfo gcNotificationInfo;
|
||||
|
||||
private TestNotification(GarbageCollectionNotificationInfo gcNotificationInfo) {
|
||||
super(
|
||||
GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION,
|
||||
"test",
|
||||
sequence.incrementAndGet());
|
||||
this.gcNotificationInfo = gcNotificationInfo;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.instrumentation.runtimemetrics.java8;
|
||||
|
||||
import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
|
||||
import io.opentelemetry.sdk.common.InstrumentationScopeInfoBuilder;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class ScopeUtil {
|
||||
|
||||
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.runtime-telemetry-java8";
|
||||
|
||||
@Nullable
|
||||
private static final String INSTRUMENTATION_VERSION =
|
||||
EmbeddedInstrumentationProperties.findVersion(INSTRUMENTATION_NAME);
|
||||
|
||||
public static final InstrumentationScopeInfo EXPECTED_SCOPE;
|
||||
|
||||
static {
|
||||
InstrumentationScopeInfoBuilder builder =
|
||||
InstrumentationScopeInfo.builder(INSTRUMENTATION_NAME);
|
||||
if (INSTRUMENTATION_VERSION != null) {
|
||||
builder.setVersion(INSTRUMENTATION_VERSION);
|
||||
}
|
||||
EXPECTED_SCOPE = builder.build();
|
||||
}
|
||||
|
||||
private ScopeUtil() {}
|
||||
}
|
|
@ -44,7 +44,7 @@ class PrometheusSmokeTest extends SmokeTest {
|
|||
def prometheusClient = WebClient.of("h1c://localhost:${containerManager.getTargetMappedPort(9090)}")
|
||||
def prometheusData = prometheusClient.get("/").aggregate().join().contentUtf8()
|
||||
|
||||
prometheusData.contains("process_runtime_jvm_memory_usage")
|
||||
prometheusData.contains("jvm_memory_used")
|
||||
|
||||
cleanup:
|
||||
stopTarget()
|
||||
|
|
|
@ -82,10 +82,10 @@ class SpringBootSmokeTest extends SmokeTest {
|
|||
|
||||
then: "JVM metrics are exported"
|
||||
def metrics = new MetricsInspector(waitForMetrics())
|
||||
metrics.hasMetricsNamed("process.runtime.jvm.memory.init")
|
||||
metrics.hasMetricsNamed("process.runtime.jvm.memory.usage")
|
||||
metrics.hasMetricsNamed("process.runtime.jvm.memory.committed")
|
||||
metrics.hasMetricsNamed("process.runtime.jvm.memory.limit")
|
||||
metrics.hasMetricsNamed("jvm.memory.used")
|
||||
metrics.hasMetricsNamed("jvm.memory.committed")
|
||||
metrics.hasMetricsNamed("jvm.memory.limit")
|
||||
metrics.hasMetricsNamed("jvm.memory.used_after_last_gc")
|
||||
|
||||
then: "service name is autodetected"
|
||||
def serviceName = findResourceAttribute(traces, "service.name")
|
||||
|
|
Loading…
Reference in New Issue