Skip to content

Commit 5d007bb

Browse files
author
Mateusz Rzeszutek
authored
Stable JVM semconv implementation: the rest (open-telemetry#9896)
1 parent 683c311 commit 5d007bb

File tree

21 files changed

+1360
-190
lines changed

21 files changed

+1360
-190
lines changed

instrumentation/runtime-telemetry/runtime-telemetry-java17/javaagent/src/main/java/io/opentelemetry/instrumentation/javaagent/runtimemetrics/java17/Java17RuntimeMetricsInstaller.java

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import io.opentelemetry.api.GlobalOpenTelemetry;
1010
import io.opentelemetry.api.OpenTelemetry;
1111
import io.opentelemetry.instrumentation.runtimemetrics.java17.RuntimeMetrics;
12+
import io.opentelemetry.instrumentation.runtimemetrics.java17.RuntimeMetricsBuilder;
1213
import io.opentelemetry.javaagent.extension.AgentListener;
1314
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
1415
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
@@ -23,24 +24,29 @@ public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
2324
ConfigProperties config = AutoConfigureUtil.getConfig(autoConfiguredSdk);
2425

2526
OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
26-
RuntimeMetrics runtimeMetrics = null;
27+
RuntimeMetricsBuilder builder = null;
2728
/*
2829
By default don't use any JFR metrics. May change this once semantic conventions are updated.
2930
If enabled, default to only the metrics not already covered by runtime-telemetry-java8
3031
*/
3132
boolean defaultEnabled = config.getBoolean("otel.instrumentation.common.default-enabled", true);
3233
if (config.getBoolean("otel.instrumentation.runtime-telemetry-java17.enable-all", false)) {
33-
runtimeMetrics = RuntimeMetrics.builder(openTelemetry).enableAllFeatures().build();
34+
builder = RuntimeMetrics.builder(openTelemetry).enableAllFeatures();
3435
} else if (config.getBoolean("otel.instrumentation.runtime-telemetry-java17.enabled", false)) {
35-
runtimeMetrics = RuntimeMetrics.create(openTelemetry);
36+
builder = RuntimeMetrics.builder(openTelemetry);
3637
} else if (config.getBoolean(
3738
"otel.instrumentation.runtime-telemetry.enabled", defaultEnabled)) {
3839
// This only uses metrics gathered by JMX
39-
runtimeMetrics = RuntimeMetrics.builder(openTelemetry).disableAllFeatures().build();
40+
builder = RuntimeMetrics.builder(openTelemetry).disableAllFeatures();
4041
}
4142

42-
if (runtimeMetrics != null) {
43-
RuntimeMetrics finalJfrTelemetry = runtimeMetrics;
43+
if (builder != null) {
44+
if (config.getBoolean(
45+
"otel.instrumentation.runtime-telemetry.emit-experimental-telemetry", false)) {
46+
builder.enableExperimentalJmxTelemetry();
47+
}
48+
49+
RuntimeMetrics finalJfrTelemetry = builder.build();
4450
Thread cleanupTelemetry = new Thread(() -> finalJfrTelemetry.close());
4551
Runtime.getRuntime().addShutdownHook(cleanupTelemetry);
4652
}

instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
import io.opentelemetry.instrumentation.runtimemetrics.java8.GarbageCollector;
1414
import io.opentelemetry.instrumentation.runtimemetrics.java8.MemoryPools;
1515
import io.opentelemetry.instrumentation.runtimemetrics.java8.Threads;
16+
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.ExperimentalBufferPools;
17+
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.ExperimentalCpu;
18+
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.ExperimentalMemoryPools;
1619
import java.util.ArrayList;
1720
import java.util.Arrays;
1821
import java.util.Collections;
@@ -28,6 +31,7 @@ public final class RuntimeMetricsBuilder {
2831
final EnumMap<JfrFeature, Boolean> enabledFeatureMap;
2932

3033
private boolean disableJmx = false;
34+
private boolean enableExperimentalJmxTelemetry = false;
3135

3236
RuntimeMetricsBuilder(OpenTelemetry openTelemetry) {
3337
this.openTelemetry = openTelemetry;
@@ -73,13 +77,20 @@ public RuntimeMetricsBuilder disableFeature(JfrFeature feature) {
7377
return this;
7478
}
7579

76-
/** Disable telemetry collection associated with the {@link JfrFeature}. */
80+
/** Disable all JMX telemetry collection. */
7781
@CanIgnoreReturnValue
7882
public RuntimeMetricsBuilder disableAllJmx() {
7983
disableJmx = true;
8084
return this;
8185
}
8286

87+
/** Disable telemetry collection associated with the {@link JfrFeature}. */
88+
@CanIgnoreReturnValue
89+
public RuntimeMetricsBuilder enableExperimentalJmxTelemetry() {
90+
enableExperimentalJmxTelemetry = true;
91+
return this;
92+
}
93+
8394
/** Build and start an {@link RuntimeMetrics} with the config from this builder. */
8495
public RuntimeMetrics build() {
8596
List<AutoCloseable> observables = buildObservables();
@@ -98,9 +109,14 @@ private List<AutoCloseable> buildObservables() {
98109
observables.addAll(BufferPools.registerObservers(openTelemetry));
99110
observables.addAll(Classes.registerObservers(openTelemetry));
100111
observables.addAll(Cpu.registerObservers(openTelemetry));
112+
observables.addAll(GarbageCollector.registerObservers(openTelemetry));
101113
observables.addAll(MemoryPools.registerObservers(openTelemetry));
102114
observables.addAll(Threads.registerObservers(openTelemetry));
103-
observables.addAll(GarbageCollector.registerObservers(openTelemetry));
115+
if (enableExperimentalJmxTelemetry) {
116+
observables.addAll(ExperimentalBufferPools.registerObservers(openTelemetry));
117+
observables.addAll(ExperimentalCpu.registerObservers(openTelemetry));
118+
observables.addAll(ExperimentalMemoryPools.registerObservers(openTelemetry));
119+
}
104120
return observables;
105121
} catch (Exception e) {
106122
throw new IllegalStateException("Error building RuntimeMetrics", e);

instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/instrumentation/javaagent/runtimemetrics/java8/Java8RuntimeMetricsInstaller.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
import io.opentelemetry.instrumentation.runtimemetrics.java8.GarbageCollector;
1515
import io.opentelemetry.instrumentation.runtimemetrics.java8.MemoryPools;
1616
import io.opentelemetry.instrumentation.runtimemetrics.java8.Threads;
17+
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.ExperimentalBufferPools;
18+
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.ExperimentalCpu;
19+
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.ExperimentalMemoryPools;
1720
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil;
1821
import io.opentelemetry.javaagent.extension.AgentListener;
1922
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
@@ -35,19 +38,24 @@ public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) {
3538
|| Double.parseDouble(System.getProperty("java.specification.version")) >= 17) {
3639
return;
3740
}
41+
3842
OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
3943
List<AutoCloseable> observables = new ArrayList<>();
4044
observables.addAll(BufferPools.registerObservers(openTelemetry));
4145
observables.addAll(Classes.registerObservers(openTelemetry));
4246
observables.addAll(Cpu.registerObservers(openTelemetry));
47+
observables.addAll(GarbageCollector.registerObservers(openTelemetry));
4348
observables.addAll(MemoryPools.registerObservers(openTelemetry));
4449
observables.addAll(Threads.registerObservers(openTelemetry));
45-
observables.addAll(GarbageCollector.registerObservers(openTelemetry));
46-
Thread cleanupTelemetry =
47-
new Thread(
48-
() -> {
49-
JmxRuntimeMetricsUtil.closeObservers(observables);
50-
});
50+
51+
if (config.getBoolean(
52+
"otel.instrumentation.runtime-telemetry.emit-experimental-telemetry", false)) {
53+
observables.addAll(ExperimentalBufferPools.registerObservers(openTelemetry));
54+
observables.addAll(ExperimentalCpu.registerObservers(openTelemetry));
55+
observables.addAll(ExperimentalMemoryPools.registerObservers(openTelemetry));
56+
}
57+
58+
Thread cleanupTelemetry = new Thread(() -> JmxRuntimeMetricsUtil.closeObservers(observables));
5159
Runtime.getRuntime().addShutdownHook(cleanupTelemetry);
5260
}
5361
}

instrumentation/runtime-telemetry/runtime-telemetry-java8/library/README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,26 @@ Register observers for the desired runtime metrics:
3434
```java
3535
OpenTelemetry openTelemetry = // OpenTelemetry instance configured elsewhere
3636

37-
BufferPools.registerObservers(openTelemetry);
3837
Classes.registerObservers(openTelemetry);
3938
Cpu.registerObservers(openTelemetry);
4039
MemoryPools.registerObservers(openTelemetry);
4140
Threads.registerObservers(openTelemetry);
4241
GarbageCollector.registerObservers(openTelemetry);
4342
```
4443

44+
## Stable JVM metrics preview
45+
46+
If you want to enable the preview of the stable JVM semantic conventions, you need to set either
47+
the `otel.semconv-stability.opt-in` system property or the `OTEL_SEMCONV_STABILITY_OPT_IN`
48+
environment variable to one of the following values:
49+
50+
- `jvm` - this will make the runtime metrics emit only the new, stable conventions, and stop
51+
emitting the old experimental conventions that the instrumentation emitted previously.
52+
- `jvm/dup` - emit both the old and the stable JVM conventions, allowing for a seamless transition.
53+
54+
Note that the `otel.semconv-stability.opt-in` setting is a comma-separated list, and you can specify
55+
more than one value, e.g. `-Dotel.semconv-stability.opt-in=http,jvm`.
56+
4557
## Garbage Collector Dependent Metrics
4658

4759
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.

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import io.opentelemetry.api.common.Attributes;
1111
import io.opentelemetry.api.metrics.Meter;
1212
import io.opentelemetry.api.metrics.ObservableLongMeasurement;
13+
import io.opentelemetry.instrumentation.api.internal.SemconvStability;
1314
import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil;
1415
import java.lang.management.BufferPoolMXBean;
1516
import java.lang.management.ManagementFactory;
1617
import java.util.ArrayList;
18+
import java.util.Collections;
1719
import java.util.List;
1820
import java.util.function.Consumer;
1921
import java.util.function.Function;
@@ -48,6 +50,11 @@ public static List<AutoCloseable> registerObservers(OpenTelemetry openTelemetry)
4850
// Visible for testing
4951
static List<AutoCloseable> registerObservers(
5052
OpenTelemetry openTelemetry, List<BufferPoolMXBean> bufferBeans) {
53+
54+
// buffer pool metrics are experimental in the new semconv
55+
if (!SemconvStability.emitOldJvmSemconv()) {
56+
return Collections.emptyList();
57+
}
5158
List<AutoCloseable> observables = new ArrayList<>();
5259
Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry);
5360
observables.add(

0 commit comments

Comments
 (0)