From 82b07aa799dd6d755025006c065f490ec105b212 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 4 Feb 2026 07:18:24 -0800 Subject: [PATCH 01/14] Simplify / unify runtime-telemetry modules --- .fossa.yml | 6 + instrumentation/runtime-telemetry/README.md | 25 +- .../javaagent/build.gradle.kts | 16 + .../runtimetelemetry}/JarAnalyzer.java | 69 ++-- .../JarAnalyzerInstaller.java | 83 ++++ .../runtimetelemetry}/JarDetails.java | 2 +- .../RuntimeTelemetryInstaller.java | 30 ++ .../runtime-telemetry/library/README.md | 173 ++++++++ .../library/build.gradle.kts | 170 ++++++++ .../runtimetelemetry/RuntimeTelemetry.java | 81 ++++ .../RuntimeTelemetryBuilder.java | 123 ++++++ .../internal/BufferPools.java | 12 +- .../runtimetelemetry}/internal/Classes.java | 10 +- .../runtimetelemetry}/internal/Cpu.java | 10 +- .../internal/CpuMethods.java | 2 +- .../internal/Experimental.java | 68 ++++ .../internal/FileDescriptor.java | 11 +- .../internal/GarbageCollector.java | 11 +- .../runtimetelemetry/internal/Internal.java | 377 ++++++++++++++++++ .../runtimetelemetry/internal/JfrConfig.java | 54 +++ .../internal/JmxRuntimeMetricsFactory.java | 45 +++ .../internal/MemoryInit.java | 12 +- .../internal/MemoryPools.java | 10 +- .../runtimetelemetry}/internal/SystemCpu.java | 14 +- .../runtimetelemetry}/internal/Threads.java | 25 +- .../runtimetelemetry}/internal/Constants.java | 2 +- .../internal/DurationUtil.java | 2 +- .../internal/HandlerRegistry.java | 100 +++++ .../runtimetelemetry/internal/JfrConfig.java | 219 ++++++++++ .../runtimetelemetry/internal/JfrFeature.java | 49 +++ .../internal/RecordedEventHandler.java | 3 +- .../buffer/DirectBufferStatisticsHandler.java | 8 +- .../classes/ClassesLoadedHandler.java | 8 +- .../ContainerConfigurationHandler.java | 28 +- .../cpu/ContextSwitchRateHandler.java | 8 +- .../internal/cpu/LongLockHandler.java | 10 +- .../internal/cpu/OverallCpuLoadHandler.java | 8 +- .../G1GarbageCollectionHandler.java | 10 +- .../OldGarbageCollectionHandler.java | 10 +- .../YoungGarbageCollectionHandler.java | 10 +- .../memory/CodeCacheConfigurationHandler.java | 8 +- .../internal/memory/G1HeapSummaryHandler.java | 8 +- .../memory/MetaspaceSummaryHandler.java | 12 +- .../ObjectAllocationInNewTlabHandler.java | 8 +- .../ObjectAllocationOutsideTlabHandler.java | 8 +- .../memory/ParallelHeapSummaryHandler.java | 12 +- .../internal/network/NetworkReadHandler.java | 10 +- .../internal/network/NetworkWriteHandler.java | 10 +- .../internal/threads/ThreadCountHandler.java | 10 +- .../META-INF/native-image/reflect-config.json | 10 + .../internal/BufferPoolsTest.java | 14 +- .../internal/ClassesTest.java | 14 +- .../runtimetelemetry}/internal/CpuTest.java | 17 +- .../internal/FileDescriptorTest.java | 13 +- .../internal/GarbageCollectorTest.java | 8 +- .../internal/MemoryInitTest.java | 8 +- .../internal/MemoryPoolsTest.java | 17 +- .../internal/SystemCpuTest.java | 12 +- .../internal/ThreadsTest.java | 18 +- .../runtimetelemetry}/BufferMetricTest.java | 12 +- .../CodeCacheMemoryInitMetricTest.java | 16 +- .../G1GcMemoryMetricTest.java | 45 ++- .../runtimetelemetry}/GenerateDocs.java | 26 +- .../JfrClassesLoadedCountTest.java | 10 +- .../runtimetelemetry}/JfrCpuLockTest.java | 10 +- .../runtimetelemetry}/JfrExtension.java | 18 +- .../JfrOverallCpuLoadHandlerTest.java | 11 +- .../runtimetelemetry}/JfrThreadCountTest.java | 12 +- .../MetaspaceMemoryCommittedMetricTest.java | 18 +- .../MetaspaceMemoryLimitMetricTest.java | 16 +- .../MetaspaceMemoryUsageMetricTest.java | 18 +- .../PsGcMemoryMetricTest.java | 51 +-- .../RuntimeTelemetryBuilderTest.java | 98 +++++ .../RuntimeTelemetryTest.java | 123 ++++++ .../SerialGcMemoryMetricTest.java | 22 +- .../internal/DurationUtilTest.java | 2 +- .../javaagent/build.gradle.kts | 6 +- .../java17/Java17RuntimeMetricsInstaller.java | 33 -- .../library/README.md | 4 + .../library/build.gradle.kts | 52 +-- .../java17/HandlerRegistry.java | 115 ------ .../runtimemetrics/java17/JfrFeature.java | 10 + .../runtimemetrics/java17/RuntimeMetrics.java | 146 +------ .../java17/RuntimeMetricsBuilder.java | 163 ++++++-- .../internal/RuntimeMetricsConfigUtil.java | 56 --- .../java17/RuntimeMetricsBuilderTest.java | 51 ++- .../java17/RuntimeMetricsTest.java | 32 +- .../javaagent/build.gradle.kts | 8 +- .../java8/JarAnalyzerInstaller.java | 39 -- .../java8/Java8RuntimeMetricsInstaller.java | 37 -- .../runtime-telemetry-java8/library/README.md | 48 +-- .../library/build.gradle.kts | 2 +- .../runtimemetrics/java8/RuntimeMetrics.java | 37 +- .../java8/RuntimeMetricsBuilder.java | 54 ++- .../internal/JmxRuntimeMetricsFactory.java | 37 -- .../java8/internal/JmxRuntimeMetricsUtil.java | 56 --- .../internal/RuntimeMetricsConfigUtil.java | 42 -- .../runtimemetrics/java8/ScopeUtil.java | 33 -- .../testing/build.gradle.kts | 2 +- .../testapp/DummyApplication.java | 0 .../runtimetelemetry}/JarAnalyzerTest.java | 27 +- .../build.gradle.kts | 3 +- .../Java8RuntimeMetricsAutoConfiguration.java | 71 ---- .../RuntimeMetricsAutoConfiguration.java} | 23 +- .../main/resources/META-INF/spring.factories | 3 +- ...ot.autoconfigure.AutoConfiguration.imports | 3 +- settings.gradle.kts | 4 +- .../AbstractSpringStarterSmokeTest.java | 5 +- 108 files changed, 2568 insertions(+), 1273 deletions(-) create mode 100644 instrumentation/runtime-telemetry/javaagent/build.gradle.kts rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8 => javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry}/JarAnalyzer.java (79%) create mode 100644 instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzerInstaller.java rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8 => javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry}/JarDetails.java (99%) create mode 100644 instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/RuntimeTelemetryInstaller.java create mode 100644 instrumentation/runtime-telemetry/library/README.md create mode 100644 instrumentation/runtime-telemetry/library/build.gradle.kts create mode 100644 instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetry.java create mode 100644 instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/BufferPools.java (86%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/Classes.java (81%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/Cpu.java (90%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/CpuMethods.java (98%) create mode 100644 instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Experimental.java rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/FileDescriptor.java (79%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/GarbageCollector.java (94%) create mode 100644 instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java create mode 100644 instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrConfig.java create mode 100644 instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/JmxRuntimeMetricsFactory.java rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/MemoryInit.java (84%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/MemoryPools.java (91%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/SystemCpu.java (79%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/Threads.java (86%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/Constants.java (98%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/DurationUtil.java (90%) create mode 100644 instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java create mode 100644 instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrConfig.java create mode 100644 instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrFeature.java rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/RecordedEventHandler.java (93%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/buffer/DirectBufferStatisticsHandler.java (90%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/classes/ClassesLoadedHandler.java (89%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/container/ContainerConfigurationHandler.java (51%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/cpu/ContextSwitchRateHandler.java (81%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/cpu/LongLockHandler.java (80%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/cpu/OverallCpuLoadHandler.java (88%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/garbagecollection/G1GarbageCollectionHandler.java (78%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/garbagecollection/OldGarbageCollectionHandler.java (78%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/garbagecollection/YoungGarbageCollectionHandler.java (79%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/memory/CodeCacheConfigurationHandler.java (84%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/memory/G1HeapSummaryHandler.java (93%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/memory/MetaspaceSummaryHandler.java (91%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/memory/ObjectAllocationInNewTlabHandler.java (82%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/memory/ObjectAllocationOutsideTlabHandler.java (82%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/memory/ParallelHeapSummaryHandler.java (94%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/network/NetworkReadHandler.java (81%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/network/NetworkWriteHandler.java (85%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry}/internal/threads/ThreadCountHandler.java (85%) create mode 100644 instrumentation/runtime-telemetry/library/src/main/resources/META-INF/native-image/reflect-config.json rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/BufferPoolsTest.java (89%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/ClassesTest.java (85%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/CpuTest.java (81%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/FileDescriptorTest.java (83%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/GarbageCollectorTest.java (95%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/MemoryInitTest.java (90%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/MemoryPoolsTest.java (93%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/SystemCpuTest.java (81%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8 => library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/ThreadsTest.java (91%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/BufferMetricTest.java (87%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/CodeCacheMemoryInitMetricTest.java (58%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/G1GcMemoryMetricTest.java (60%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/GenerateDocs.java (84%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/JfrClassesLoadedCountTest.java (85%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/JfrCpuLockTest.java (80%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/JfrExtension.java (80%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/JfrOverallCpuLoadHandlerTest.java (71%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/JfrThreadCountTest.java (77%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/MetaspaceMemoryCommittedMetricTest.java (54%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/MetaspaceMemoryLimitMetricTest.java (55%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/MetaspaceMemoryUsageMetricTest.java (56%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/PsGcMemoryMetricTest.java (55%) create mode 100644 instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilderTest.java create mode 100644 instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryTest.java rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/SerialGcMemoryMetricTest.java (61%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17 => library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry}/internal/DurationUtilTest.java (85%) delete mode 100644 instrumentation/runtime-telemetry/runtime-telemetry-java17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java17/Java17RuntimeMetricsInstaller.java delete mode 100644 instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/HandlerRegistry.java delete mode 100644 instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java delete mode 100644 instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarAnalyzerInstaller.java delete mode 100644 instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/Java8RuntimeMetricsInstaller.java delete mode 100644 instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java delete mode 100644 instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsUtil.java delete mode 100644 instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java delete mode 100644 instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/ScopeUtil.java rename instrumentation/runtime-telemetry/{runtime-telemetry-java8 => }/testing/build.gradle.kts (96%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8 => }/testing/src/main/java/io/opentelemetry/instrumentation/testapp/DummyApplication.java (100%) rename instrumentation/runtime-telemetry/{runtime-telemetry-java8/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8 => testing/src/test/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry}/JarAnalyzerTest.java (90%) delete mode 100644 instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimemetrics/Java8RuntimeMetricsAutoConfiguration.java rename instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/{runtimemetrics/Java17RuntimeMetricsAutoConfiguration.java => runtimetelemetry/RuntimeMetricsAutoConfiguration.java} (67%) diff --git a/.fossa.yml b/.fossa.yml index cf35ab1c3c1d..dbf9f9ac20c5 100644 --- a/.fossa.yml +++ b/.fossa.yml @@ -277,6 +277,12 @@ targets: - type: gradle path: ./ target: ':instrumentation:rmi:javaagent' + - type: gradle + path: ./ + target: ':instrumentation:runtime-telemetry:javaagent' + - type: gradle + path: ./ + target: ':instrumentation:runtime-telemetry:library' - type: gradle path: ./ target: ':instrumentation:scala-fork-join-2.8:javaagent' diff --git a/instrumentation/runtime-telemetry/README.md b/instrumentation/runtime-telemetry/README.md index 51a6611f7c08..e36eab69fe3c 100644 --- a/instrumentation/runtime-telemetry/README.md +++ b/instrumentation/runtime-telemetry/README.md @@ -1,10 +1,19 @@ # Settings for the Runtime Telemetry instrumentation -| System property | Type | Default | Description | -|--------------------------------------------------------------------------|---------|---------|-----------------------------------------------------------------------------------| -| `otel.instrumentation.runtime-telemetry.capture-gc-cause` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. | -| `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Enable the capture of experimental metrics. | -| `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Enable the capture of all JFR based metrics. | -| `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Enable the capture of JFR based metrics. | -| `otel.instrumentation.runtime-telemetry.package-emitter.enabled` | Boolean | `false` | Enable creating events for JAR libraries used by the application. | -| `otel.instrumentation.runtime-telemetry.package-emitter.jars-per-second` | Integer | 10 | The number of JAR files processed per second. | +| System property | Type | Default | Description | +|---------------------------------------------------------------------------------------|---------|---------|-----------------------------------------------------------------------------------| +| `otel.instrumentation.runtime-telemetry.emit-experimental-metrics` | Boolean | `false` | Enable the capture of experimental metrics. | +| `otel.instrumentation.runtime-telemetry.experimental.prefer-jfr` | Boolean | `false` | Use JFR instead of JMX for overlapping metrics (Java 17+). | +| `otel.instrumentation.runtime-telemetry.experimental.package-emitter.enabled` | Boolean | `false` | Enable creating events for JAR libraries used by the application. | +| `otel.instrumentation.runtime-telemetry.experimental.package-emitter.jars-per-second` | Integer | 10 | The number of JAR files processed per second. | + +## Deprecated Properties (to be removed in 3.0) + +| System property | Type | Default | Description | +|------------------------------------------------------------------------------------|---------|---------|-----------------------------------------------------------------------------------| +| `otel.instrumentation.runtime-telemetry.capture-gc-cause` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute. Will always be captured in 3.0. | +| `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Use `emit-experimental-metrics` instead. | +| `otel.instrumentation.runtime-telemetry.package-emitter.enabled` | Boolean | `false` | Use `experimental.package-emitter.enabled` instead. | +| `otel.instrumentation.runtime-telemetry.package-emitter.jars-per-second` | Integer | 10 | Use `experimental.package-emitter.jars-per-second` instead. | +| `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Deprecated. Use `emit-experimental-metrics` for experimental JFR features. | +| `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Deprecated. Use `emit-experimental-metrics` and `experimental.prefer-jfr`. | diff --git a/instrumentation/runtime-telemetry/javaagent/build.gradle.kts b/instrumentation/runtime-telemetry/javaagent/build.gradle.kts new file mode 100644 index 000000000000..493e69c45b3c --- /dev/null +++ b/instrumentation/runtime-telemetry/javaagent/build.gradle.kts @@ -0,0 +1,16 @@ +plugins { + id("otel.javaagent-instrumentation") +} + +dependencies { + implementation(project(":instrumentation:runtime-telemetry:library")) + + compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + compileOnly("io.opentelemetry:opentelemetry-api-incubator") +} + +tasks { + test { + jvmArgs("-Dotel.instrumentation.runtime-telemetry.experimental.package-emitter.enabled=true") + } +} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarAnalyzer.java b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzer.java similarity index 79% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarAnalyzer.java rename to instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzer.java index b32f2c44a805..a431beb621f1 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarAnalyzer.java +++ b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzer.java @@ -3,11 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8; +package io.opentelemetry.javaagent.instrumentation.runtimetelemetry; -import static io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8.JarDetails.EAR_EXTENSION; -import static io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8.JarDetails.JAR_EXTENSION; -import static io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8.JarDetails.WAR_EXTENSION; +import static io.opentelemetry.javaagent.instrumentation.runtimetelemetry.JarDetails.EAR_EXTENSION; +import static io.opentelemetry.javaagent.instrumentation.runtimetelemetry.JarDetails.JAR_EXTENSION; +import static io.opentelemetry.javaagent.instrumentation.runtimetelemetry.JarDetails.WAR_EXTENSION; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.logging.Level.FINEST; import static java.util.logging.Level.INFO; @@ -17,8 +17,8 @@ import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; -import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder; -import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil; +import io.opentelemetry.api.logs.Logger; +import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; import io.opentelemetry.sdk.common.Clock; import io.opentelemetry.sdk.common.internal.DaemonThreadFactory; import io.opentelemetry.sdk.common.internal.RateLimiter; @@ -34,7 +34,6 @@ import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; -import java.util.logging.Logger; /** * {@link JarAnalyzer} is a {@link ClassFileTransformer} which processes the {@link @@ -43,7 +42,8 @@ */ final class JarAnalyzer implements ClassFileTransformer { - private static final Logger logger = Logger.getLogger(JarAnalyzer.class.getName()); + private static final java.util.logging.Logger logger = + java.util.logging.Logger.getLogger(JarAnalyzer.class.getName()); private static final String EVENT_NAME_INFO = "package.info"; static final AttributeKey PACKAGE_NAME = AttributeKey.stringKey("package.name"); @@ -59,16 +59,16 @@ final class JarAnalyzer implements ClassFileTransformer { private final Set seenUris = new HashSet<>(); private final BlockingQueue toProcess = new LinkedBlockingDeque<>(); - private JarAnalyzer(OpenTelemetry openTelemetry, int jarsPerSecond) { - ExtendedLogRecordBuilder logRecordBuilder = - (ExtendedLogRecordBuilder) - openTelemetry - .getLogsBridge() - .loggerBuilder(JmxRuntimeMetricsUtil.getInstrumentationName()) - .setInstrumentationVersion(JmxRuntimeMetricsUtil.getInstrumentationVersion()) - .build() - .logRecordBuilder(); - Worker worker = new Worker(logRecordBuilder, toProcess, jarsPerSecond); + private JarAnalyzer(OpenTelemetry openTelemetry, String instrumentationName, int jarsPerSecond) { + String instrumentationVersion = + EmbeddedInstrumentationProperties.findVersion(instrumentationName); + Logger logger = + openTelemetry + .getLogsBridge() + .loggerBuilder(instrumentationName) + .setInstrumentationVersion(instrumentationVersion) + .build(); + Worker worker = new Worker(logger, toProcess, jarsPerSecond); Thread workerThread = new DaemonThreadFactory(JarAnalyzer.class.getSimpleName() + "_WorkerThread") .newThread(worker); @@ -76,8 +76,10 @@ private JarAnalyzer(OpenTelemetry openTelemetry, int jarsPerSecond) { } /** Create {@link JarAnalyzer} and start the worker thread. */ - public static JarAnalyzer create(OpenTelemetry unused, int jarsPerSecond) { - return new JarAnalyzer(unused, jarsPerSecond); + // TODO can remove instrumentationName parameter in 3.0 + public static JarAnalyzer create( + OpenTelemetry openTelemetry, String instrumentationName, int jarsPerSecond) { + return new JarAnalyzer(openTelemetry, instrumentationName, jarsPerSecond); } /** @@ -156,20 +158,19 @@ private void handle(ProtectionDomain protectionDomain) { private static final class Worker implements Runnable { - private final ExtendedLogRecordBuilder eventLogger; + private final Logger logger; private final BlockingQueue toProcess; private final RateLimiter rateLimiter; - private Worker( - ExtendedLogRecordBuilder eventLogger, BlockingQueue toProcess, int jarsPerSecond) { - this.eventLogger = eventLogger; + private Worker(Logger logger, BlockingQueue toProcess, int jarsPerSecond) { + this.logger = logger; this.toProcess = toProcess; this.rateLimiter = new RateLimiter(jarsPerSecond, jarsPerSecond, Clock.getDefault()); } /** * Continuously poll the {@link #toProcess} for archive {@link URL}s, and process each wit - * {@link #processUrl(ExtendedLogRecordBuilder, URL)}. + * {@link #processUrl(Logger, URL)}. */ @Override public void run() { @@ -190,12 +191,13 @@ public void run() { try { // TODO(jack-berg): add ability to optionally re-process urls periodically to re-emit // events - processUrl(eventLogger, archiveUrl); + processUrl(logger, archiveUrl); } catch (Throwable e) { - logger.log(WARNING, "Unexpected error processing archive URL: " + archiveUrl, e); + JarAnalyzer.logger.log( + WARNING, "Unexpected error processing archive URL: " + archiveUrl, e); } } - logger.warning("JarAnalyzer stopped"); + JarAnalyzer.logger.warning("JarAnalyzer stopped"); } } @@ -203,12 +205,13 @@ public void run() { * Process the {@code archiveUrl}, extracting metadata from it and emitting an event with the * content. */ - static void processUrl(ExtendedLogRecordBuilder eventLogger, URL archiveUrl) { + static void processUrl(Logger logger, URL archiveUrl) { JarDetails jarDetails; try { jarDetails = JarDetails.forUrl(archiveUrl); } catch (IOException e) { - logger.log(WARNING, "Error reading package for archive URL: " + archiveUrl, e); + JarAnalyzer.logger.log( + WARNING, "Error reading package for archive URL: " + archiveUrl, e); return; } AttributesBuilder builder = Attributes.builder(); @@ -242,6 +245,10 @@ static void processUrl(ExtendedLogRecordBuilder eventLogger, URL archiveUrl) { builder.put(PACKAGE_CHECKSUM, packageChecksum); builder.put(PACKAGE_CHECKSUM_ALGORITHM, "SHA1"); - eventLogger.setEventName(EVENT_NAME_INFO).setAllAttributes(builder.build()).emit(); + logger + .logRecordBuilder() + .setEventName(EVENT_NAME_INFO) + .setAllAttributes(builder.build()) + .emit(); } } diff --git a/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzerInstaller.java b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzerInstaller.java new file mode 100644 index 000000000000..c6d3f0d93f8e --- /dev/null +++ b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzerInstaller.java @@ -0,0 +1,83 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.runtimetelemetry; + +import com.google.auto.service.AutoService; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; +import io.opentelemetry.javaagent.bootstrap.InstrumentationHolder; +import io.opentelemetry.javaagent.tooling.BeforeAgentListener; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; +import java.lang.instrument.Instrumentation; +import java.util.logging.Logger; + +/** Installs the {@link JarAnalyzer}. */ +@AutoService(BeforeAgentListener.class) +public class JarAnalyzerInstaller implements BeforeAgentListener { + + private static final Logger logger = Logger.getLogger(JarAnalyzerInstaller.class.getName()); + private static final int DEFAULT_JARS_PER_SECOND = 10; + + @Override + public void beforeAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { + OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); + DeclarativeConfigProperties config = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "runtime_telemetry"); + + // Support both new config (package_emitter/development) and old path + // (package_emitter) + DeclarativeConfigProperties newPackageEmitterConfig = config.get("package_emitter/development"); + DeclarativeConfigProperties oldPackageEmitterConfig = config.get("package_emitter"); + + boolean enabledNew = newPackageEmitterConfig.getBoolean("enabled", false); + boolean enabledOld = oldPackageEmitterConfig.getBoolean("enabled", false); + if (enabledOld) { + logger.warning( + "otel.instrumentation.runtime-telemetry.package-emitter.enabled is deprecated and will" + + " be removed in 3.0. Use" + + " otel.instrumentation.runtime-telemetry.experimental.package-emitter.enabled" + + " instead."); + } + if (!enabledNew && !enabledOld) { + return; + } + Instrumentation inst = InstrumentationHolder.getInstrumentation(); + if (inst == null) { + return; + } + + // Use appropriate instrumentation name based on which config is active + String instrumentationName = + enabledNew + ? "io.opentelemetry.runtime-telemetry" + : "io.opentelemetry.runtime-telemetry-java8"; + + int newJarsPerSecond = newPackageEmitterConfig.getInt("jars_per_second", -1); + int oldJarsPerSecond = oldPackageEmitterConfig.getInt("jars_per_second", -1); + + if (oldJarsPerSecond >= 0) { + logger.warning( + "otel.instrumentation.runtime-telemetry.package-emitter.jars-per-second is deprecated" + + " and will be removed in 3.0. Use" + + " otel.instrumentation.runtime-telemetry.experimental.package-emitter.jars-per-second" + + " instead."); + } + + int jarsPerSecond; + if (newJarsPerSecond >= 0) { + jarsPerSecond = newJarsPerSecond; + } else if (oldJarsPerSecond >= 0) { + jarsPerSecond = oldJarsPerSecond; + } else { + jarsPerSecond = DEFAULT_JARS_PER_SECOND; + } + + JarAnalyzer jarAnalyzer = JarAnalyzer.create(openTelemetry, instrumentationName, jarsPerSecond); + inst.addTransformer(jarAnalyzer); + } +} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarDetails.java b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarDetails.java similarity index 99% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarDetails.java rename to instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarDetails.java index 0e61f186ec65..5b2fd6bc6691 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarDetails.java +++ b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarDetails.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8; +package io.opentelemetry.javaagent.instrumentation.runtimetelemetry; import static java.util.function.Function.identity; import static java.util.stream.Collectors.collectingAndThen; diff --git a/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/RuntimeTelemetryInstaller.java b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/RuntimeTelemetryInstaller.java new file mode 100644 index 000000000000..c7d56189cf9e --- /dev/null +++ b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/RuntimeTelemetryInstaller.java @@ -0,0 +1,30 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.runtimetelemetry; + +import com.google.auto.service.AutoService; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetry; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Internal; +import io.opentelemetry.javaagent.extension.AgentListener; +import io.opentelemetry.javaagent.tooling.config.AgentConfig; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; + +/** An {@link AgentListener} that enables runtime metrics during agent startup. */ +@AutoService(AgentListener.class) +public class RuntimeTelemetryInstaller implements AgentListener { + + @Override + public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) { + RuntimeTelemetry runtimeTelemetry = + Internal.configure(GlobalOpenTelemetry.get(), AgentConfig.instrumentationMode()); + if (runtimeTelemetry != null) { + Runtime.getRuntime() + .addShutdownHook( + new Thread(runtimeTelemetry::close, "OpenTelemetry RuntimeTelemetryShutdownHook")); + } + } +} diff --git a/instrumentation/runtime-telemetry/library/README.md b/instrumentation/runtime-telemetry/library/README.md new file mode 100644 index 000000000000..29339b21382b --- /dev/null +++ b/instrumentation/runtime-telemetry/library/README.md @@ -0,0 +1,173 @@ +# JVM Runtime Metrics + +This module provides JVM runtime metrics as documented in the [semantic conventions](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md). + +This is the unified runtime telemetry module that works on all Java versions. On Java 8-16, it uses +JMX for metrics collection. On Java 17+, it can additionally use JFR (Java Flight Recorder) for +metrics that are not available via JMX. + +## Quickstart + +### Add these dependencies to your project + +Replace `OPENTELEMETRY_VERSION` with the [latest +release](https://central.sonatype.com/artifact/io.opentelemetry.instrumentation/opentelemetry-runtime-telemetry). + +For Maven, add to your `pom.xml` dependencies: + +```xml + + + io.opentelemetry.instrumentation + opentelemetry-runtime-telemetry + OPENTELEMETRY_VERSION + + +``` + +For Gradle, add to your dependencies: + +```groovy +runtimeOnly("io.opentelemetry.instrumentation:opentelemetry-runtime-telemetry:OPENTELEMETRY_VERSION") +``` + +### Usage + +Register JVM runtime metrics: + +```java +OpenTelemetry openTelemetry = // OpenTelemetry instance configured elsewhere + +RuntimeTelemetry runtimeTelemetry = RuntimeTelemetry.create(openTelemetry); + +// When done, close to stop metric collection +runtimeTelemetry.close(); +``` + +To select specific metrics, configure [metric views](https://opentelemetry.io/docs/languages/java/sdk/#views) +on the SDK to filter or customize which metrics are exported. + +For example, using [declarative configuration](https://github.com/open-telemetry/opentelemetry-java-examples/tree/main/declarative-configuration): + +```yaml +meter_provider: + views: + # Drop jvm.memory.committed metric + - selector: + instrument_name: jvm.memory.committed + stream: + aggregation: + drop: + # Only retain jvm.memory.type attribute on jvm.memory.used + - selector: + instrument_name: jvm.memory.used + stream: + attribute_keys: + included: + - jvm.memory.type +``` + +To retain only `jvm.memory.used` and drop all other JVM runtime metrics: + +```yaml +meter_provider: + views: + # Drop all metrics from this instrumentation scope + - selector: + meter_name: io.opentelemetry.runtime-telemetry + stream: + aggregation: + drop: + # Keep jvm.memory.used (views are additive, this creates a second stream) + - selector: + meter_name: io.opentelemetry.runtime-telemetry + instrument_name: jvm.memory.used + stream: {} +``` + +## Metrics + +### Stable Metrics (enabled by default) + +These metrics are collected via JMX on all Java versions: + +| Metric | Description | +| -------- | ----------- | +| `jvm.class.count` | Number of classes currently loaded | +| `jvm.class.loaded` | Number of classes loaded since JVM start | +| `jvm.class.unloaded` | Number of classes unloaded since JVM start | +| `jvm.cpu.recent_utilization` | Recent CPU utilization for the process | +| `jvm.cpu.time` | CPU time used by the process | +| `jvm.gc.duration` | Duration of JVM garbage collection actions | +| `jvm.memory.committed` | Measure of memory committed | +| `jvm.memory.limit` | Measure of max obtainable memory | +| `jvm.memory.used` | Measure of memory used | +| `jvm.memory.used_after_last_gc` | Measure of memory used, as measured after the most recent garbage collection event on this pool | +| `jvm.thread.count` | Number of executing platform threads | + +### Experimental Metrics + +These metrics are enabled with `emitExperimentalMetrics()`: + +**JMX-based (all Java versions):** + +| Metric | Description | +| -------- | ----------- | +| `jvm.buffer.count` | Number of buffers in the pool | +| `jvm.buffer.memory.limit` | Measure of total memory capacity of buffers | +| `jvm.buffer.memory.used` | Measure of memory used by buffers | +| `jvm.memory.init` | Measure of initial memory requested | +| `jvm.system.cpu.utilization` | System-wide CPU utilization | + +**JFR-based (Java 17+ only):** + +| Metric | Description | +| -------- | ----------- | +| `jvm.cpu.context_switch` | Context switch rate | +| `jvm.cpu.longlock` | Long lock contention | +| `jvm.memory.allocation` | Memory allocation rate | +| `jvm.network.io` | Network I/O bytes | +| `jvm.network.time` | Network I/O time | + +## Garbage Collector Dependent Metrics + +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 `*.used`, `*.committed`, and `*.limit` since not all memory pools report a limit. + +- CMS Garbage Collector + - `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 + - `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 + - `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 + - `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 + - `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 + - `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} diff --git a/instrumentation/runtime-telemetry/library/build.gradle.kts b/instrumentation/runtime-telemetry/library/build.gradle.kts new file mode 100644 index 000000000000..2a390f89da1b --- /dev/null +++ b/instrumentation/runtime-telemetry/library/build.gradle.kts @@ -0,0 +1,170 @@ +plugins { + id("otel.library-instrumentation") +} + +val mrJarVersions = listOf(17) + +dependencies { + implementation(project(":instrumentation-api")) + implementation(project(":instrumentation-api-incubator")) + + testImplementation("io.opentelemetry:opentelemetry-sdk-testing") + testImplementation("io.github.netmikey.logunit:logunit-jul:1.1.3") +} + +sourceSets { + create("testJava17") { + java { + setSrcDirs(listOf("src/testJava17/java")) + } + } +} + +for (version in mrJarVersions) { + sourceSets { + create("java$version") { + java { + setSrcDirs(listOf("src/main/java$version")) + } + } + } + + tasks { + named("compileJava${version}Java") { + sourceCompatibility = "$version" + targetCompatibility = "$version" + options.release.set(version) + } + } + + configurations { + named("java${version}Implementation") { + extendsFrom(configurations["implementation"]) + } + named("java${version}CompileOnly") { + extendsFrom(configurations["compileOnly"]) + } + } + + dependencies { + // Common to reference classes in main sourceset from Java 17 one + add("java${version}Implementation", files(sourceSets.main.get().output.classesDirs)) + } +} + +// Configure testJava17 dependencies after java17 sourceset is created +configurations { + named("testJava17Implementation") { + extendsFrom(configurations["testImplementation"]) + } + named("testJava17RuntimeOnly") { + extendsFrom(configurations["testRuntimeOnly"]) + } +} + +dependencies { + add("testJava17Implementation", sourceSets.test.get().output) + add("testJava17Implementation", sourceSets["java17"].output) + add("testJava17Implementation", sourceSets.main.get().output) +} + +tasks { + // Configure testJava17 compilation for Java 17 + named("compileTestJava17Java") { + dependsOn("compileJava17Java") + sourceCompatibility = "17" + targetCompatibility = "17" + options.release.set(17) + } + + withType(Jar::class) { + val sourcePathProvider = if (name == "jar") { + { ss: SourceSet? -> ss?.output } + } else if (name == "sourcesJar") { + { ss: SourceSet? -> ss?.java } + } else { + { project.objects.fileCollection() } + } + + for (version in mrJarVersions) { + into("META-INF/versions/$version") { + from(sourcePathProvider(sourceSets["java$version"])) + } + } + manifest.attributes( + "Multi-Release" to "true", + ) + } + + // GC-specific tests that require Java 17+ + val testG1 by registering(Test::class) { + dependsOn("compileTestJava17Java") + testClassesDirs = sourceSets["testJava17"].output.classesDirs + classpath = sourceSets["testJava17"].runtimeClasspath + filter { + includeTestsMatching("*G1GcMemoryMetricTest*") + } + include("**/*G1GcMemoryMetricTest.*") + jvmArgs("-XX:+UseG1GC") + } + + val testPS by registering(Test::class) { + dependsOn("compileTestJava17Java") + testClassesDirs = sourceSets["testJava17"].output.classesDirs + classpath = sourceSets["testJava17"].runtimeClasspath + filter { + includeTestsMatching("*PsGcMemoryMetricTest*") + } + include("**/*PsGcMemoryMetricTest.*") + jvmArgs("-XX:+UseParallelGC") + } + + val testSerial by registering(Test::class) { + dependsOn("compileTestJava17Java") + testClassesDirs = sourceSets["testJava17"].output.classesDirs + classpath = sourceSets["testJava17"].runtimeClasspath + filter { + includeTestsMatching("*SerialGcMemoryMetricTest*") + } + include("**/*SerialGcMemoryMetricTest.*") + jvmArgs("-XX:+UseSerialGC") + } + + // Run other Java 17 tests (not GC-specific) + val testJava17 by registering(Test::class) { + dependsOn("compileTestJava17Java") + testClassesDirs = sourceSets["testJava17"].output.classesDirs + classpath = sourceSets["testJava17"].runtimeClasspath + filter { + excludeTestsMatching("*G1GcMemoryMetricTest") + excludeTestsMatching("*SerialGcMemoryMetricTest") + excludeTestsMatching("*PsGcMemoryMetricTest") + } + } + + test { + // Java 8 tests only + } + + val testJavaVersion = + gradle.startParameter.projectProperties.get("testJavaVersion")?.let(JavaVersion::toVersion) + ?: JavaVersion.current() + if (!testJavaVersion.isCompatibleWith(JavaVersion.VERSION_17)) { + named("testG1", Test::class).configure { + enabled = false + } + named("testPS", Test::class).configure { + enabled = false + } + named("testSerial", Test::class).configure { + enabled = false + } + named("testJava17", Test::class).configure { + enabled = false + } + } + + check { + dependsOn(testJava17, testG1, testPS, testSerial) + } +} diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetry.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetry.java new file mode 100644 index 000000000000..2cd832b8f46c --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetry.java @@ -0,0 +1,81 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.runtimetelemetry; + +import io.opentelemetry.api.OpenTelemetry; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +/** The entry point class for runtime telemetry support using JMX (Java 8+) and JFR (Java 17+). */ +public final class RuntimeTelemetry implements AutoCloseable { + + private static final Logger logger = Logger.getLogger(RuntimeTelemetry.class.getName()); + + private final AtomicBoolean isClosed = new AtomicBoolean(); + private final List observables; + @Nullable private final AutoCloseable jfrTelemetry; + + RuntimeTelemetry(List observables, @Nullable AutoCloseable jfrTelemetry) { + this.observables = Collections.unmodifiableList(observables); + this.jfrTelemetry = jfrTelemetry; + } + + /** + * Create and start {@link RuntimeTelemetry}. + * + *

Listens for select JMX beans (and JFR events on Java 17+), extracts data, and records to + * various metrics. Recording will continue until {@link #close()} is called. + * + * @param openTelemetry the {@link OpenTelemetry} instance used to record telemetry + */ + public static RuntimeTelemetry create(OpenTelemetry openTelemetry) { + return new RuntimeTelemetryBuilder(openTelemetry).build(); + } + + /** + * Create a builder for configuring {@link RuntimeTelemetry}. + * + * @param openTelemetry the {@link OpenTelemetry} instance used to record telemetry + */ + public static RuntimeTelemetryBuilder builder(OpenTelemetry openTelemetry) { + return new RuntimeTelemetryBuilder(openTelemetry); + } + + // Only used by tests + @Nullable + AutoCloseable getJfrTelemetry() { + return jfrTelemetry; + } + + /** Stop recording metrics. */ + @Override + public void close() { + if (!isClosed.compareAndSet(false, true)) { + logger.log(Level.WARNING, "RuntimeTelemetry is already closed"); + return; + } + + if (jfrTelemetry != null) { + try { + jfrTelemetry.close(); + } catch (Exception e) { + logger.log(Level.WARNING, "Error closing JFR telemetry", e); + } + } + + for (AutoCloseable observable : observables) { + try { + observable.close(); + } catch (Exception e) { + // Ignore + } + } + } +} diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java new file mode 100644 index 000000000000..f023d4f5e68e --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java @@ -0,0 +1,123 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.runtimetelemetry; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.api.metrics.MeterBuilder; +import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Experimental; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Internal; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrConfig; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JmxRuntimeMetricsFactory; +import java.util.Collections; +import java.util.List; + +/** Builder for {@link RuntimeTelemetry}. */ +public final class RuntimeTelemetryBuilder { + + private static final String DEFAULT_INSTRUMENTATION_NAME = "io.opentelemetry.runtime-telemetry"; + + private final OpenTelemetry openTelemetry; + private final JfrConfig jfrConfig; + + private boolean emitExperimentalMetrics = false; + private boolean preferJfrMetrics = false; + private boolean disableJmx = false; + private boolean captureGcCause = true; + // For backward compatibility: support separate instrumentation names for JMX and JFR metrics + private String jmxInstrumentationName = null; + private String jfrInstrumentationName = null; + + static { + Experimental.internalSetEmitExperimentalMetrics( + (builder, emit) -> { + builder.emitExperimentalMetrics = emit; + if (emit) { + builder.jfrConfig.enableExperimentalFeatures(); + } + }); + Experimental.internalSetPreferJfrMetrics( + (builder, prefer) -> builder.preferJfrMetrics = prefer); + Internal.internalSetEnableAllJfrFeatures( + (builder, enable) -> { + if (enable) { + builder.jfrConfig.enableAllFeatures(); + } + }); + Internal.internalSetDisableAllJfrFeatures( + (builder, disable) -> { + if (disable) { + builder.jfrConfig.disableAllFeatures(); + } + }); + Internal.internalSetEnableExperimentalJfrFeatures( + (builder, enable) -> { + if (enable) { + builder.jfrConfig.enableExperimentalFeatures(); + } + }); + Internal.internalSetCaptureGcCause((builder, capture) -> builder.captureGcCause = capture); + Internal.internalSetUseLegacyJfrCpuCountMetric( + (builder, useLegacy) -> builder.jfrConfig.setUseLegacyJfrCpuCountMetric(useLegacy)); + Internal.internalSetJmxInstrumentationName( + (builder, name) -> builder.jmxInstrumentationName = name); + Internal.internalSetJfrInstrumentationName( + (builder, name) -> builder.jfrInstrumentationName = name); + Internal.internalSetEnableJfrFeature( + (builder, featureName) -> builder.jfrConfig.enableFeature(featureName)); + Internal.internalSetDisableJfrFeature( + (builder, featureName) -> builder.jfrConfig.disableFeature(featureName)); + Internal.internalSetDisableJmx((builder, disable) -> builder.disableJmx = disable); + } + + RuntimeTelemetryBuilder(OpenTelemetry openTelemetry) { + this.openTelemetry = openTelemetry; + this.jfrConfig = JfrConfig.create(); + } + + // Visible for testing + JfrConfig getJfrConfig() { + return jfrConfig; + } + + /** Disable all JMX telemetry collection. Visible for testing. */ + @CanIgnoreReturnValue + RuntimeTelemetryBuilder disableAllJmx() { + disableJmx = true; + return this; + } + + /** Build and start a {@link RuntimeTelemetry} with the config from this builder. */ + public RuntimeTelemetry build() { + // Use configured names, or fall back to default if not set + String jmxName = + jmxInstrumentationName != null ? jmxInstrumentationName : DEFAULT_INSTRUMENTATION_NAME; + String jfrName = + jfrInstrumentationName != null ? jfrInstrumentationName : DEFAULT_INSTRUMENTATION_NAME; + + Meter jmxMeter = getMeter(openTelemetry, jmxName); + Meter jfrMeter = getMeter(openTelemetry, jfrName); + + List observables = + disableJmx + ? Collections.emptyList() + : JmxRuntimeMetricsFactory.buildObservables( + emitExperimentalMetrics, captureGcCause, preferJfrMetrics, jmxMeter); + AutoCloseable jfrTelemetry = jfrConfig.buildJfrTelemetry(preferJfrMetrics, jfrMeter); + return new RuntimeTelemetry(observables, jfrTelemetry); + } + + private static Meter getMeter(OpenTelemetry openTelemetry, String instrumentationName) { + MeterBuilder meterBuilder = openTelemetry.meterBuilder(instrumentationName); + String version = EmbeddedInstrumentationProperties.findVersion(instrumentationName); + if (version != null) { + meterBuilder.setInstrumentationVersion(version); + } + return meterBuilder.build(); + } +} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/BufferPools.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/BufferPools.java similarity index 86% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/BufferPools.java rename to instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/BufferPools.java index 375b97625def..360d994284a6 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/BufferPools.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/BufferPools.java @@ -3,11 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; import static io.opentelemetry.api.common.AttributeKey.stringKey; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.Meter; @@ -31,18 +30,15 @@ public final class BufferPools { stringKey("jvm.buffer.pool.name"); /** Register observers for java runtime buffer pool metrics. */ - public static List registerObservers(OpenTelemetry openTelemetry) { + public static List registerObservers(Meter meter) { List bufferBeans = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class); - return registerObservers(openTelemetry, bufferBeans); + return registerObservers(meter, bufferBeans); } // Visible for testing - static List registerObservers( - OpenTelemetry openTelemetry, List bufferBeans) { - + static List registerObservers(Meter meter, List bufferBeans) { List observables = new ArrayList<>(); - Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); observables.add( meter .upDownCounterBuilder("jvm.buffer.memory.used") diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/Classes.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Classes.java similarity index 81% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/Classes.java rename to instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Classes.java index afe74d074a0d..dd7711d39eef 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/Classes.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Classes.java @@ -3,9 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.metrics.Meter; import java.lang.management.ClassLoadingMXBean; import java.lang.management.ManagementFactory; @@ -27,13 +26,12 @@ public class Classes { static final Classes INSTANCE = new Classes(); /** Register observers for java runtime class metrics. */ - public static List registerObservers(OpenTelemetry openTelemetry) { - return INSTANCE.registerObservers(openTelemetry, ManagementFactory.getClassLoadingMXBean()); + public static List registerObservers(Meter meter) { + return INSTANCE.registerObservers(meter, ManagementFactory.getClassLoadingMXBean()); } // Visible for testing - List registerObservers(OpenTelemetry openTelemetry, ClassLoadingMXBean classBean) { - Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); + List registerObservers(Meter meter, ClassLoadingMXBean classBean) { List observables = new ArrayList<>(); observables.add( diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/Cpu.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Cpu.java similarity index 90% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/Cpu.java rename to instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Cpu.java index 5014ef765736..3b713a056a4e 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/Cpu.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Cpu.java @@ -3,11 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; import static java.util.concurrent.TimeUnit.SECONDS; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.metrics.Meter; import java.util.ArrayList; import java.util.List; @@ -32,9 +31,9 @@ public class Cpu { private static final double NANOS_PER_S = SECONDS.toNanos(1); /** Register observers for java runtime CPU metrics. */ - public static List registerObservers(OpenTelemetry openTelemetry) { + public static List registerObservers(Meter meter) { return INSTANCE.registerObservers( - openTelemetry, + meter, Runtime.getRuntime()::availableProcessors, CpuMethods.processCpuTime(), CpuMethods.processCpuUtilization()); @@ -42,11 +41,10 @@ public static List registerObservers(OpenTelemetry openTelemetry) // Visible for testing List registerObservers( - OpenTelemetry openTelemetry, + Meter meter, IntSupplier availableProcessors, @Nullable Supplier processCpuTime, @Nullable Supplier processCpuUtilization) { - Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); List observables = new ArrayList<>(); if (processCpuTime != null) { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/CpuMethods.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/CpuMethods.java similarity index 98% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/CpuMethods.java rename to instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/CpuMethods.java index 479170865901..e2d56fbfa59d 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/CpuMethods.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/CpuMethods.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Experimental.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Experimental.java new file mode 100644 index 000000000000..351794fdb9d9 --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Experimental.java @@ -0,0 +1,68 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.runtimetelemetry.internal; + +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetryBuilder; +import java.util.function.BiConsumer; +import javax.annotation.Nullable; + +/** + * This class is internal and experimental. Its APIs are unstable and can change at any time. Its + * APIs (or a version of them) may be promoted to the public stable API in the future, but no + * guarantees are made. + */ +public final class Experimental { + + @Nullable + private static volatile BiConsumer setEmitExperimentalMetrics; + + @Nullable + private static volatile BiConsumer setPreferJfrMetrics; + + /** + * Sets whether experimental metrics should be emitted. Experimental metrics are those not marked + * as stable in the semantic + * conventions. + * + * @param builder the runtime telemetry builder + * @param emitExperimentalMetrics {@code true} to emit experimental metrics + */ + public static void setEmitExperimentalMetrics( + RuntimeTelemetryBuilder builder, boolean emitExperimentalMetrics) { + if (setEmitExperimentalMetrics != null) { + setEmitExperimentalMetrics.accept(builder, emitExperimentalMetrics); + } + } + + public static void internalSetEmitExperimentalMetrics( + BiConsumer setEmitExperimentalMetrics) { + Experimental.setEmitExperimentalMetrics = setEmitExperimentalMetrics; + } + + /** + * Sets whether to prefer JFR over JMX for metrics where both collection methods are available. + * When set to {@code true}, metrics available from both sources will be collected using JFR. When + * set to {@code false} (default), metrics available from both sources will be collected using + * JMX. Metrics available from only one source are unaffected by this setting. + * + * @param builder the runtime telemetry builder + * @param preferJfrMetrics {@code true} to prefer JFR over JMX where both are available + */ + public static void setPreferJfrMetrics( + RuntimeTelemetryBuilder builder, boolean preferJfrMetrics) { + if (setPreferJfrMetrics != null) { + setPreferJfrMetrics.accept(builder, preferJfrMetrics); + } + } + + public static void internalSetPreferJfrMetrics( + BiConsumer setPreferJfrMetrics) { + Experimental.setPreferJfrMetrics = setPreferJfrMetrics; + } + + private Experimental() {} +} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/FileDescriptor.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/FileDescriptor.java similarity index 79% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/FileDescriptor.java rename to instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/FileDescriptor.java index ead10c67253a..f34169c1c05b 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/FileDescriptor.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/FileDescriptor.java @@ -3,10 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; import com.sun.management.UnixOperatingSystemMXBean; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.metrics.Meter; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; @@ -30,14 +29,12 @@ private static Class loadClass(String className) { } /** Register observers for java runtime file descriptor metrics. */ - public static List registerObservers(OpenTelemetry openTelemetry) { - return registerObservers(openTelemetry, ManagementFactory.getOperatingSystemMXBean()); + public static List registerObservers(Meter meter) { + return registerObservers(meter, ManagementFactory.getOperatingSystemMXBean()); } // Visible for testing - static List registerObservers( - OpenTelemetry openTelemetry, OperatingSystemMXBean osBean) { - Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); + static List registerObservers(Meter meter, OperatingSystemMXBean osBean) { List observables = new ArrayList<>(); if (unixOperatingSystemMxBeanClass != null diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/GarbageCollector.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/GarbageCollector.java similarity index 94% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/GarbageCollector.java rename to instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/GarbageCollector.java index 6c18be0ecbbc..d6a484c8b6ec 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/GarbageCollector.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/GarbageCollector.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; import static io.opentelemetry.semconv.JvmAttributes.JVM_GC_ACTION; import static io.opentelemetry.semconv.JvmAttributes.JVM_GC_NAME; @@ -12,7 +12,6 @@ import static java.util.concurrent.TimeUnit.SECONDS; import com.sun.management.GarbageCollectionNotificationInfo; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.AttributesBuilder; @@ -58,8 +57,7 @@ public class GarbageCollector { .equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION); /** Register observers for java runtime memory metrics. */ - public static List registerObservers( - OpenTelemetry openTelemetry, boolean captureGcCause) { + public static List registerObservers(Meter meter, boolean captureGcCause) { if (!isNotificationClassPresent()) { logger.fine( "The com.sun.management.GarbageCollectionNotificationInfo class is not available;" @@ -68,7 +66,7 @@ public static List registerObservers( } return registerObservers( - openTelemetry, + meter, ManagementFactory.getGarbageCollectorMXBeans(), GarbageCollector::extractNotificationInfo, captureGcCause); @@ -76,11 +74,10 @@ public static List registerObservers( // Visible for testing public static List registerObservers( - OpenTelemetry openTelemetry, + Meter meter, List gcBeans, Function notificationInfoExtractor, boolean captureGcCause) { - Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); DoubleHistogram gcDuration = meter diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java new file mode 100644 index 000000000000..c98869a843b3 --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java @@ -0,0 +1,377 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.runtimetelemetry.internal; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; +import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetry; +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetryBuilder; +import java.util.function.BiConsumer; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + * + *

This class provides configuration methods for use by the Java agent, including backward + * compatibility support for previous configuration options. The backward compatibility methods may + * be simplified or removed in a future major version (3.0). + */ +public final class Internal { + + private static final Logger logger = Logger.getLogger(Internal.class.getName()); + + @Nullable + private static volatile BiConsumer setEnableAllJfrFeatures; + + @Nullable + private static volatile BiConsumer setDisableAllJfrFeatures; + + @Nullable + private static volatile BiConsumer + setEnableExperimentalJfrFeatures; + + @Nullable private static volatile BiConsumer setCaptureGcCause; + + @Nullable + private static volatile BiConsumer + setUseLegacyJfrCpuCountMetric; + + @Nullable + private static volatile BiConsumer setJmxInstrumentationName; + + @Nullable + private static volatile BiConsumer setJfrInstrumentationName; + + @Nullable private static volatile BiConsumer setEnableJfrFeature; + + @Nullable + private static volatile BiConsumer setDisableJfrFeature; + + @Nullable private static volatile BiConsumer setDisableJmx; + + private Internal() {} + + /** + * Sets whether all JFR features should be enabled. This is used for backward compatibility with + * the {@code runtime_telemetry_java17.enable_all} configuration option. + * + *

On Java 17+, this enables all JFR features including those that overlap with JMX metrics. + */ + public static void setEnableAllJfrFeatures( + RuntimeTelemetryBuilder builder, boolean enableAllJfr) { + if (setEnableAllJfrFeatures != null) { + setEnableAllJfrFeatures.accept(builder, enableAllJfr); + } + } + + public static void internalSetEnableAllJfrFeatures( + BiConsumer callback) { + Internal.setEnableAllJfrFeatures = callback; + } + + /** + * Sets whether all JFR features should be disabled. This is used for backward compatibility when + * running on Java 17+ but only the base {@code runtime_telemetry.enabled} option is set (without + * {@code runtime_telemetry_java17.enabled}). + */ + public static void setDisableAllJfrFeatures( + RuntimeTelemetryBuilder builder, boolean disableAllJfr) { + if (setDisableAllJfrFeatures != null) { + setDisableAllJfrFeatures.accept(builder, disableAllJfr); + } + } + + public static void internalSetDisableAllJfrFeatures( + BiConsumer callback) { + Internal.setDisableAllJfrFeatures = callback; + } + + /** + * Sets whether experimental JFR features should be enabled. This is used for backward + * compatibility with the {@code runtime_telemetry_java17.enabled} configuration option, which + * enabled experimental JFR features (context switches, locks, allocations, network I/O) but not + * experimental JMX features. + */ + public static void setEnableExperimentalJfrFeatures( + RuntimeTelemetryBuilder builder, boolean enable) { + if (setEnableExperimentalJfrFeatures != null) { + setEnableExperimentalJfrFeatures.accept(builder, enable); + } + } + + public static void internalSetEnableExperimentalJfrFeatures( + BiConsumer callback) { + Internal.setEnableExperimentalJfrFeatures = callback; + } + + /** + * Sets whether the GC cause attribute should be captured on GC duration metrics. The default is + * {@code true}. This is configurable for backward compatibility with the previous behavior where + * {@code capture_gc_cause} defaulted to {@code false}. + * + * @param builder the runtime telemetry builder + * @param captureGcCause {@code true} to capture the GC cause attribute (default) + */ + public static void setCaptureGcCause(RuntimeTelemetryBuilder builder, boolean captureGcCause) { + if (setCaptureGcCause != null) { + setCaptureGcCause.accept(builder, captureGcCause); + } + } + + public static void internalSetCaptureGcCause( + BiConsumer callback) { + Internal.setCaptureGcCause = callback; + } + + /** + * Sets whether to use the legacy metric name {@code jvm.cpu.limit} instead of the standard {@code + * jvm.cpu.count} for the JFR CPU count feature. This is for backward compatibility with the + * previous runtime-telemetry-java17 module. + * + * @param builder the runtime telemetry builder + * @param useLegacy {@code true} to use the legacy metric name + */ + public static void setUseLegacyJfrCpuCountMetric( + RuntimeTelemetryBuilder builder, boolean useLegacy) { + if (setUseLegacyJfrCpuCountMetric != null) { + setUseLegacyJfrCpuCountMetric.accept(builder, useLegacy); + } + } + + public static void internalSetUseLegacyJfrCpuCountMetric( + BiConsumer callback) { + Internal.setUseLegacyJfrCpuCountMetric = callback; + } + + /** + * Sets the instrumentation name to use for JMX metrics. This is used for backward compatibility + * to preserve the original instrumentation names when using old configuration options. + * + * @param builder the runtime telemetry builder + * @param name the instrumentation name for JMX metrics + */ + public static void setJmxInstrumentationName(RuntimeTelemetryBuilder builder, String name) { + if (setJmxInstrumentationName != null) { + setJmxInstrumentationName.accept(builder, name); + } + } + + public static void internalSetJmxInstrumentationName( + BiConsumer callback) { + Internal.setJmxInstrumentationName = callback; + } + + /** + * Sets the instrumentation name to use for JFR metrics. This is used for backward compatibility + * to preserve the original instrumentation names when using old configuration options. + * + * @param builder the runtime telemetry builder + * @param name the instrumentation name for JFR metrics + */ + public static void setJfrInstrumentationName(RuntimeTelemetryBuilder builder, String name) { + if (setJfrInstrumentationName != null) { + setJfrInstrumentationName.accept(builder, name); + } + } + + public static void internalSetJfrInstrumentationName( + BiConsumer callback) { + Internal.setJfrInstrumentationName = callback; + } + + /** + * Enables a specific JFR feature by name. This is used for backward compatibility with the + * runtime-telemetry-java17 module's per-feature control. + * + * @param builder the runtime telemetry builder + * @param featureName the JFR feature name (e.g., "CPU_COUNT_METRICS") + */ + public static void setEnableJfrFeature(RuntimeTelemetryBuilder builder, String featureName) { + if (setEnableJfrFeature != null) { + setEnableJfrFeature.accept(builder, featureName); + } + } + + public static void internalSetEnableJfrFeature( + BiConsumer callback) { + Internal.setEnableJfrFeature = callback; + } + + /** + * Disables a specific JFR feature by name. This is used for backward compatibility with the + * runtime-telemetry-java17 module's per-feature control. + * + * @param builder the runtime telemetry builder + * @param featureName the JFR feature name (e.g., "CPU_COUNT_METRICS") + */ + public static void setDisableJfrFeature(RuntimeTelemetryBuilder builder, String featureName) { + if (setDisableJfrFeature != null) { + setDisableJfrFeature.accept(builder, featureName); + } + } + + public static void internalSetDisableJfrFeature( + BiConsumer callback) { + Internal.setDisableJfrFeature = callback; + } + + /** + * Disables all JMX-based metrics. This is used for backward compatibility with the + * runtime-telemetry-java17 module's disableAllJmx() method. + * + * @param builder the runtime telemetry builder + * @param disable {@code true} to disable JMX metrics + */ + public static void setDisableJmx(RuntimeTelemetryBuilder builder, boolean disable) { + if (setDisableJmx != null) { + setDisableJmx.accept(builder, disable); + } + } + + public static void internalSetDisableJmx(BiConsumer callback) { + Internal.setDisableJmx = callback; + } + + /** + * Configures and builds a {@link RuntimeTelemetry} instance based on the provided configuration. + * + * @param openTelemetry the OpenTelemetry instance + * @param instrumentationMode the instrumentation mode ("default" or other) + * @return the configured RuntimeTelemetry, or null if runtime telemetry is disabled + */ + @Nullable + public static RuntimeTelemetry configure( + OpenTelemetry openTelemetry, String instrumentationMode) { + DeclarativeConfigProperties config = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "runtime_telemetry"); + DeclarativeConfigProperties java17Config = + DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "runtime_telemetry_java17"); + + // Determine which configuration is being used + boolean baseEnabled = config.getBoolean("enabled", instrumentationMode.equals("default")); + boolean java17Enabled = java17Config.getBoolean("enabled", false); + boolean java17EnableAll = java17Config.getBoolean("enable_all", false); + + if (!baseEnabled && !java17Enabled && !java17EnableAll) { + return null; // Nothing is enabled + } + + RuntimeTelemetryBuilder builder = RuntimeTelemetry.builder(openTelemetry); + + // Old deprecated java17 configs: FREEZE their behavior, don't apply new unified options + if (java17EnableAll) { + configureJava17EnableAll(builder, config); + return builder.build(); + } + if (java17Enabled) { + configureJava17Enabled(builder); + return builder.build(); + } + + // New unified config: handles both old java8 settings and new unified options + if (baseEnabled) { + configureUnified(builder, config); + return builder.build(); + } + + throw new AssertionError("Unreachable: at least one enabled flag must be true"); + } + + private static void configureJava17EnableAll( + RuntimeTelemetryBuilder builder, DeclarativeConfigProperties config) { + logger.warning( + "otel.instrumentation.runtime-telemetry-java17.enable-all is deprecated and will be" + + " removed in 3.0. Use otel.instrumentation.runtime-telemetry.emit-experimental-metrics" + + " and otel.instrumentation.runtime-telemetry.experimental.prefer-jfr instead."); + // For backward compatibility: route JMX metrics to java8 scope, JFR metrics to java17 scope + Internal.setJmxInstrumentationName(builder, "io.opentelemetry.runtime-telemetry-java8"); + Internal.setJfrInstrumentationName(builder, "io.opentelemetry.runtime-telemetry-java17"); + Internal.setEnableAllJfrFeatures(builder, true); + Internal.setUseLegacyJfrCpuCountMetric(builder, true); + + // Check if base config also has emit_experimental_telemetry enabled (for JMX experimental) + boolean emitExperimentalTelemetry = + config.getBoolean("emit_experimental_telemetry/development", false); + boolean emitExperimentalMetrics = + config.getBoolean("emit_experimental_metrics/development", false); + if (emitExperimentalTelemetry || emitExperimentalMetrics) { + if (emitExperimentalTelemetry) { + logger.warning( + "otel.instrumentation.runtime-telemetry.emit-experimental-telemetry is deprecated and" + + " will be removed in 3.0. Use" + + " otel.instrumentation.runtime-telemetry.emit-experimental-metrics instead."); + } + Experimental.setEmitExperimentalMetrics(builder, true); + } + } + + private static void configureJava17Enabled(RuntimeTelemetryBuilder builder) { + logger.warning( + "otel.instrumentation.runtime-telemetry-java17.enabled is deprecated and will be" + + " removed in 3.0. Use otel.instrumentation.runtime-telemetry.emit-experimental-metrics" + + " for experimental JFR features."); + // Enable default JFR features: context switches, CPU count, locks, allocations, network I/O + Internal.setEnableJfrFeature(builder, "CONTEXT_SWITCH_METRICS"); + Internal.setEnableJfrFeature(builder, "CPU_COUNT_METRICS"); + Internal.setEnableJfrFeature(builder, "LOCK_METRICS"); + Internal.setEnableJfrFeature(builder, "MEMORY_ALLOCATION_METRICS"); + Internal.setEnableJfrFeature(builder, "NETWORK_IO_METRICS"); + Internal.setUseLegacyJfrCpuCountMetric(builder, true); + // For backward compatibility: OLD java17 module used java8's JMX factory, so JMX -> java8 scope + Internal.setJmxInstrumentationName(builder, "io.opentelemetry.runtime-telemetry-java8"); + Internal.setJfrInstrumentationName(builder, "io.opentelemetry.runtime-telemetry-java17"); + } + + private static void configureUnified( + RuntimeTelemetryBuilder builder, DeclarativeConfigProperties config) { + // Check if user is using new unified config options + boolean emitExperimentalMetrics = + config.getBoolean("emit_experimental_metrics/development", false); + boolean preferJfr = config.getBoolean("prefer_jfr/development", false); + boolean newConfig = emitExperimentalMetrics || preferJfr; + + if (newConfig) { + // New unified config: Use new instrumentation name for both JMX and JFR + Internal.setJmxInstrumentationName(builder, "io.opentelemetry.runtime-telemetry"); + Internal.setJfrInstrumentationName(builder, "io.opentelemetry.runtime-telemetry"); + } else { + // Old java8 config: JMX-only, disable JFR for backward compatibility + Internal.setDisableAllJfrFeatures(builder, true); + Internal.setJmxInstrumentationName(builder, "io.opentelemetry.runtime-telemetry-java8"); + Internal.setJfrInstrumentationName(builder, "io.opentelemetry.runtime-telemetry-java8"); + } + + // Apply emit_experimental_metrics (supports both old and new names) + boolean emitExperimentalTelemetry = + config.getBoolean("emit_experimental_telemetry/development", false); + if (emitExperimentalTelemetry) { + logger.warning( + "otel.instrumentation.runtime-telemetry.emit-experimental-telemetry is deprecated and" + + " will be removed in 3.0. Use" + + " otel.instrumentation.runtime-telemetry.emit-experimental-metrics instead."); + } + if (emitExperimentalMetrics || emitExperimentalTelemetry) { + Experimental.setEmitExperimentalMetrics(builder, true); + } + + // Apply prefer_jfr + if (preferJfr) { + Experimental.setPreferJfrMetrics(builder, true); + } + + // Apply capture_gc_cause + boolean captureGcCause = config.getBoolean("capture_gc_cause", false); + if (captureGcCause) { + logger.warning( + "otel.instrumentation.runtime-telemetry.capture-gc-cause is deprecated and will be" + + " removed in 3.0. GC cause will always be captured."); + } + Internal.setCaptureGcCause(builder, captureGcCause); + } +} diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrConfig.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrConfig.java new file mode 100644 index 000000000000..5eede69aa060 --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrConfig.java @@ -0,0 +1,54 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.runtimetelemetry.internal; + +import io.opentelemetry.api.metrics.Meter; +import javax.annotation.Nullable; + +/** + * Configuration holder for JFR telemetry. On Java 8, this is a no-op implementation since JFR is + * not available. On Java 17+, this is replaced by an implementation that manages JFR features. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public class JfrConfig { + + public static JfrConfig create() { + return new JfrConfig(); + } + + public JfrConfig enableAllFeatures() { + return this; + } + + public JfrConfig disableAllFeatures() { + return this; + } + + public JfrConfig enableExperimentalFeatures() { + return this; + } + + public JfrConfig enableFeature(String featureName) { + return this; + } + + public JfrConfig disableFeature(String featureName) { + return this; + } + + public JfrConfig setUseLegacyJfrCpuCountMetric(boolean useLegacy) { + return this; + } + + @Nullable + public AutoCloseable buildJfrTelemetry(boolean preferJfrMetrics, Meter meter) { + return null; + } + + private JfrConfig() {} +} diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/JmxRuntimeMetricsFactory.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/JmxRuntimeMetricsFactory.java new file mode 100644 index 000000000000..f45823aabf6b --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/JmxRuntimeMetricsFactory.java @@ -0,0 +1,45 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.runtimetelemetry.internal; + +import io.opentelemetry.api.metrics.Meter; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public class JmxRuntimeMetricsFactory { + public static List buildObservables( + boolean emitExperimentalTelemetry, + boolean captureGcCause, + boolean preferJfrMetrics, + Meter meter) { + // Set up metrics gathered by JMX + // When preferJfrMetrics is true, skip JMX metrics that have JFR equivalents + List observables = new ArrayList<>(); + if (!preferJfrMetrics) { + observables.addAll(Classes.registerObservers(meter)); + observables.addAll(Cpu.registerObservers(meter)); + observables.addAll(GarbageCollector.registerObservers(meter, captureGcCause)); + observables.addAll(MemoryPools.registerObservers(meter)); + observables.addAll(Threads.registerObservers(meter)); + } + if (emitExperimentalTelemetry) { + if (!preferJfrMetrics) { + observables.addAll(BufferPools.registerObservers(meter)); + observables.addAll(SystemCpu.registerObservers(meter)); + observables.addAll(MemoryInit.registerObservers(meter)); + } + // FileDescriptor has no JFR equivalent, always register + observables.addAll(FileDescriptor.registerObservers(meter)); + } + return observables; + } + + private JmxRuntimeMetricsFactory() {} +} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryInit.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryInit.java similarity index 84% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryInit.java rename to instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryInit.java index 11a7a5ba5262..771f1991d46c 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryInit.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryInit.java @@ -3,13 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; import static io.opentelemetry.semconv.JvmAttributes.JVM_MEMORY_POOL_NAME; import static io.opentelemetry.semconv.JvmAttributes.JVM_MEMORY_TYPE; import static java.util.Collections.singletonList; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.metrics.ObservableLongMeasurement; @@ -31,15 +30,12 @@ public final class MemoryInit { /** Register observers for java runtime experimental memory metrics. */ - public static List registerObservers(OpenTelemetry openTelemetry) { - return registerObservers(openTelemetry, ManagementFactory.getMemoryPoolMXBeans()); + public static List registerObservers(Meter meter) { + return registerObservers(meter, ManagementFactory.getMemoryPoolMXBeans()); } // Visible for testing - static List registerObservers( - OpenTelemetry openTelemetry, List poolBeans) { - - Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); + static List registerObservers(Meter meter, List poolBeans) { return singletonList( meter .upDownCounterBuilder("jvm.memory.init") diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryPools.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryPools.java similarity index 91% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryPools.java rename to instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryPools.java index 95f79d7adad7..0691207d0d13 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryPools.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryPools.java @@ -3,12 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; import static io.opentelemetry.semconv.JvmAttributes.JVM_MEMORY_POOL_NAME; import static io.opentelemetry.semconv.JvmAttributes.JVM_MEMORY_TYPE; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.Meter; @@ -35,14 +34,13 @@ public class MemoryPools { /** Register observers for java runtime memory metrics. */ - public static List registerObservers(OpenTelemetry openTelemetry) { - return registerObservers(openTelemetry, ManagementFactory.getMemoryPoolMXBeans()); + public static List registerObservers(Meter meter) { + return registerObservers(meter, ManagementFactory.getMemoryPoolMXBeans()); } // Visible for testing public static List registerObservers( - OpenTelemetry openTelemetry, List poolBeans) { - Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); + Meter meter, List poolBeans) { List observables = new ArrayList<>(); observables.add( diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/SystemCpu.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/SystemCpu.java similarity index 79% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/SystemCpu.java rename to instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/SystemCpu.java index 735ed1798c21..50bcda59410d 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/SystemCpu.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/SystemCpu.java @@ -3,9 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.metrics.Meter; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; @@ -23,20 +22,15 @@ public final class SystemCpu { /** Register observers for java runtime experimental CPU metrics. */ - public static List registerObservers(OpenTelemetry openTelemetry) { + public static List registerObservers(Meter meter) { return registerObservers( - openTelemetry, - ManagementFactory.getOperatingSystemMXBean(), - CpuMethods.systemCpuUtilization()); + meter, ManagementFactory.getOperatingSystemMXBean(), CpuMethods.systemCpuUtilization()); } // Visible for testing static List registerObservers( - OpenTelemetry openTelemetry, - OperatingSystemMXBean osBean, - @Nullable Supplier systemCpuUtilization) { + Meter meter, OperatingSystemMXBean osBean, @Nullable Supplier systemCpuUtilization) { - Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); List observables = new ArrayList<>(); observables.add( meter diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/Threads.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Threads.java similarity index 86% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/Threads.java rename to instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Threads.java index 4fc4e1aebf00..5edbb5c8574f 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/Threads.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Threads.java @@ -3,13 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; import static io.opentelemetry.semconv.JvmAttributes.JVM_THREAD_DAEMON; import static io.opentelemetry.semconv.JvmAttributes.JVM_THREAD_STATE; import static java.util.Objects.requireNonNull; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.metrics.ObservableLongMeasurement; @@ -44,36 +43,34 @@ public class Threads { static final Threads INSTANCE = new Threads(); /** Register observers for java runtime class metrics. */ - public static List registerObservers(OpenTelemetry openTelemetry) { - return INSTANCE.registerObservers(openTelemetry, useThreads()); + public static List registerObservers(Meter meter) { + return INSTANCE.registerObservers(meter, useThreads()); } - private List registerObservers(OpenTelemetry openTelemetry, boolean useThread) { + private List registerObservers(Meter meter, boolean useThread) { if (useThread) { - return registerObservers(openTelemetry, Threads::getThreads); + return registerObservers(meter, Threads::getThreads); } - return registerObservers(openTelemetry, ManagementFactory.getThreadMXBean()); + return registerObservers(meter, ManagementFactory.getThreadMXBean()); } // Visible for testing - List registerObservers(OpenTelemetry openTelemetry, ThreadMXBean threadBean) { + List registerObservers(Meter meter, ThreadMXBean threadBean) { return registerObservers( - openTelemetry, + meter, isJava9OrNewer() ? Threads::java9AndNewerCallback : Threads::java8Callback, threadBean); } // Visible for testing - List registerObservers( - OpenTelemetry openTelemetry, Supplier threadSupplier) { - return registerObservers(openTelemetry, Threads::java8ThreadCallback, threadSupplier); + List registerObservers(Meter meter, Supplier threadSupplier) { + return registerObservers(meter, Threads::java8ThreadCallback, threadSupplier); } private static List registerObservers( - OpenTelemetry openTelemetry, + Meter meter, Function> callbackProvider, T threadInfo) { - Meter meter = JmxRuntimeMetricsUtil.getMeter(openTelemetry); List observables = new ArrayList<>(); observables.add( diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/Constants.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/Constants.java similarity index 98% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/Constants.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/Constants.java index d4f3e79d38e8..cfd35f63f3e5 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/Constants.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/Constants.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/DurationUtil.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/DurationUtil.java similarity index 90% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/DurationUtil.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/DurationUtil.java index 27d5110f9df9..23437d6a88ba 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/DurationUtil.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/DurationUtil.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; import static java.util.concurrent.TimeUnit.SECONDS; diff --git a/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java new file mode 100644 index 000000000000..7b4a7c9e5a57 --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java @@ -0,0 +1,100 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.runtimetelemetry.internal; + +import io.opentelemetry.api.metrics.Meter; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.buffer.DirectBufferStatisticsHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.classes.ClassesLoadedHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.container.ContainerConfigurationHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.cpu.ContextSwitchRateHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.cpu.LongLockHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.cpu.OverallCpuLoadHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.garbagecollection.G1GarbageCollectionHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.garbagecollection.OldGarbageCollectionHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.garbagecollection.YoungGarbageCollectionHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.memory.CodeCacheConfigurationHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.memory.G1HeapSummaryHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.memory.MetaspaceSummaryHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.memory.ObjectAllocationInNewTlabHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.memory.ObjectAllocationOutsideTlabHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.memory.ParallelHeapSummaryHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.network.NetworkReadHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.network.NetworkWriteHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.threads.ThreadCountHandler; +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.function.Predicate; + +final class HandlerRegistry { + + private HandlerRegistry() {} + + @SuppressWarnings("StatementSwitchToExpressionSwitch") + static List getHandlers( + Meter meter, Predicate featurePredicate, boolean useLegacyCpuCountMetric) { + + List handlers = new ArrayList(); + for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) { + String name = bean.getName(); + switch (name) { + case "G1 Young Generation": + handlers.add(new G1HeapSummaryHandler(meter)); + handlers.add(new G1GarbageCollectionHandler(meter)); + break; + + case "Copy": + handlers.add(new YoungGarbageCollectionHandler(meter, name)); + break; + + case "PS Scavenge": + handlers.add(new YoungGarbageCollectionHandler(meter, name)); + handlers.add(new ParallelHeapSummaryHandler(meter)); + break; + + case "G1 Old Generation": + case "PS MarkSweep": + case "MarkSweepCompact": + handlers.add(new OldGarbageCollectionHandler(meter, name)); + break; + + default: + // If none of the above GCs are detected, no action. + } + } + + List basicHandlers = + List.of( + new ObjectAllocationInNewTlabHandler(meter), + new ObjectAllocationOutsideTlabHandler(meter), + new NetworkReadHandler(meter), + new NetworkWriteHandler(meter), + new ContextSwitchRateHandler(meter), + new OverallCpuLoadHandler(meter), + new ContainerConfigurationHandler(meter, useLegacyCpuCountMetric), + new LongLockHandler(meter), + new ThreadCountHandler(meter), + new ClassesLoadedHandler(meter), + new MetaspaceSummaryHandler(meter), + new CodeCacheConfigurationHandler(meter), + new DirectBufferStatisticsHandler(meter)); + handlers.addAll(basicHandlers); + + // Filter and close disabled handlers + Iterator iter = handlers.iterator(); + while (iter.hasNext()) { + RecordedEventHandler handler = iter.next(); + if (!featurePredicate.test(handler.getFeature())) { + handler.close(); + iter.remove(); + } + } + + return handlers; + } +} diff --git a/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrConfig.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrConfig.java new file mode 100644 index 000000000000..a2583c791f13 --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrConfig.java @@ -0,0 +1,219 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.runtimetelemetry.internal; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.metrics.Meter; +import java.io.Closeable; +import java.util.Arrays; +import java.util.EnumMap; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.function.Predicate; +import javax.annotation.Nullable; +import jdk.jfr.EventSettings; +import jdk.jfr.FlightRecorder; +import jdk.jfr.consumer.RecordingStream; + +/** + * Configuration holder for JFR telemetry. On Java 17+, this implementation manages JFR features and + * creates JFR telemetry. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public class JfrConfig { + + // Visible for testing + public final EnumMap enabledFeatureMap; + + private boolean useLegacyCpuCountMetric = false; + + /** Create a new JfrConfig with default feature settings. */ + public static JfrConfig create() { + return new JfrConfig(); + } + + protected JfrConfig() { + enabledFeatureMap = new EnumMap<>(JfrFeature.class); + // By default, enable JFR features that don't overlap with JMX and are not experimental + for (JfrFeature feature : JfrFeature.values()) { + enabledFeatureMap.put(feature, !feature.overlapsWithJmx() && !feature.isExperimental()); + } + } + + /** Enable all JFR features. */ + @CanIgnoreReturnValue + public JfrConfig enableAllFeatures() { + Arrays.stream(JfrFeature.values()).forEach(feature -> enabledFeatureMap.put(feature, true)); + return this; + } + + /** Disable all JFR features. */ + @CanIgnoreReturnValue + public JfrConfig disableAllFeatures() { + Arrays.stream(JfrFeature.values()).forEach(feature -> enabledFeatureMap.put(feature, false)); + return this; + } + + /** Enable experimental JFR features. */ + @CanIgnoreReturnValue + public JfrConfig enableExperimentalFeatures() { + Arrays.stream(JfrFeature.values()) + .filter(JfrFeature::isExperimental) + .forEach(feature -> enabledFeatureMap.put(feature, true)); + return this; + } + + /** Enable a specific JFR feature. */ + @CanIgnoreReturnValue + public JfrConfig enableFeature(JfrFeature feature) { + enabledFeatureMap.put(feature, true); + return this; + } + + /** Enable a specific JFR feature by name. */ + @CanIgnoreReturnValue + public JfrConfig enableFeature(String featureName) { + enableFeature(JfrFeature.valueOf(featureName)); + return this; + } + + /** Disable a specific JFR feature. */ + @CanIgnoreReturnValue + public JfrConfig disableFeature(JfrFeature feature) { + enabledFeatureMap.put(feature, false); + return this; + } + + /** Disable a specific JFR feature by name. */ + @CanIgnoreReturnValue + public JfrConfig disableFeature(String featureName) { + disableFeature(JfrFeature.valueOf(featureName)); + return this; + } + + /** + * Sets whether to use the legacy metric name {@code jvm.cpu.limit} instead of the standard {@code + * jvm.cpu.count}. This is for backward compatibility with previous versions. + */ + @CanIgnoreReturnValue + public JfrConfig setUseLegacyJfrCpuCountMetric(boolean useLegacy) { + this.useLegacyCpuCountMetric = useLegacy; + return this; + } + + /** + * Build JFR telemetry based on the current configuration. + * + * @param preferJfrMetrics if true, enable JFR features that overlap with JMX + * @param meter the Meter to use for metrics + * @return the JFR telemetry closeable, or null if JFR is not available or all features are + * disabled + */ + @Nullable + public AutoCloseable buildJfrTelemetry(boolean preferJfrMetrics, Meter meter) { + // If preferJfrMetrics is set, enable JFR features that overlap with JMX + if (preferJfrMetrics) { + for (JfrFeature feature : JfrFeature.values()) { + if (feature.overlapsWithJmx()) { + enabledFeatureMap.put(feature, true); + } + } + } + + if (enabledFeatureMap.values().stream().noneMatch(isEnabled -> isEnabled)) { + return null; + } + return JfrRuntimeMetrics.build(meter, enabledFeatureMap::get, useLegacyCpuCountMetric); + } + + /** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ + public static class JfrRuntimeMetrics implements Closeable { + private final List recordedEventHandlers; + private final RecordingStream recordingStream; + private final CountDownLatch startUpLatch = new CountDownLatch(1); + private volatile boolean closed = false; + + private JfrRuntimeMetrics( + Meter meter, Predicate featurePredicate, boolean useLegacyCpuCountMetric) { + this.recordedEventHandlers = + HandlerRegistry.getHandlers(meter, featurePredicate, useLegacyCpuCountMetric); + recordingStream = new RecordingStream(); + recordedEventHandlers.forEach( + handler -> { + EventSettings eventSettings = recordingStream.enable(handler.getEventName()); + handler.getPollingDuration().ifPresent(eventSettings::withPeriod); + handler.getThreshold().ifPresent(eventSettings::withThreshold); + recordingStream.onEvent(handler.getEventName(), handler); + }); + recordingStream.onMetadata(event -> startUpLatch.countDown()); + Thread daemonRunner = + new Thread(this::startRecordingStream, "OpenTelemetry JFR-Metrics-Runner"); + daemonRunner.setDaemon(true); + daemonRunner.setContextClassLoader(null); + daemonRunner.start(); + } + + private void startRecordingStream() { + if (closed) { + return; + } + + try { + recordingStream.start(); + } catch (IllegalStateException exception) { + // Can happen when close is called at the same time as start + if (!closed) { + throw exception; + } + } + } + + @Nullable + static JfrRuntimeMetrics build( + Meter meter, Predicate featurePredicate, boolean useLegacyCpuCountMetric) { + if (!isJfrAvailable()) { + return null; + } + return new JfrRuntimeMetrics(meter, featurePredicate, useLegacyCpuCountMetric); + } + + @Override + public void close() { + closed = true; + recordingStream.close(); + recordedEventHandlers.forEach(RecordedEventHandler::close); + } + + // Visible for testing + public List getRecordedEventHandlers() { + return recordedEventHandlers; + } + + // Visible for testing + public RecordingStream getRecordingStream() { + return recordingStream; + } + + // Visible for testing + public CountDownLatch getStartUpLatch() { + return startUpLatch; + } + + private static boolean isJfrAvailable() { + try { + return FlightRecorder.isAvailable(); + } catch (Throwable e) { + // NoClassDefFoundError, UnsatisfiedLinkError (native images), or other issues + return false; + } + } + } +} diff --git a/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrFeature.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrFeature.java new file mode 100644 index 000000000000..598462e9bc94 --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/JfrFeature.java @@ -0,0 +1,49 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.runtimetelemetry.internal; + +/** + * Enumeration of JFR features, used internally to control which JFR events are registered. + * + *

Features that overlap with stable JMX-based instrumentation are disabled by default to avoid + * duplicate metrics. Experimental features (those not marked stable in the semantic conventions) + * are also disabled by default and require {@code emit_experimental_metrics=true} to enable. + * + *

This class is internal and is hence not for public use. Its APIs are unstable and can change + * at any time. + */ +public enum JfrFeature { + BUFFER_METRICS(/* overlapsWithJmx= */ true, /* experimental= */ true), + CLASS_LOAD_METRICS(/* overlapsWithJmx= */ true, /* experimental= */ false), + CONTEXT_SWITCH_METRICS(/* overlapsWithJmx= */ false, /* experimental= */ true), + CPU_COUNT_METRICS(/* overlapsWithJmx= */ true, /* experimental= */ false), + CPU_UTILIZATION_METRICS(/* overlapsWithJmx= */ true, /* experimental= */ false), + GC_DURATION_METRICS(/* overlapsWithJmx= */ true, /* experimental= */ false), + LOCK_METRICS(/* overlapsWithJmx= */ false, /* experimental= */ true), + MEMORY_ALLOCATION_METRICS(/* overlapsWithJmx= */ false, /* experimental= */ true), + MEMORY_POOL_METRICS(/* overlapsWithJmx= */ true, /* experimental= */ false), + NETWORK_IO_METRICS(/* overlapsWithJmx= */ false, /* experimental= */ true), + THREAD_METRICS(/* overlapsWithJmx= */ true, /* experimental= */ false), + ; + + private final boolean overlapsWithJmx; + private final boolean experimental; + + JfrFeature(boolean overlapsWithJmx, boolean experimental) { + this.overlapsWithJmx = overlapsWithJmx; + this.experimental = experimental; + } + + /** Returns true if this JFR feature overlaps with JMX-based metrics. */ + public boolean overlapsWithJmx() { + return overlapsWithJmx; + } + + /** Returns true if this JFR feature produces experimental (non-stable) metrics. */ + public boolean isExperimental() { + return experimental; + } +} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RecordedEventHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/RecordedEventHandler.java similarity index 93% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RecordedEventHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/RecordedEventHandler.java index 16df1a9405a5..920fc0eafb4e 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RecordedEventHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/RecordedEventHandler.java @@ -3,9 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; import java.time.Duration; import java.util.List; import java.util.Optional; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/buffer/DirectBufferStatisticsHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/buffer/DirectBufferStatisticsHandler.java similarity index 90% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/buffer/DirectBufferStatisticsHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/buffer/DirectBufferStatisticsHandler.java index 2f9ed50b2c26..12e2d46770a7 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/buffer/DirectBufferStatisticsHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/buffer/DirectBufferStatisticsHandler.java @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.buffer; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.buffer; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.time.Duration; import java.util.ArrayList; import java.util.List; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/classes/ClassesLoadedHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/classes/ClassesLoadedHandler.java similarity index 89% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/classes/ClassesLoadedHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/classes/ClassesLoadedHandler.java index 98bee7942725..47e5ec8a8256 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/classes/ClassesLoadedHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/classes/ClassesLoadedHandler.java @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.classes; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.classes; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.time.Duration; import java.util.ArrayList; import java.util.List; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/container/ContainerConfigurationHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/container/ContainerConfigurationHandler.java similarity index 51% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/container/ContainerConfigurationHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/container/ContainerConfigurationHandler.java index 09220d3c6beb..7e29caa8a4fc 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/container/ContainerConfigurationHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/container/ContainerConfigurationHandler.java @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.container; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.container; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.util.ArrayList; import java.util.List; import jdk.jfr.consumer.RecordedEvent; @@ -18,7 +18,10 @@ * any time. */ public final class ContainerConfigurationHandler implements RecordedEventHandler { - private static final String METRIC_NAME = "jvm.cpu.limit"; + private static final String METRIC_NAME = "jvm.cpu.count"; + // Legacy metric name for backward compatibility with runtime-telemetry-java17 module + private static final String LEGACY_METRIC_NAME = "jvm.cpu.limit"; + private static final String EVENT_NAME = "jdk.ContainerConfiguration"; private static final String EFFECTIVE_CPU_COUNT = "effectiveCpuCount"; @@ -26,12 +29,15 @@ public final class ContainerConfigurationHandler implements RecordedEventHandler private volatile long value = 0L; - public ContainerConfigurationHandler(Meter meter) { - observables.add( - meter - .upDownCounterBuilder(METRIC_NAME) - .setUnit(Constants.ONE) - .buildWithCallback(codm -> codm.record(value))); + public ContainerConfigurationHandler(Meter meter, boolean useLegacyMetric) { + var builder = + useLegacyMetric + ? meter.upDownCounterBuilder(LEGACY_METRIC_NAME).setUnit(Constants.ONE) + : meter + .upDownCounterBuilder(METRIC_NAME) + .setUnit("{cpu}") + .setDescription("Number of processors available to the Java virtual machine."); + observables.add(builder.buildWithCallback(codm -> codm.record(value))); } @Override diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/cpu/ContextSwitchRateHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/cpu/ContextSwitchRateHandler.java similarity index 81% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/cpu/ContextSwitchRateHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/cpu/ContextSwitchRateHandler.java index 39a3dc6efa7c..fea1769fecb1 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/cpu/ContextSwitchRateHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/cpu/ContextSwitchRateHandler.java @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.cpu; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.cpu; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.time.Duration; import java.util.ArrayList; import java.util.List; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/cpu/LongLockHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/cpu/LongLockHandler.java similarity index 80% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/cpu/LongLockHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/cpu/LongLockHandler.java index b3dfad486887..cc1d66691a92 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/cpu/LongLockHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/cpu/LongLockHandler.java @@ -3,15 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.cpu; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.cpu; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.DurationUtil; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.DurationUtil; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.time.Duration; import java.util.Optional; import jdk.jfr.consumer.RecordedEvent; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/cpu/OverallCpuLoadHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/cpu/OverallCpuLoadHandler.java similarity index 88% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/cpu/OverallCpuLoadHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/cpu/OverallCpuLoadHandler.java index 260b26857c9e..59ffbfc6829b 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/cpu/OverallCpuLoadHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/cpu/OverallCpuLoadHandler.java @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.cpu; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.cpu; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.time.Duration; import java.util.ArrayList; import java.util.List; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/garbagecollection/G1GarbageCollectionHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/garbagecollection/G1GarbageCollectionHandler.java similarity index 78% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/garbagecollection/G1GarbageCollectionHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/garbagecollection/G1GarbageCollectionHandler.java index 2ac74dd9b8f9..089fededcd32 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/garbagecollection/G1GarbageCollectionHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/garbagecollection/G1GarbageCollectionHandler.java @@ -3,15 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.garbagecollection; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.garbagecollection; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.DurationUtil; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.DurationUtil; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.time.Duration; import java.util.Optional; import jdk.jfr.consumer.RecordedEvent; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/garbagecollection/OldGarbageCollectionHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/garbagecollection/OldGarbageCollectionHandler.java similarity index 78% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/garbagecollection/OldGarbageCollectionHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/garbagecollection/OldGarbageCollectionHandler.java index 7fbaeeadefed..840c3fb2aa7b 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/garbagecollection/OldGarbageCollectionHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/garbagecollection/OldGarbageCollectionHandler.java @@ -3,15 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.garbagecollection; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.garbagecollection; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.DurationUtil; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.DurationUtil; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.time.Duration; import java.util.Optional; import jdk.jfr.consumer.RecordedEvent; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/garbagecollection/YoungGarbageCollectionHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/garbagecollection/YoungGarbageCollectionHandler.java similarity index 79% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/garbagecollection/YoungGarbageCollectionHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/garbagecollection/YoungGarbageCollectionHandler.java index 53fa2f22da81..8fc75c8079d3 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/garbagecollection/YoungGarbageCollectionHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/garbagecollection/YoungGarbageCollectionHandler.java @@ -3,15 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.garbagecollection; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.garbagecollection; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.DurationUtil; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.DurationUtil; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.time.Duration; import java.util.Optional; import jdk.jfr.consumer.RecordedEvent; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/CodeCacheConfigurationHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/CodeCacheConfigurationHandler.java similarity index 84% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/CodeCacheConfigurationHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/CodeCacheConfigurationHandler.java index 1b11c80ea4d1..1515722a22a7 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/CodeCacheConfigurationHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/CodeCacheConfigurationHandler.java @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.memory; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.time.Duration; import java.util.ArrayList; import java.util.List; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/G1HeapSummaryHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/G1HeapSummaryHandler.java similarity index 93% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/G1HeapSummaryHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/G1HeapSummaryHandler.java index 05c8a49fb5cc..a292e0bdfe31 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/G1HeapSummaryHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/G1HeapSummaryHandler.java @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.memory; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/MetaspaceSummaryHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/MetaspaceSummaryHandler.java similarity index 91% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/MetaspaceSummaryHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/MetaspaceSummaryHandler.java index fcbe93cafbab..06f44688e917 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/MetaspaceSummaryHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/MetaspaceSummaryHandler.java @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.memory; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -128,8 +128,8 @@ private static void doIfAvailable( return; } Object value = event.getValue(field); - if (value instanceof RecordedObject) { - closure.accept((RecordedObject) value); + if (value instanceof RecordedObject recordedObject) { + closure.accept(recordedObject); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/ObjectAllocationInNewTlabHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/ObjectAllocationInNewTlabHandler.java similarity index 82% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/ObjectAllocationInNewTlabHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/ObjectAllocationInNewTlabHandler.java index c04de5bf944c..5d960d3270cc 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/ObjectAllocationInNewTlabHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/ObjectAllocationInNewTlabHandler.java @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.memory; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.LongHistogram; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import jdk.jfr.consumer.RecordedEvent; /** diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/ObjectAllocationOutsideTlabHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/ObjectAllocationOutsideTlabHandler.java similarity index 82% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/ObjectAllocationOutsideTlabHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/ObjectAllocationOutsideTlabHandler.java index 30dfc78c0126..a26098eaf623 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/ObjectAllocationOutsideTlabHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/ObjectAllocationOutsideTlabHandler.java @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.memory; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.LongHistogram; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import jdk.jfr.consumer.RecordedEvent; /** diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/ParallelHeapSummaryHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/ParallelHeapSummaryHandler.java similarity index 94% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/ParallelHeapSummaryHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/ParallelHeapSummaryHandler.java index 3ec8e57c845d..1ec213b187f0 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/memory/ParallelHeapSummaryHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/memory/ParallelHeapSummaryHandler.java @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.memory; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -145,8 +145,8 @@ private static void doIfAvailable( return; } Object value = event.getValue(field); - if (value instanceof RecordedObject) { - closure.accept((RecordedObject) value); + if (value instanceof RecordedObject recordedObject) { + closure.accept(recordedObject); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/network/NetworkReadHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/network/NetworkReadHandler.java similarity index 81% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/network/NetworkReadHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/network/NetworkReadHandler.java index e84ca15a2315..4ce834b41bf1 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/network/NetworkReadHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/network/NetworkReadHandler.java @@ -3,16 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.network; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.network; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; import io.opentelemetry.api.metrics.LongHistogram; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.DurationUtil; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.DurationUtil; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import jdk.jfr.consumer.RecordedEvent; /** diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/network/NetworkWriteHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/network/NetworkWriteHandler.java similarity index 85% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/network/NetworkWriteHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/network/NetworkWriteHandler.java index 8d0124ff4bcf..9ccdc1031d0f 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/network/NetworkWriteHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/network/NetworkWriteHandler.java @@ -3,16 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.network; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.network; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.DoubleHistogram; import io.opentelemetry.api.metrics.LongHistogram; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.DurationUtil; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.DurationUtil; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import jdk.jfr.consumer.RecordedEvent; // jdk.SocketWrite { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/threads/ThreadCountHandler.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/threads/ThreadCountHandler.java similarity index 85% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/threads/ThreadCountHandler.java rename to instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/threads/ThreadCountHandler.java index ef741482cc3f..b936ec957fa7 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/threads/ThreadCountHandler.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/threads/ThreadCountHandler.java @@ -3,13 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal.threads; +package io.opentelemetry.instrumentation.runtimetelemetry.internal.threads; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.instrumentation.runtimemetrics.java17.JfrFeature; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.RecordedEventHandler; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -23,7 +23,7 @@ public final class ThreadCountHandler implements RecordedEventHandler { private static final String METRIC_NAME = "jvm.thread.count"; private static final String EVENT_NAME = "jdk.JavaThreadStatistics"; - private static final String METRIC_DESCRIPTION = "Number of executing threads"; + private static final String METRIC_DESCRIPTION = "Number of executing platform threads."; private static final Attributes ATTR_DAEMON_TRUE = Attributes.of(Constants.ATTR_DAEMON, true); private static final Attributes ATTR_DAEMON_FALSE = Attributes.of(Constants.ATTR_DAEMON, false); diff --git a/instrumentation/runtime-telemetry/library/src/main/resources/META-INF/native-image/reflect-config.json b/instrumentation/runtime-telemetry/library/src/main/resources/META-INF/native-image/reflect-config.json new file mode 100644 index 000000000000..1e250d63300c --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/main/resources/META-INF/native-image/reflect-config.json @@ -0,0 +1,10 @@ +[ + { + "name": "com.sun.management.OperatingSystemMXBean", + "allPublicMethods": true + }, + { + "name": "com.ibm.lang.management.OperatingSystemMXBean", + "allPublicMethods": true + } +] diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/BufferPoolsTest.java b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/BufferPoolsTest.java similarity index 89% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/BufferPoolsTest.java rename to instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/BufferPoolsTest.java index 5cbf8c87fa1f..f2d5b87cd915 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/BufferPoolsTest.java +++ b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/BufferPoolsTest.java @@ -3,10 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; 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; @@ -52,16 +51,15 @@ void registerObservers() { when(bufferPoolBean.getTotalCapacity()).thenReturn(11L); when(bufferPoolBean.getCount()).thenReturn(12L); - BufferPools.registerObservers(testing.getOpenTelemetry(), beans); + BufferPools.registerObservers(testing.getOpenTelemetry().getMeter("test"), beans); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.buffer.memory.used", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Measure of memory used by buffers.") .hasUnit("By") .hasLongSumSatisfying( @@ -74,13 +72,12 @@ void registerObservers() { stringKey("jvm.buffer.pool.name"), "buffer_pool_1"))))); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.buffer.memory.limit", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Measure of total memory capacity of buffers.") .hasUnit("By") .hasLongSumSatisfying( @@ -93,13 +90,12 @@ void registerObservers() { stringKey("jvm.buffer.pool.name"), "buffer_pool_1"))))); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.buffer.count", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Number of buffers in the pool.") .hasUnit("{buffer}") .hasLongSumSatisfying( diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/ClassesTest.java b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/ClassesTest.java similarity index 85% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/ClassesTest.java rename to instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/ClassesTest.java index 5399e84efa47..34069b83250d 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/ClassesTest.java +++ b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/ClassesTest.java @@ -3,9 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; -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; @@ -33,16 +32,15 @@ void registerObservers() { when(classBean.getUnloadedClassCount()).thenReturn(2L); when(classBean.getLoadedClassCount()).thenReturn(1); - Classes.INSTANCE.registerObservers(testing.getOpenTelemetry(), classBean); + Classes.INSTANCE.registerObservers(testing.getOpenTelemetry().getMeter("test"), classBean); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.class.loaded", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Number of classes loaded since JVM start.") .hasUnit("{class}") .hasLongSumSatisfying( @@ -52,13 +50,12 @@ void registerObservers() { point -> point.hasValue(3).hasAttributes(Attributes.empty()))))); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.class.unloaded", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Number of classes unloaded since JVM start.") .hasUnit("{class}") .hasLongSumSatisfying( @@ -68,13 +65,12 @@ void registerObservers() { point -> point.hasValue(2).hasAttributes(Attributes.empty()))))); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.class.count", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Number of classes currently loaded.") .hasUnit("{class}") .hasLongSumSatisfying( diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/CpuTest.java b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/CpuTest.java similarity index 81% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/CpuTest.java rename to instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/CpuTest.java index 982abad9eaa6..e35a748ce8aa 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/CpuTest.java +++ b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/CpuTest.java @@ -3,9 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; -import static io.opentelemetry.instrumentation.runtimemetrics.java8.ScopeUtil.EXPECTED_SCOPE; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static java.util.concurrent.TimeUnit.SECONDS; @@ -28,16 +27,18 @@ void registerObservers() { Supplier processCpuUtilization = () -> 0.05; Cpu.INSTANCE.registerObservers( - testing.getOpenTelemetry(), availableProcessors, processCpuTime, processCpuUtilization); + testing.getOpenTelemetry().getMeter("test"), + availableProcessors, + processCpuTime, + processCpuUtilization); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.cpu.time", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("CPU time used by the process as reported by the JVM.") .hasUnit("s") .hasDoubleSumSatisfying( @@ -46,13 +47,12 @@ void registerObservers() { .isMonotonic() .hasPointsSatisfying(point -> point.hasValue(42))))); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.cpu.count", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription( "Number of processors available to the Java virtual machine.") .hasUnit("{cpu}") @@ -62,13 +62,12 @@ void registerObservers() { .isNotMonotonic() .hasPointsSatisfying(point -> point.hasValue(8))))); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.cpu.recent_utilization", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription( "Recent CPU utilization for the process as reported by the JVM.") .hasUnit("1") diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/FileDescriptorTest.java b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/FileDescriptorTest.java similarity index 83% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/FileDescriptorTest.java rename to instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/FileDescriptorTest.java index ba367585108f..389a6a4762b0 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/FileDescriptorTest.java +++ b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/FileDescriptorTest.java @@ -3,9 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; -import static io.opentelemetry.instrumentation.runtimemetrics.java8.ScopeUtil.EXPECTED_SCOPE; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.mockito.Mockito.when; @@ -43,16 +42,15 @@ void setUp() { // verify that mock is called with the correct value void registerObservers() { when(osBean.getOpenFileDescriptorCount()).thenReturn(42L); - FileDescriptor.registerObservers(testing.getOpenTelemetry(), osBean); + FileDescriptor.registerObservers(testing.getOpenTelemetry().getMeter("test"), osBean); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.file_descriptor.count", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Number of open file descriptors as reported by the JVM.") .hasUnit("{file_descriptor}") .hasLongSumSatisfying( @@ -63,16 +61,15 @@ void registerObservers() { // Verify that no metrics are emitted with non-zero values void registerObservers_NegativeValue() { when(osBean.getOpenFileDescriptorCount()).thenReturn(-1L); - FileDescriptor.registerObservers(testing.getOpenTelemetry(), osBean); + FileDescriptor.registerObservers(testing.getOpenTelemetry().getMeter("test"), osBean); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.file_descriptor.count", metrics -> metrics.allSatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Number of open file descriptors as reported by the JVM.") .hasUnit("{file_descriptor}") .hasLongSumSatisfying( diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/GarbageCollectorTest.java b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/GarbageCollectorTest.java similarity index 95% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/GarbageCollectorTest.java rename to instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/GarbageCollectorTest.java index f6fe2a7a115d..25e73fbcb235 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/GarbageCollectorTest.java +++ b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/GarbageCollectorTest.java @@ -3,10 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; 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 io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.semconv.JvmAttributes.JVM_GC_ACTION; @@ -56,7 +55,7 @@ class GarbageCollectorTest { @ValueSource(booleans = {true, false}) void registerObservers(boolean captureGcCause) { GarbageCollector.registerObservers( - testing.getOpenTelemetry(), + testing.getOpenTelemetry().getMeter("test"), singletonList(gcBean), GarbageCollectorTest::getGcNotificationInfo, captureGcCause); @@ -75,13 +74,12 @@ void registerObservers(boolean captureGcCause) { createTestNotification("G1 Old Generation", "end of major GC", "System.gc()", 11), null); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.gc.duration", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Duration of JVM garbage collection actions.") .hasUnit("s") .hasHistogramSatisfying( diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryInitTest.java b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryInitTest.java similarity index 90% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryInitTest.java rename to instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryInitTest.java index 87efe5cd3b78..b198568163d3 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryInitTest.java +++ b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryInitTest.java @@ -3,10 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; 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 org.mockito.Mockito.when; @@ -56,16 +55,15 @@ void setup() { void registerObservers() { when(heapPoolUsage.getInit()).thenReturn(11L); when(nonHeapUsage.getInit()).thenReturn(15L); - MemoryInit.registerObservers(testing.getOpenTelemetry(), beans); + MemoryInit.registerObservers(testing.getOpenTelemetry().getMeter("test"), beans); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.memory.init", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Measure of initial memory requested.") .hasUnit("By") .hasLongSumSatisfying( diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryPoolsTest.java b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryPoolsTest.java similarity index 93% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryPoolsTest.java rename to instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryPoolsTest.java index 1dc3a438c95d..397efeeaf984 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/MemoryPoolsTest.java +++ b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/MemoryPoolsTest.java @@ -3,10 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; 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; @@ -78,16 +77,15 @@ void registerObservers() { when(nonHeapUsage.getMax()).thenReturn(17L); when(heapCollectionUsage.getUsed()).thenReturn(18L); when(nonHeapCollectionUsage.getUsed()).thenReturn(19L); - MemoryPools.registerObservers(testing.getOpenTelemetry(), beans); + MemoryPools.registerObservers(testing.getOpenTelemetry().getMeter("test"), beans); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.memory.used", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Measure of memory used.") .hasUnit("By") .hasLongSumSatisfying( @@ -107,13 +105,12 @@ void registerObservers() { .hasAttribute( stringKey("jvm.memory.type"), "non_heap"))))); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.memory.committed", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Measure of memory committed.") .hasUnit("By") .hasLongSumSatisfying( @@ -133,13 +130,12 @@ void registerObservers() { .hasAttribute( stringKey("jvm.memory.type"), "non_heap"))))); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.memory.limit", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Measure of max obtainable memory.") .hasUnit("By") .hasLongSumSatisfying( @@ -159,13 +155,12 @@ void registerObservers() { .hasAttribute( stringKey("jvm.memory.type"), "non_heap"))))); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.memory.used_after_last_gc", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription( "Measure of memory used, as measured after the most recent garbage collection event on this pool.") .hasUnit("By") diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/SystemCpuTest.java b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/SystemCpuTest.java similarity index 81% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/SystemCpuTest.java rename to instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/SystemCpuTest.java index 19e27ee37493..0ee84a7e12ff 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/SystemCpuTest.java +++ b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/SystemCpuTest.java @@ -3,9 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; -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; @@ -32,29 +31,28 @@ void registerObservers() { when(osBean.getSystemLoadAverage()).thenReturn(2.2); Supplier systemCpuUtilization = () -> 0.11; - SystemCpu.registerObservers(testing.getOpenTelemetry(), osBean, systemCpuUtilization); + SystemCpu.registerObservers( + testing.getOpenTelemetry().getMeter("test"), osBean, systemCpuUtilization); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "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 as reported by the JVM.") .hasUnit("{run_queue_item}") .hasDoubleGaugeSatisfying( gauge -> gauge.hasPointsSatisfying(point -> point.hasValue(2.2))))); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.system.cpu.utilization", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription( "Recent CPU utilization for the whole system as reported by the JVM.") .hasUnit("1") diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/ThreadsTest.java b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/ThreadsTest.java similarity index 91% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/ThreadsTest.java rename to instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/ThreadsTest.java index 09b42fe3d2b8..74aa1344e4d6 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/ThreadsTest.java +++ b/instrumentation/runtime-telemetry/library/src/test/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/ThreadsTest.java @@ -3,9 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; -import static io.opentelemetry.instrumentation.runtimemetrics.java8.ScopeUtil.EXPECTED_SCOPE; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.semconv.JvmAttributes.JVM_THREAD_DAEMON; @@ -49,17 +48,16 @@ void registerObservers_Java8Jmx() { when(threadBean.getDaemonThreadCount()).thenReturn(2); Threads.INSTANCE - .registerObservers(testing.getOpenTelemetry(), threadBean) + .registerObservers(testing.getOpenTelemetry().getMeter("test"), threadBean) .forEach(cleanup::deferCleanup); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.thread.count", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Number of executing platform threads.") .hasUnit("{thread}") .hasLongSumSatisfying( @@ -86,17 +84,16 @@ void registerObservers_Java8Thread() { Thread[] threads = new Thread[] {threadInfo1, threadInfo2}; Threads.INSTANCE - .registerObservers(testing.getOpenTelemetry(), () -> threads) + .registerObservers(testing.getOpenTelemetry().getMeter("test"), () -> threads) .forEach(cleanup::deferCleanup); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.thread.count", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Number of executing platform threads.") .hasUnit("{thread}") .hasLongSumSatisfying( @@ -131,17 +128,16 @@ void registerObservers_Java9AndNewer() { .thenReturn(new ThreadInfo[] {threadInfo1, null, threadInfo2}); Threads.INSTANCE - .registerObservers(testing.getOpenTelemetry(), threadBean) + .registerObservers(testing.getOpenTelemetry().getMeter("test"), threadBean) .forEach(cleanup::deferCleanup); testing.waitAndAssertMetrics( - "io.opentelemetry.runtime-telemetry-java8", + "test", "jvm.thread.count", metrics -> metrics.anySatisfy( metricData -> assertThat(metricData) - .hasInstrumentationScope(EXPECTED_SCOPE) .hasDescription("Number of executing platform threads.") .hasUnit("{thread}") .hasLongSumSatisfying( diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/BufferMetricTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/BufferMetricTest.java similarity index 87% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/BufferMetricTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/BufferMetricTest.java index 25d999c4f118..2ae95715ed2d 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/BufferMetricTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/BufferMetricTest.java @@ -3,15 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.BYTES; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.UNIT_BUFFERS; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.BYTES; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.UNIT_BUFFERS; import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import java.nio.ByteBuffer; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -21,7 +22,10 @@ class BufferMetricTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> builder.disableAllFeatures().enableFeature(JfrFeature.BUFFER_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.BUFFER_METRICS); + }); /** * This is a basic test that allocates some buffers and tests to make sure the resulting JFR event diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/CodeCacheMemoryInitMetricTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/CodeCacheMemoryInitMetricTest.java similarity index 58% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/CodeCacheMemoryInitMetricTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/CodeCacheMemoryInitMetricTest.java index 49ccd293a9ce..5beb498e0185 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/CodeCacheMemoryInitMetricTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/CodeCacheMemoryInitMetricTest.java @@ -3,14 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_CODE_CACHE; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.BYTES; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_MEMORY_INIT; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_MEMORY_INIT; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_CODE_CACHE; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.BYTES; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_MEMORY_INIT; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_MEMORY_INIT; import static org.assertj.core.api.Assertions.assertThat; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -19,7 +20,10 @@ class CodeCacheMemoryInitMetricTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> builder.disableAllFeatures().enableFeature(JfrFeature.MEMORY_POOL_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.MEMORY_POOL_METRICS); + }); @Test void shouldHaveMemoryInitMetrics() { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/G1GcMemoryMetricTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/G1GcMemoryMetricTest.java similarity index 60% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/G1GcMemoryMetricTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/G1GcMemoryMetricTest.java index f341d8920b93..6d50f87c0fe3 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/G1GcMemoryMetricTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/G1GcMemoryMetricTest.java @@ -3,27 +3,28 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_G1_EDEN_SPACE; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_G1_SURVIVOR_SPACE; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_GC_ACTION; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_GC_NAME; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.BYTES; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.END_OF_MAJOR_GC; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.END_OF_MINOR_GC; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_COMMITTED; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_GC_DURATION; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_MEMORY; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_MEMORY_AFTER; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_COMMITTED; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_GC_DURATION; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_MEMORY; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_MEMORY_AFTER; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.SECONDS; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_G1_EDEN_SPACE; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_G1_SURVIVOR_SPACE; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_GC_ACTION; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_GC_NAME; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.BYTES; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.END_OF_MAJOR_GC; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.END_OF_MINOR_GC; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_COMMITTED; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_GC_DURATION; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_MEMORY; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_MEMORY_AFTER; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_COMMITTED; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_GC_DURATION; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_MEMORY; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_MEMORY_AFTER; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import io.opentelemetry.sdk.metrics.data.MetricData; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -33,11 +34,11 @@ class G1GcMemoryMetricTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> - builder - .disableAllFeatures() - .enableFeature(JfrFeature.GC_DURATION_METRICS) - .enableFeature(JfrFeature.MEMORY_POOL_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.GC_DURATION_METRICS); + jfrConfig.enableFeature(JfrFeature.MEMORY_POOL_METRICS); + }); @Test void shouldHaveMemoryMetrics() { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/GenerateDocs.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/GenerateDocs.java similarity index 84% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/GenerateDocs.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/GenerateDocs.java index c9fb2b704cda..bee04137c5f5 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/GenerateDocs.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/GenerateDocs.java @@ -3,12 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; import static java.util.logging.Level.WARNING; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toSet; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrConfig; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.data.MetricData; @@ -38,7 +40,7 @@ private GenerateDocs() {} public static void main(String[] args) throws Exception { // Suppress info level logs - Logger.getLogger(RuntimeMetrics.class.getName()).setLevel(WARNING); + Logger.getLogger(RuntimeTelemetry.class.getName()).setLevel(WARNING); String jfrReadmePath = System.getProperty(JFR_README_PATH_KEY); if (jfrReadmePath == null) { @@ -52,6 +54,15 @@ public static void main(String[] args) throws Exception { logger.info("Done"); } + private static RuntimeTelemetry buildTelemetryForFeature( + OpenTelemetrySdk sdk, JfrFeature feature) { + RuntimeTelemetryBuilder builder = RuntimeTelemetry.builder(sdk); + JfrConfig jfrConfig = builder.getJfrConfig(); + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(feature); + return builder.build(); + } + private static String generateMarkdownTable() throws InterruptedException { // Create new JfrTelemetry for each JfrFeature Map map = new HashMap<>(); @@ -63,10 +74,7 @@ private static String generateMarkdownTable() throws InterruptedException { .build(); map.put( feature, - new JfrTelemetryWithFeature( - RuntimeMetrics.builder(sdk).disableAllFeatures().enableFeature(feature).build(), - sdk, - reader)); + new JfrTelemetryWithFeature(buildTelemetryForFeature(sdk, feature), sdk, reader)); } // Exercise JVM to produce various JFR events @@ -94,7 +102,7 @@ private static String generateMarkdownTable() throws InterruptedException { .append("| ") .append(feature.name()) .append(" | ") - .append(feature.isDefaultEnabled()) + .append(feature.overlapsWithJmx()) .append(" | ") .append(metricCol) .append(" |") @@ -107,12 +115,12 @@ private static String generateMarkdownTable() throws InterruptedException { } private static class JfrTelemetryWithFeature { - private final RuntimeMetrics jfrTelemetry; + private final RuntimeTelemetry jfrTelemetry; private final OpenTelemetrySdk sdk; private final InMemoryMetricReader reader; private JfrTelemetryWithFeature( - RuntimeMetrics jfrTelemetry, OpenTelemetrySdk sdk, InMemoryMetricReader reader) { + RuntimeTelemetry jfrTelemetry, OpenTelemetrySdk sdk, InMemoryMetricReader reader) { this.jfrTelemetry = jfrTelemetry; this.sdk = sdk; this.reader = reader; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrClassesLoadedCountTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrClassesLoadedCountTest.java similarity index 85% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrClassesLoadedCountTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrClassesLoadedCountTest.java index 4e5eb144be30..f1727e0855e5 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrClassesLoadedCountTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrClassesLoadedCountTest.java @@ -3,11 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.UNIT_CLASSES; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.UNIT_CLASSES; import static org.assertj.core.api.Assertions.assertThat; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -16,7 +17,10 @@ class JfrClassesLoadedCountTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> builder.disableAllFeatures().enableFeature(JfrFeature.CLASS_LOAD_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.CLASS_LOAD_METRICS); + }); @Test void shouldHaveJfrLoadedClassesCountEvents() throws Exception { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrCpuLockTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrCpuLockTest.java similarity index 80% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrCpuLockTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrCpuLockTest.java index ce16fc528457..c9ba68f028e9 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrCpuLockTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrCpuLockTest.java @@ -3,11 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.SECONDS; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.SECONDS; import static org.assertj.core.api.Assertions.assertThat; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import java.time.Duration; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.Test; @@ -18,7 +19,10 @@ class JfrCpuLockTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> builder.disableAllFeatures().enableFeature(JfrFeature.LOCK_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.LOCK_METRICS); + }); @Test void shouldHaveLockEvents() throws Exception { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrExtension.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrExtension.java similarity index 80% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrExtension.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrExtension.java index dc63325c2d4b..ccfd696785ac 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrExtension.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrExtension.java @@ -3,12 +3,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static java.util.concurrent.TimeUnit.SECONDS; import static org.awaitility.Awaitility.await; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrConfig; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.data.MetricData; @@ -24,14 +25,14 @@ public class JfrExtension implements BeforeEachCallback, AfterEachCallback { - private final Consumer builderConsumer; + private final Consumer jfrConfigConsumer; private SdkMeterProvider meterProvider; private InMemoryMetricReader metricReader; - private RuntimeMetrics runtimeMetrics; + private RuntimeTelemetry runtimeMetrics; - public JfrExtension(Consumer builderConsumer) { - this.builderConsumer = builderConsumer; + public JfrExtension(Consumer jfrConfigConsumer) { + this.jfrConfigConsumer = jfrConfigConsumer; } @Override @@ -46,10 +47,11 @@ public void beforeEach(ExtensionContext context) throws InterruptedException { metricReader = InMemoryMetricReader.create(); meterProvider = SdkMeterProvider.builder().registerMetricReader(metricReader).build(); OpenTelemetrySdk sdk = OpenTelemetrySdk.builder().setMeterProvider(meterProvider).build(); - RuntimeMetricsBuilder builder = RuntimeMetrics.builder(sdk); - builderConsumer.accept(builder); + RuntimeTelemetryBuilder builder = RuntimeTelemetry.builder(sdk); + jfrConfigConsumer.accept(builder.getJfrConfig()); runtimeMetrics = builder.build(); - RuntimeMetrics.JfrRuntimeMetrics jfrRuntimeMetrics = runtimeMetrics.getJfrRuntimeMetrics(); + JfrConfig.JfrRuntimeMetrics jfrRuntimeMetrics = + (JfrConfig.JfrRuntimeMetrics) runtimeMetrics.getJfrTelemetry(); if (jfrRuntimeMetrics != null) { jfrRuntimeMetrics.getStartUpLatch().await(30, SECONDS); } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrOverallCpuLoadHandlerTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrOverallCpuLoadHandlerTest.java similarity index 71% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrOverallCpuLoadHandlerTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrOverallCpuLoadHandlerTest.java index 38c8585a50d0..d1406e42ccba 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrOverallCpuLoadHandlerTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrOverallCpuLoadHandlerTest.java @@ -3,10 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.UNIT_UTILIZATION; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.UNIT_UTILIZATION; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -15,8 +16,10 @@ class JfrOverallCpuLoadHandlerTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> - builder.disableAllFeatures().enableFeature(JfrFeature.CPU_UTILIZATION_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.CPU_UTILIZATION_METRICS); + }); @Test void shouldHaveCpuLoadEvents() { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrThreadCountTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrThreadCountTest.java similarity index 77% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrThreadCountTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrThreadCountTest.java index 52831b9a798f..d15fe6d1a749 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrThreadCountTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/JfrThreadCountTest.java @@ -3,13 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_DAEMON; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.UNIT_THREADS; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_DAEMON; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.UNIT_THREADS; import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import io.opentelemetry.sdk.metrics.data.LongPointData; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -19,7 +20,10 @@ class JfrThreadCountTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> builder.disableAllFeatures().enableFeature(JfrFeature.THREAD_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.THREAD_METRICS); + }); @Test void shouldHaveJfrThreadCountEvents() throws Exception { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/MetaspaceMemoryCommittedMetricTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/MetaspaceMemoryCommittedMetricTest.java similarity index 54% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/MetaspaceMemoryCommittedMetricTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/MetaspaceMemoryCommittedMetricTest.java index 768fca11771a..d744cb26a973 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/MetaspaceMemoryCommittedMetricTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/MetaspaceMemoryCommittedMetricTest.java @@ -3,15 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_COMPRESSED_CLASS_SPACE; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_METASPACE; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.BYTES; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_COMMITTED; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_COMMITTED; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_COMPRESSED_CLASS_SPACE; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_METASPACE; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.BYTES; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_COMMITTED; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_COMMITTED; import static org.assertj.core.api.Assertions.assertThat; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -20,7 +21,10 @@ class MetaspaceMemoryCommittedMetricTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> builder.disableAllFeatures().enableFeature(JfrFeature.MEMORY_POOL_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.MEMORY_POOL_METRICS); + }); @Test void shouldHaveMemoryCommittedMetrics() { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/MetaspaceMemoryLimitMetricTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/MetaspaceMemoryLimitMetricTest.java similarity index 55% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/MetaspaceMemoryLimitMetricTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/MetaspaceMemoryLimitMetricTest.java index 4ef4f41f6b3d..928c9ca6fa64 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/MetaspaceMemoryLimitMetricTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/MetaspaceMemoryLimitMetricTest.java @@ -3,14 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_COMPRESSED_CLASS_SPACE; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.BYTES; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_MEMORY_LIMIT; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_MEMORY_LIMIT; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_COMPRESSED_CLASS_SPACE; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.BYTES; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_MEMORY_LIMIT; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_MEMORY_LIMIT; import static org.assertj.core.api.Assertions.assertThat; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -19,7 +20,10 @@ class MetaspaceMemoryLimitMetricTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> builder.disableAllFeatures().enableFeature(JfrFeature.MEMORY_POOL_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.MEMORY_POOL_METRICS); + }); @Test void shouldHaveMemoryLimitMetrics() { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/MetaspaceMemoryUsageMetricTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/MetaspaceMemoryUsageMetricTest.java similarity index 56% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/MetaspaceMemoryUsageMetricTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/MetaspaceMemoryUsageMetricTest.java index 004115d11c33..6f638d6b45e6 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/MetaspaceMemoryUsageMetricTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/MetaspaceMemoryUsageMetricTest.java @@ -3,15 +3,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_COMPRESSED_CLASS_SPACE; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_METASPACE; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.BYTES; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_MEMORY; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_MEMORY; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_COMPRESSED_CLASS_SPACE; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_METASPACE; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.BYTES; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_MEMORY; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_MEMORY; import static org.assertj.core.api.Assertions.assertThat; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -20,7 +21,10 @@ class MetaspaceMemoryUsageMetricTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> builder.disableAllFeatures().enableFeature(JfrFeature.MEMORY_POOL_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.MEMORY_POOL_METRICS); + }); /** This is a basic test for jvm.memory.used. */ @Test diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/PsGcMemoryMetricTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/PsGcMemoryMetricTest.java similarity index 55% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/PsGcMemoryMetricTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/PsGcMemoryMetricTest.java index eaba1c4ff9c4..1d1b70a574da 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/PsGcMemoryMetricTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/PsGcMemoryMetricTest.java @@ -3,30 +3,31 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_GC_ACTION; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_GC_NAME; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_PS_EDEN_SPACE; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_PS_OLD_GEN; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_PS_SURVIVOR_SPACE; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.BYTES; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.END_OF_MAJOR_GC; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.END_OF_MINOR_GC; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_COMMITTED; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_GC_DURATION; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_MEMORY; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_MEMORY_AFTER; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_MEMORY_LIMIT; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_COMMITTED; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_GC_DURATION; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_MEMORY; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_MEMORY_AFTER; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_MEMORY_LIMIT; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.SECONDS; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_GC_ACTION; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_GC_NAME; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_PS_EDEN_SPACE; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_PS_OLD_GEN; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_PS_SURVIVOR_SPACE; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.BYTES; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.END_OF_MAJOR_GC; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.END_OF_MINOR_GC; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_COMMITTED; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_GC_DURATION; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_MEMORY; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_MEMORY_AFTER; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_MEMORY_LIMIT; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_COMMITTED; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_GC_DURATION; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_MEMORY; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_MEMORY_AFTER; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_MEMORY_LIMIT; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import io.opentelemetry.sdk.metrics.data.MetricData; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -36,11 +37,11 @@ class PsGcMemoryMetricTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> - builder - .disableAllFeatures() - .enableFeature(JfrFeature.GC_DURATION_METRICS) - .enableFeature(JfrFeature.MEMORY_POOL_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.GC_DURATION_METRICS); + jfrConfig.enableFeature(JfrFeature.MEMORY_POOL_METRICS); + }); @Test void shouldHaveMemoryMetrics() { diff --git a/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilderTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilderTest.java new file mode 100644 index 000000000000..be16d5f58765 --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilderTest.java @@ -0,0 +1,98 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.runtimetelemetry; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrConfig; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import java.util.Arrays; +import java.util.HashMap; +import jdk.jfr.FlightRecorder; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +class RuntimeTelemetryBuilderTest { + + @BeforeAll + static void setup() { + try { + Class.forName("jdk.jfr.FlightRecorder"); + } catch (ClassNotFoundException exception) { + Assumptions.abort("JFR not present"); + } + Assumptions.assumeTrue(FlightRecorder.isAvailable(), "JFR not available"); + } + + @Test + void defaultFeatures() { + // By default, features that don't overlap with JMX AND are not experimental are enabled + var defaultFeatures = new HashMap(); + Arrays.stream(JfrFeature.values()) + .forEach( + jfrFeature -> + defaultFeatures.put( + jfrFeature, !jfrFeature.overlapsWithJmx() && !jfrFeature.isExperimental())); + + assertThat(newBuilder().getJfrConfig().enabledFeatureMap).isEqualTo(defaultFeatures); + } + + @Test + void enableAllFeatures() { + assertThat(newBuilder().getJfrConfig().enableAllFeatures().enabledFeatureMap) + .allSatisfy((unused, enabled) -> assertThat(enabled).isTrue()); + } + + @Test + void disableAllFeatures() { + assertThat(newBuilder().getJfrConfig().disableAllFeatures().enabledFeatureMap) + .allSatisfy((unused, enabled) -> assertThat(enabled).isFalse()); + } + + @Test + void enableDisableFeature() { + var builder = RuntimeTelemetry.builder(OpenTelemetry.noop()); + + // BUFFER_METRICS overlaps with JMX and is experimental, so it's disabled by default + assertThat(builder.getJfrConfig().enabledFeatureMap.get(JfrFeature.BUFFER_METRICS)).isFalse(); + + builder.getJfrConfig().enableFeature(JfrFeature.BUFFER_METRICS); + assertThat(builder.getJfrConfig().enabledFeatureMap.get(JfrFeature.BUFFER_METRICS)).isTrue(); + builder.getJfrConfig().disableFeature(JfrFeature.BUFFER_METRICS); + assertThat(builder.getJfrConfig().enabledFeatureMap.get(JfrFeature.BUFFER_METRICS)).isFalse(); + } + + @Test + void build_DefaultNoJfr() { + // By default, no JFR features are enabled because all features either overlap + // with JMX or are experimental + var openTelemetry = OpenTelemetry.noop(); + try (var runtimeTelemetry = RuntimeTelemetry.builder(openTelemetry).build()) { + assertThat(runtimeTelemetry.getJfrTelemetry()).isNull(); + } + } + + @Test + void build_WithFeatureEnabled() { + var openTelemetry = OpenTelemetry.noop(); + var builder = RuntimeTelemetry.builder(openTelemetry); + builder.getJfrConfig().enableFeature(JfrFeature.LOCK_METRICS); + try (var runtimeTelemetry = builder.build()) { + var jfrRuntimeMetrics = (JfrConfig.JfrRuntimeMetrics) runtimeTelemetry.getJfrTelemetry(); + assertThat(jfrRuntimeMetrics).isNotNull(); + assertThat(jfrRuntimeMetrics.getRecordedEventHandlers()) + .hasSizeGreaterThan(0) + .allSatisfy( + handler -> assertThat(handler.getFeature()).isEqualTo(JfrFeature.LOCK_METRICS)); + } + } + + private static RuntimeTelemetryBuilder newBuilder() { + return RuntimeTelemetry.builder(OpenTelemetry.noop()); + } +} diff --git a/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryTest.java new file mode 100644 index 000000000000..142e23bcf175 --- /dev/null +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryTest.java @@ -0,0 +1,123 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.runtimetelemetry; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; + +import io.github.netmikey.logunit.api.LogCapturer; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrConfig; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.metrics.SdkMeterProvider; +import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader; +import java.util.concurrent.atomic.AtomicBoolean; +import jdk.jfr.FlightRecorder; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class RuntimeTelemetryTest { + + @RegisterExtension LogCapturer logs = LogCapturer.create().captureForType(RuntimeTelemetry.class); + + private InMemoryMetricReader reader; + private OpenTelemetrySdk sdk; + + @BeforeEach + void setup() { + try { + Class.forName("jdk.jfr.FlightRecorder"); + } catch (ClassNotFoundException exception) { + Assumptions.abort("JFR not present"); + } + Assumptions.assumeTrue(FlightRecorder.isAvailable(), "JFR not available"); + + reader = InMemoryMetricReader.createDelta(); + sdk = + OpenTelemetrySdk.builder() + .setMeterProvider(SdkMeterProvider.builder().registerMetricReader(reader).build()) + .build(); + } + + @AfterEach + void tearDown() { + if (sdk != null) { + sdk.getSdkMeterProvider().close(); + } + } + + @Test + void create_Default() { + try (RuntimeTelemetry unused = RuntimeTelemetry.create(sdk)) { + assertThat(reader.collectAllMetrics()) + .isNotEmpty() + .allSatisfy( + metric -> { + assertThat(metric.getInstrumentationScopeInfo().getName()) + .isEqualTo("io.opentelemetry.runtime-telemetry"); + }); + } + } + + @Test + void builder_DefaultNoJfr() { + // By default, no JFR features are enabled because all features either overlap + // with JMX or are experimental + try (var runtimeTelemetry = RuntimeTelemetry.builder(sdk).build()) { + assertThat(runtimeTelemetry.getJfrTelemetry()).isNull(); + } + } + + @Test + void builder_WithFeatureEnabled() { + RuntimeTelemetryBuilder builder = RuntimeTelemetry.builder(sdk); + builder.getJfrConfig().enableFeature(JfrFeature.LOCK_METRICS); + try (var runtimeTelemetry = builder.build()) { + JfrConfig.JfrRuntimeMetrics jfrRuntimeMetrics = + (JfrConfig.JfrRuntimeMetrics) runtimeTelemetry.getJfrTelemetry(); + assertThat(jfrRuntimeMetrics).isNotNull(); + assertThat(jfrRuntimeMetrics.getRecordedEventHandlers()) + .hasSizeGreaterThan(0) + .allSatisfy( + handler -> { + assertThat(handler.getFeature()).isEqualTo(JfrFeature.LOCK_METRICS); + }); + } + } + + @Test + void close() throws InterruptedException { + RuntimeTelemetryBuilder builder = RuntimeTelemetry.builder(sdk); + // Enable a feature to test close behavior with JFR + builder.getJfrConfig().enableFeature(JfrFeature.LOCK_METRICS); + try (RuntimeTelemetry jfrTelemetry = builder.build()) { + JfrConfig.JfrRuntimeMetrics jfrRuntimeMetrics = + (JfrConfig.JfrRuntimeMetrics) jfrTelemetry.getJfrTelemetry(); + + // Track whether RecordingStream has been closed + AtomicBoolean recordingStreamClosed = new AtomicBoolean(false); + jfrRuntimeMetrics.getRecordingStream().onClose(() -> recordingStreamClosed.set(true)); + + assertThat(reader.collectAllMetrics()).isNotEmpty(); + + jfrTelemetry.close(); + logs.assertDoesNotContain("RuntimeTelemetry is already closed"); + assertThat(recordingStreamClosed.get()).isTrue(); + + // clear all metrics that might have arrived after close + Thread.sleep(100); // give time for any inflight metric export to be received + reader.collectAllMetrics(); + + Thread.sleep(100); + assertThat(reader.collectAllMetrics()).isEmpty(); + + jfrTelemetry.close(); + logs.assertContains("RuntimeTelemetry is already closed"); + } + } +} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/SerialGcMemoryMetricTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/SerialGcMemoryMetricTest.java similarity index 61% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/SerialGcMemoryMetricTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/SerialGcMemoryMetricTest.java index b8e51bc1b99c..9536d41025cc 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/SerialGcMemoryMetricTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/SerialGcMemoryMetricTest.java @@ -3,18 +3,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17; +package io.opentelemetry.instrumentation.runtimetelemetry; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_GC_ACTION; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.ATTR_GC_NAME; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.END_OF_MAJOR_GC; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.END_OF_MINOR_GC; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_DESCRIPTION_GC_DURATION; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.METRIC_NAME_GC_DURATION; -import static io.opentelemetry.instrumentation.runtimemetrics.java17.internal.Constants.SECONDS; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_GC_ACTION; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.ATTR_GC_NAME; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.END_OF_MAJOR_GC; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.END_OF_MINOR_GC; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_DESCRIPTION_GC_DURATION; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.METRIC_NAME_GC_DURATION; +import static io.opentelemetry.instrumentation.runtimetelemetry.internal.Constants.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -23,7 +24,10 @@ class SerialGcMemoryMetricTest { @RegisterExtension JfrExtension jfrExtension = new JfrExtension( - builder -> builder.disableAllFeatures().enableFeature(JfrFeature.GC_DURATION_METRICS)); + jfrConfig -> { + jfrConfig.disableAllFeatures(); + jfrConfig.enableFeature(JfrFeature.GC_DURATION_METRICS); + }); @Test void shouldHaveMemoryMetrics() { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/DurationUtilTest.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/DurationUtilTest.java similarity index 85% rename from instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/DurationUtilTest.java rename to instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/DurationUtilTest.java index 401894c5b2f7..891730090f55 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/DurationUtilTest.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/DurationUtilTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal; +package io.opentelemetry.instrumentation.runtimetelemetry.internal; import static org.assertj.core.api.Assertions.assertThat; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/javaagent/build.gradle.kts b/instrumentation/runtime-telemetry/runtime-telemetry-java17/javaagent/build.gradle.kts index 5b9763cf1e8e..934ea07f8684 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/javaagent/build.gradle.kts +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/javaagent/build.gradle.kts @@ -2,13 +2,15 @@ plugins { id("otel.javaagent-instrumentation") } +// This module's main code has been consolidated into :instrumentation:runtime-telemetry:javaagent +// Tests are kept to verify backward compatibility + otelJava { minJavaVersionSupported.set(JavaVersion.VERSION_17) } dependencies { - implementation(project(":instrumentation:runtime-telemetry:runtime-telemetry-java17:library")) - compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") + testInstrumentation(project(":instrumentation:runtime-telemetry:javaagent")) } tasks { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java17/Java17RuntimeMetricsInstaller.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java17/Java17RuntimeMetricsInstaller.java deleted file mode 100644 index ba2b1d0de1e2..000000000000 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java17/Java17RuntimeMetricsInstaller.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.runtimemetrics.java17; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.runtimemetrics.java17.RuntimeMetrics; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RuntimeMetricsConfigUtil; -import io.opentelemetry.javaagent.extension.AgentListener; -import io.opentelemetry.javaagent.tooling.config.AgentConfig; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; - -/** An {@link AgentListener} that enables runtime metrics during agent startup. */ -@AutoService(AgentListener.class) -public class Java17RuntimeMetricsInstaller implements AgentListener { - - @Override - public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) { - RuntimeMetrics runtimeMetrics = - RuntimeMetricsConfigUtil.configure( - RuntimeMetrics.builder(GlobalOpenTelemetry.get()), - GlobalOpenTelemetry.get(), - AgentConfig.instrumentationMode()); - if (runtimeMetrics != null) { - Runtime.getRuntime() - .addShutdownHook( - new Thread(runtimeMetrics::close, "OpenTelemetry RuntimeMetricsShutdownHook")); - } - } -} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/README.md b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/README.md index 382475411c6c..3f6e112d80bd 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/README.md +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/README.md @@ -1,5 +1,9 @@ # Runtime Telemetry Java 17 +> **Deprecated:** This module is deprecated. Use +> [`opentelemetry-runtime-telemetry`](../library/README.md) instead, which provides a unified API +> for all Java versions including JFR support on Java 17+. + The main entry point is the `RuntimeMetrics` class in the package `io.opentelemetry.instrumentation.runtimemetrics.java17`: ```java diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/build.gradle.kts b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/build.gradle.kts index a261bb7e75d8..0ad3b31295b3 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/build.gradle.kts +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/build.gradle.kts @@ -7,61 +7,11 @@ otelJava { } dependencies { - implementation(project(":instrumentation:runtime-telemetry:runtime-telemetry-java8:library")) + implementation(project(":instrumentation:runtime-telemetry:library")) testImplementation("io.github.netmikey.logunit:logunit-jul:1.1.3") } -tasks.register("generateDocs", JavaExec::class) { - group = "build" - description = "Generate table for README.md" - classpath = sourceSets.test.get().runtimeClasspath - mainClass.set("io.opentelemetry.instrumentation.runtimemetrics.java17.GenerateDocs") - systemProperties.set("jfr.readme.path", project.projectDir.toString() + "/README.md") -} - tasks { - val testG1 by registering(Test::class) { - testClassesDirs = sourceSets.test.get().output.classesDirs - classpath = sourceSets.test.get().runtimeClasspath - filter { - includeTestsMatching("*G1GcMemoryMetricTest*") - } - include("**/*G1GcMemoryMetricTest.*") - jvmArgs("-XX:+UseG1GC") - } - - val testPS by registering(Test::class) { - testClassesDirs = sourceSets.test.get().output.classesDirs - classpath = sourceSets.test.get().runtimeClasspath - filter { - includeTestsMatching("*PsGcMemoryMetricTest*") - } - include("**/*PsGcMemoryMetricTest.*") - jvmArgs("-XX:+UseParallelGC") - } - - val testSerial by registering(Test::class) { - testClassesDirs = sourceSets.test.get().output.classesDirs - classpath = sourceSets.test.get().runtimeClasspath - filter { - includeTestsMatching("*SerialGcMemoryMetricTest*") - } - include("**/*SerialGcMemoryMetricTest.*") - jvmArgs("-XX:+UseSerialGC") - } - - test { - filter { - excludeTestsMatching("*G1GcMemoryMetricTest") - excludeTestsMatching("*SerialGcMemoryMetricTest") - excludeTestsMatching("*PsGcMemoryMetricTest") - } - } - - check { - dependsOn(testG1, testPS, testSerial) - } - compileJava { // We compile this module for java 8 because it is used as a dependency in spring-boot-autoconfigure. // If this module is compiled for java 17 then gradle can figure out based on the metadata that diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/HandlerRegistry.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/HandlerRegistry.java deleted file mode 100644 index 6de364065082..000000000000 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/HandlerRegistry.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.runtimemetrics.java17; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.api.metrics.MeterBuilder; -import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.buffer.DirectBufferStatisticsHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.classes.ClassesLoadedHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.container.ContainerConfigurationHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.cpu.ContextSwitchRateHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.cpu.LongLockHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.cpu.OverallCpuLoadHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.garbagecollection.G1GarbageCollectionHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.garbagecollection.OldGarbageCollectionHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.garbagecollection.YoungGarbageCollectionHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory.CodeCacheConfigurationHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory.G1HeapSummaryHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory.MetaspaceSummaryHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory.ObjectAllocationInNewTlabHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory.ObjectAllocationOutsideTlabHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.memory.ParallelHeapSummaryHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.network.NetworkReadHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.network.NetworkWriteHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.threads.ThreadCountHandler; -import java.lang.management.GarbageCollectorMXBean; -import java.lang.management.ManagementFactory; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.function.Predicate; -import javax.annotation.Nullable; - -final class HandlerRegistry { - private static final String SCOPE_NAME = "io.opentelemetry.runtime-telemetry-java17"; - - @Nullable - private static final String SCOPE_VERSION = - EmbeddedInstrumentationProperties.findVersion(SCOPE_NAME); - - private HandlerRegistry() {} - - static List getHandlers( - OpenTelemetry openTelemetry, Predicate featurePredicate) { - - MeterBuilder meterBuilder = openTelemetry.meterBuilder(SCOPE_NAME); - if (SCOPE_VERSION != null) { - meterBuilder.setInstrumentationVersion(SCOPE_VERSION); - } - Meter meter = meterBuilder.build(); - - List handlers = new ArrayList(); - for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) { - String name = bean.getName(); - switch (name) { - case "G1 Young Generation": - handlers.add(new G1HeapSummaryHandler(meter)); - handlers.add(new G1GarbageCollectionHandler(meter)); - break; - - case "Copy": - handlers.add(new YoungGarbageCollectionHandler(meter, name)); - break; - - case "PS Scavenge": - handlers.add(new YoungGarbageCollectionHandler(meter, name)); - handlers.add(new ParallelHeapSummaryHandler(meter)); - break; - - case "G1 Old Generation": - case "PS MarkSweep": - case "MarkSweepCompact": - handlers.add(new OldGarbageCollectionHandler(meter, name)); - break; - - default: - // If none of the above GCs are detected, no action. - } - } - - List basicHandlers = - List.of( - new ObjectAllocationInNewTlabHandler(meter), - new ObjectAllocationOutsideTlabHandler(meter), - new NetworkReadHandler(meter), - new NetworkWriteHandler(meter), - new ContextSwitchRateHandler(meter), - new OverallCpuLoadHandler(meter), - new ContainerConfigurationHandler(meter), - new LongLockHandler(meter), - new ThreadCountHandler(meter), - new ClassesLoadedHandler(meter), - new MetaspaceSummaryHandler(meter), - new CodeCacheConfigurationHandler(meter), - new DirectBufferStatisticsHandler(meter)); - handlers.addAll(basicHandlers); - - // Filter and close disabled handlers - Iterator iter = handlers.iterator(); - while (iter.hasNext()) { - RecordedEventHandler handler = iter.next(); - if (!featurePredicate.test(handler.getFeature())) { - handler.close(); - iter.remove(); - } - } - - return handlers; - } -} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrFeature.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrFeature.java index aacaaf8fa654..f91bc60a93e9 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrFeature.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/JfrFeature.java @@ -5,13 +5,23 @@ package io.opentelemetry.instrumentation.runtimemetrics.java17; +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetry; + /** * Enumeration of JFR features, which can be toggled on or off via {@link RuntimeMetricsBuilder}. * *

Features are disabled by default if they are already available through {@code * io.opentelemetry.instrumentation:opentelemetry-runtime-telemetry-java8} JMX based * instrumentation. + * + * @deprecated Use {@link RuntimeTelemetry#builder(io.opentelemetry.api.OpenTelemetry)} in the + * {@code runtime-telemetry} module instead. To enable experimental features, use {@link + * io.opentelemetry.instrumentation.runtimetelemetry.internal.Experimental#setEmitExperimentalMetrics(io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetryBuilder, + * boolean)}. To enable JFR collection for metrics that overlap with JMX, use {@link + * io.opentelemetry.instrumentation.runtimetelemetry.internal.Experimental#setPreferJfrMetrics(io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetryBuilder, + * boolean)}. To disable specific metrics, configure metric views. */ +@Deprecated public enum JfrFeature { BUFFER_METRICS(/* defaultEnabled= */ false), CLASS_LOAD_METRICS(/* defaultEnabled= */ false), diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetrics.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetrics.java index 413cd8ddd6bb..56c3a56e72f6 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetrics.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetrics.java @@ -5,40 +5,23 @@ package io.opentelemetry.instrumentation.runtimemetrics.java17; -import static java.util.logging.Level.WARNING; - import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RecordedEventHandler; -import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil; -import java.io.Closeable; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Predicate; -import java.util.logging.Logger; +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetry; +import java.lang.reflect.Method; import javax.annotation.Nullable; -import jdk.jfr.EventSettings; -import jdk.jfr.FlightRecorder; -import jdk.jfr.consumer.RecordingStream; -/** The entry point class for runtime metrics support using JFR and JMX. */ +/** + * The entry point class for runtime metrics support using JFR and JMX. + * + * @deprecated Use {@link RuntimeTelemetry} in the {@code runtime-telemetry} module instead. + */ +@Deprecated public final class RuntimeMetrics implements AutoCloseable { - private static final Logger logger = Logger.getLogger(RuntimeMetrics.class.getName()); - - private final AtomicBoolean isClosed = new AtomicBoolean(); - private final OpenTelemetry openTelemetry; - private final List observables; - - @Nullable private final JfrRuntimeMetrics jfrRuntimeMetrics; + private final RuntimeTelemetry delegate; - RuntimeMetrics( - OpenTelemetry openTelemetry, - List observables, - @Nullable JfrRuntimeMetrics jfrRuntimeMetrics) { - this.openTelemetry = openTelemetry; - this.observables = List.copyOf(observables); - this.jfrRuntimeMetrics = jfrRuntimeMetrics; + RuntimeMetrics(RuntimeTelemetry delegate) { + this.delegate = delegate; } /** @@ -62,106 +45,21 @@ public static RuntimeMetricsBuilder builder(OpenTelemetry openTelemetry) { return new RuntimeMetricsBuilder(openTelemetry); } - // Visible for testing - OpenTelemetry getOpenTelemetry() { - return openTelemetry; - } - - // Visible for testing - JfrRuntimeMetrics getJfrRuntimeMetrics() { - return jfrRuntimeMetrics; + // Only used by tests + @Nullable + Object getJfrRuntimeMetrics() { + try { + Method method = RuntimeTelemetry.class.getDeclaredMethod("getJfrTelemetry"); + method.setAccessible(true); + return method.invoke(delegate); + } catch (Exception e) { + throw new IllegalStateException("Failed to access JFR telemetry via reflection", e); + } } /** Stop recording JFR events. */ @Override public void close() { - if (!isClosed.compareAndSet(false, true)) { - logger.log(WARNING, "RuntimeMetrics is already closed"); - return; - } - if (jfrRuntimeMetrics != null) { - jfrRuntimeMetrics.close(); - } - - JmxRuntimeMetricsUtil.closeObservers(observables); - } - - static class JfrRuntimeMetrics implements Closeable { - private final List recordedEventHandlers; - private final RecordingStream recordingStream; - private final CountDownLatch startUpLatch = new CountDownLatch(1); - private volatile boolean closed = false; - - private JfrRuntimeMetrics(OpenTelemetry openTelemetry, Predicate featurePredicate) { - this.recordedEventHandlers = HandlerRegistry.getHandlers(openTelemetry, featurePredicate); - recordingStream = new RecordingStream(); - recordedEventHandlers.forEach( - handler -> { - EventSettings eventSettings = recordingStream.enable(handler.getEventName()); - handler.getPollingDuration().ifPresent(eventSettings::withPeriod); - handler.getThreshold().ifPresent(eventSettings::withThreshold); - recordingStream.onEvent(handler.getEventName(), handler); - }); - recordingStream.onMetadata(event -> startUpLatch.countDown()); - Thread daemonRunner = - new Thread(this::startRecordingStream, "OpenTelemetry JFR-Metrics-Runner"); - daemonRunner.setDaemon(true); - daemonRunner.setContextClassLoader(null); - daemonRunner.start(); - } - - private void startRecordingStream() { - if (closed) { - return; - } - - try { - recordingStream.start(); - } catch (IllegalStateException exception) { - // Can happen when close is called at the same time as start - if (!closed) { - throw exception; - } - } - } - - static JfrRuntimeMetrics build( - OpenTelemetry openTelemetry, Predicate featurePredicate) { - if (!isJfrAvailable()) { - return null; - } - return new JfrRuntimeMetrics(openTelemetry, featurePredicate); - } - - @Override - public void close() { - closed = true; - recordingStream.close(); - recordedEventHandlers.forEach(RecordedEventHandler::close); - } - - // Visible for testing - List getRecordedEventHandlers() { - return recordedEventHandlers; - } - - // Visible for testing - RecordingStream getRecordingStream() { - return recordingStream; - } - - // Visible for testing - CountDownLatch getStartUpLatch() { - return startUpLatch; - } - - private static boolean isJfrAvailable() { - try { - return FlightRecorder.isAvailable(); - } catch (Throwable e) { - // NoClassDefFoundError, UnsatisfiedLinkError (native images), or other issues - return false; - } - } + delegate.close(); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java index 5fab59c1fbe0..86317c89a676 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java @@ -7,53 +7,111 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsFactory; +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetry; +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetryBuilder; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Experimental; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Internal; +import java.lang.reflect.Method; import java.util.Arrays; -import java.util.EnumMap; -import java.util.List; -import javax.annotation.Nullable; -/** Builder for {@link RuntimeMetrics}. */ +/** + * Builder for {@link RuntimeMetrics}. + * + * @deprecated Use {@link RuntimeTelemetryBuilder} in the {@code runtime-telemetry} module instead. + */ +@Deprecated public final class RuntimeMetricsBuilder { - private final OpenTelemetry openTelemetry; - // Visible for testing - final EnumMap enabledFeatureMap; - - private boolean disableJmx = false; - private boolean emitExperimentalTelemetry = false; - private boolean captureGcCause = false; + private final RuntimeTelemetryBuilder delegate; RuntimeMetricsBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; - enabledFeatureMap = new EnumMap<>(JfrFeature.class); + this.delegate = RuntimeTelemetry.builder(openTelemetry); + // Set instrumentation name for backward compatibility + // JMX metrics use java8 scope (matching old behavior where java8 module handled JMX) + Internal.setJmxInstrumentationName(delegate, "io.opentelemetry.runtime-telemetry-java8"); + Internal.setJfrInstrumentationName(delegate, "io.opentelemetry.runtime-telemetry-java17"); + // Use legacy metric for backward compatibility (jvm.cpu.limit instead of jvm.cpu.count) + Internal.setUseLegacyJfrCpuCountMetric(delegate, true); + // java17 default for captureGcCause was false (unified module default is true) + Internal.setCaptureGcCause(delegate, false); + + // Disable all JFR features first, then selectively enable based on java17 defaults. + // This ensures backward compatibility even if the unified module adds new default-enabled + // features in the future. + Internal.setDisableAllJfrFeatures(delegate, true); + + // Enable features with java17 defaults for (JfrFeature feature : JfrFeature.values()) { - enabledFeatureMap.put(feature, feature.isDefaultEnabled()); + if (feature.isDefaultEnabled()) { + Internal.setEnableJfrFeature(delegate, feature.name()); + } + } + } + + // Only used by tests + Object getJfrConfig() { + try { + Method method = RuntimeTelemetryBuilder.class.getDeclaredMethod("getJfrConfig"); + method.setAccessible(true); + return method.invoke(delegate); + } catch (Exception e) { + throw new IllegalStateException("Failed to access JfrConfig via reflection", e); } } - /** Enable telemetry collection for all {@link JfrFeature}s. */ + /** + * Enable telemetry collection for all {@link JfrFeature}s. + * + * @deprecated Use {@link RuntimeTelemetry#builder(OpenTelemetry)} in the {@code + * runtime-telemetry} module instead. To enable experimental features, use {@link + * Experimental#setEmitExperimentalMetrics(RuntimeTelemetryBuilder, boolean)}. To enable JFR + * collection for metrics that overlap with JMX, use {@link + * Experimental#setPreferJfrMetrics(RuntimeTelemetryBuilder, boolean)}. + */ + @Deprecated @CanIgnoreReturnValue public RuntimeMetricsBuilder enableAllFeatures() { Arrays.stream(JfrFeature.values()).forEach(this::enableFeature); return this; } - /** Enable telemetry collection associated with the {@link JfrFeature}. */ + /** + * Enable telemetry collection associated with the {@link JfrFeature}. + * + * @deprecated Use {@link RuntimeTelemetry#builder(OpenTelemetry)} in the {@code + * runtime-telemetry} module instead. To enable experimental features, use {@link + * Experimental#setEmitExperimentalMetrics(RuntimeTelemetryBuilder, boolean)}. To enable JFR + * collection for metrics that overlap with JMX, use {@link + * Experimental#setPreferJfrMetrics(RuntimeTelemetryBuilder, boolean)}. To disable specific + * metrics, configure metric views. + */ + @Deprecated @CanIgnoreReturnValue public RuntimeMetricsBuilder enableFeature(JfrFeature feature) { - enabledFeatureMap.put(feature, true); + Internal.setEnableJfrFeature(delegate, feature.name()); return this; } - /** Disable telemetry collection for all {@link JfrFeature}s. */ + /** + * Disable telemetry collection for all {@link JfrFeature}s. + * + * @deprecated Use {@link RuntimeTelemetry#builder(OpenTelemetry)} in the {@code + * runtime-telemetry} module instead. To disable specific metrics, configure metric views. + */ + @Deprecated @CanIgnoreReturnValue public RuntimeMetricsBuilder disableAllFeatures() { Arrays.stream(JfrFeature.values()).forEach(this::disableFeature); return this; } - /** Disable telemetry collection for all metrics. */ + /** + * Disable telemetry collection for all metrics. + * + * @deprecated Use {@link RuntimeTelemetry#builder(OpenTelemetry)} in the {@code + * runtime-telemetry} module instead. To disable specific metrics, configure metric views. + */ + @Deprecated @CanIgnoreReturnValue public RuntimeMetricsBuilder disableAllMetrics() { disableAllFeatures(); @@ -61,50 +119,67 @@ public RuntimeMetricsBuilder disableAllMetrics() { return this; } - /** Disable telemetry collection associated with the {@link JfrFeature}. */ + /** + * Disable telemetry collection associated with the {@link JfrFeature}. + * + * @deprecated Use {@link RuntimeTelemetry#builder(OpenTelemetry)} in the {@code + * runtime-telemetry} module instead. To disable specific metrics, configure metric views. + */ + @Deprecated @CanIgnoreReturnValue public RuntimeMetricsBuilder disableFeature(JfrFeature feature) { - enabledFeatureMap.put(feature, false); + Internal.setDisableJfrFeature(delegate, feature.name()); return this; } - /** Disable all JMX telemetry collection. */ + /** + * Disable all JMX telemetry collection. + * + * @deprecated Use {@link RuntimeTelemetry#builder(OpenTelemetry)} in the {@code + * runtime-telemetry} module instead. To disable specific metrics, configure metric views. + */ + @Deprecated @CanIgnoreReturnValue public RuntimeMetricsBuilder disableAllJmx() { - disableJmx = true; + Internal.setDisableJmx(delegate, true); return this; } - /** Enable experimental JMX telemetry collection. */ + /** + * Enable experimental JMX telemetry collection. + * + * @deprecated Use {@link Experimental#setEmitExperimentalMetrics(RuntimeTelemetryBuilder, + * boolean)} instead. + */ + @Deprecated @CanIgnoreReturnValue public RuntimeMetricsBuilder emitExperimentalTelemetry() { - emitExperimentalTelemetry = true; + Experimental.setEmitExperimentalMetrics(delegate, true); return this; } - /** Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. */ + /** + * Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. + * + * @deprecated Use {@link RuntimeTelemetry#builder(OpenTelemetry)} in the {@code + * runtime-telemetry} module instead. The unified {@link RuntimeTelemetryBuilder} enables GC + * cause capture by default. + */ + @Deprecated @CanIgnoreReturnValue public RuntimeMetricsBuilder captureGcCause() { - captureGcCause = true; + Internal.setCaptureGcCause(delegate, true); return this; } - /** Build and start an {@link RuntimeMetrics} with the config from this builder. */ + /** + * Build and start an {@link RuntimeMetrics} with the config from this builder. + * + * @deprecated Use {@link RuntimeTelemetry#builder(OpenTelemetry)} in the {@code + * runtime-telemetry} module instead. + */ + @Deprecated public RuntimeMetrics build() { - List observables = - disableJmx - ? List.of() - : JmxRuntimeMetricsFactory.buildObservables( - openTelemetry, emitExperimentalTelemetry, captureGcCause); - RuntimeMetrics.JfrRuntimeMetrics jfrRuntimeMetrics = buildJfrMetrics(); - return new RuntimeMetrics(openTelemetry, observables, jfrRuntimeMetrics); - } - - @Nullable - private RuntimeMetrics.JfrRuntimeMetrics buildJfrMetrics() { - if (enabledFeatureMap.values().stream().noneMatch(isEnabled -> isEnabled)) { - return null; - } - return RuntimeMetrics.JfrRuntimeMetrics.build(openTelemetry, enabledFeatureMap::get); + return new RuntimeMetrics(delegate.build()); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java deleted file mode 100644 index 221e1e86db89..000000000000 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/internal/RuntimeMetricsConfigUtil.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.runtimemetrics.java17.internal; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; -import io.opentelemetry.instrumentation.runtimemetrics.java17.RuntimeMetrics; -import io.opentelemetry.instrumentation.runtimemetrics.java17.RuntimeMetricsBuilder; -import javax.annotation.Nullable; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public final class RuntimeMetricsConfigUtil { - private RuntimeMetricsConfigUtil() {} - - @Nullable - public static RuntimeMetrics configure( - RuntimeMetricsBuilder builder, OpenTelemetry openTelemetry, String instrumentationMode) { - /* - By default, don't use any JFR metrics. May change this once semantic conventions are updated. - If enabled, default to only the metrics not already covered by runtime-telemetry-java8 - */ - if (DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "runtime_telemetry_java17") - .getBoolean("enable_all", false)) { - builder.enableAllFeatures(); - } else if (DeclarativeConfigUtil.getInstrumentationConfig( - openTelemetry, "runtime_telemetry_java17") - .getBoolean("enabled", false)) { - // default configuration - } else if (DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "runtime_telemetry") - .getBoolean("enabled", instrumentationMode.equals("default"))) { - // This only uses metrics gathered by JMX - builder.disableAllFeatures(); - } else { - // nothing is enabled - return null; - } - - if (DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "runtime_telemetry") - .getBoolean("emit_experimental_telemetry/development", false)) { - builder.emitExperimentalTelemetry(); - } - - if (DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "runtime_telemetry") - .getBoolean("capture_gc_cause", false)) { - builder.captureGcCause(); - } - - return builder.build(); - } -} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilderTest.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilderTest.java index 78f88af3f4f5..72b8accd3137 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilderTest.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilderTest.java @@ -8,13 +8,16 @@ import static org.assertj.core.api.Assertions.assertThat; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrConfig; import java.util.Arrays; +import java.util.EnumMap; import java.util.HashMap; import jdk.jfr.FlightRecorder; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +@SuppressWarnings("deprecation") // Testing deprecated API for backward compatibility class RuntimeMetricsBuilderTest { @BeforeAll @@ -33,21 +36,23 @@ void defaultFeatures() { Arrays.stream(JfrFeature.values()) .forEach(jfrFeature -> defaultFeatures.put(jfrFeature, jfrFeature.isDefaultEnabled())); - assertThat(new RuntimeMetricsBuilder(OpenTelemetry.noop()).enabledFeatureMap) + assertThat(getEnabledFeatureMap(new RuntimeMetricsBuilder(OpenTelemetry.noop()))) .isEqualTo(defaultFeatures); } @Test void enableAllFeatures() { assertThat( - new RuntimeMetricsBuilder(OpenTelemetry.noop()).enableAllFeatures().enabledFeatureMap) + getEnabledFeatureMap( + new RuntimeMetricsBuilder(OpenTelemetry.noop()).enableAllFeatures())) .allSatisfy((unused, enabled) -> assertThat(enabled).isTrue()); } @Test void disableAllFeatures() { assertThat( - new RuntimeMetricsBuilder(OpenTelemetry.noop()).disableAllFeatures().enabledFeatureMap) + getEnabledFeatureMap( + new RuntimeMetricsBuilder(OpenTelemetry.noop()).disableAllFeatures())) .allSatisfy((unused, enabled) -> assertThat(enabled).isFalse()); } @@ -55,22 +60,50 @@ void disableAllFeatures() { void enableDisableFeature() { var builder = new RuntimeMetricsBuilder(OpenTelemetry.noop()); - assertThat(builder.enabledFeatureMap.get(JfrFeature.BUFFER_METRICS)).isFalse(); + assertThat(getEnabledFeatureMap(builder).get(JfrFeature.BUFFER_METRICS)).isFalse(); builder.enableFeature(JfrFeature.BUFFER_METRICS); - assertThat(builder.enabledFeatureMap.get(JfrFeature.BUFFER_METRICS)).isTrue(); + assertThat(getEnabledFeatureMap(builder).get(JfrFeature.BUFFER_METRICS)).isTrue(); builder.disableFeature(JfrFeature.BUFFER_METRICS); - assertThat(builder.enabledFeatureMap.get(JfrFeature.BUFFER_METRICS)).isFalse(); + assertThat(getEnabledFeatureMap(builder).get(JfrFeature.BUFFER_METRICS)).isFalse(); } @Test void build() { var openTelemetry = OpenTelemetry.noop(); try (var jfrTelemetry = new RuntimeMetricsBuilder(openTelemetry).build()) { - assertThat(jfrTelemetry.getOpenTelemetry()).isSameAs(openTelemetry); - assertThat(jfrTelemetry.getJfrRuntimeMetrics().getRecordedEventHandlers()) + assertThat(getJfrRuntimeMetrics(jfrTelemetry).getRecordedEventHandlers()) .hasSizeGreaterThan(0) - .allSatisfy(handler -> assertThat(handler.getFeature().isDefaultEnabled()).isTrue()); + .allSatisfy(handler -> assertThat(isDefaultEnabled(handler.getFeature())).isTrue()); } } + + // Helper to access the unified module's state + private static JfrConfig.JfrRuntimeMetrics getJfrRuntimeMetrics(RuntimeMetrics runtimeMetrics) { + return (JfrConfig.JfrRuntimeMetrics) runtimeMetrics.getJfrRuntimeMetrics(); + } + + // Helper to access the unified module's state + private static EnumMap getEnabledFeatureMap(RuntimeMetricsBuilder builder) { + JfrConfig jfrConfig = (JfrConfig) builder.getJfrConfig(); + EnumMap result = new EnumMap<>(JfrFeature.class); + for (JfrFeature feature : JfrFeature.values()) { + result.put( + feature, + jfrConfig.enabledFeatureMap.get( + io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature.valueOf( + feature.name()))); + } + return result; + } + + // Java17 legacy defaults: all non-overlapping features + // plus CPU_COUNT_METRICS (which is emitted as cpu.count.limit) + private static boolean isDefaultEnabled( + io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature feature) { + return !feature.overlapsWithJmx() + || feature + == io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature + .CPU_COUNT_METRICS; + } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsTest.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsTest.java index 15b178abf814..44d4f6186430 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsTest.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsTest.java @@ -8,6 +8,8 @@ import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import io.github.netmikey.logunit.api.LogCapturer; +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetry; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrConfig; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader; @@ -19,9 +21,10 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; +@SuppressWarnings("deprecation") // Testing deprecated API for backward compatibility class RuntimeMetricsTest { - @RegisterExtension LogCapturer logs = LogCapturer.create().captureForType(RuntimeMetrics.class); + @RegisterExtension LogCapturer logs = LogCapturer.create().captureForType(RuntimeTelemetry.class); private InMemoryMetricReader reader; private OpenTelemetrySdk sdk; @@ -72,10 +75,9 @@ void create_AllDisabled() { @Test void builder() { try (var jfrTelemetry = RuntimeMetrics.builder(sdk).build()) { - assertThat(jfrTelemetry.getOpenTelemetry()).isSameAs(sdk); - assertThat(jfrTelemetry.getJfrRuntimeMetrics().getRecordedEventHandlers()) + assertThat(getJfrRuntimeMetrics(jfrTelemetry).getRecordedEventHandlers()) .hasSizeGreaterThan(0) - .allSatisfy(handler -> assertThat(handler.getFeature().isDefaultEnabled()).isTrue()); + .allSatisfy(handler -> assertThat(isDefaultEnabled(handler.getFeature())).isTrue()); } } @@ -84,15 +86,14 @@ void close() throws InterruptedException { try (RuntimeMetrics jfrTelemetry = RuntimeMetrics.builder(sdk).build()) { // Track whether RecordingStream has been closed AtomicBoolean recordingStreamClosed = new AtomicBoolean(false); - jfrTelemetry - .getJfrRuntimeMetrics() + getJfrRuntimeMetrics(jfrTelemetry) .getRecordingStream() .onClose(() -> recordingStreamClosed.set(true)); assertThat(reader.collectAllMetrics()).isNotEmpty(); jfrTelemetry.close(); - logs.assertDoesNotContain("RuntimeMetrics is already closed"); + logs.assertDoesNotContain("RuntimeTelemetry is already closed"); assertThat(recordingStreamClosed.get()).isTrue(); // clear all metrics that might have arrived after close @@ -103,7 +104,22 @@ void close() throws InterruptedException { assertThat(reader.collectAllMetrics()).isEmpty(); jfrTelemetry.close(); - logs.assertContains("RuntimeMetrics is already closed"); + logs.assertContains("RuntimeTelemetry is already closed"); } } + + // Helper to access the unified module's state + private static JfrConfig.JfrRuntimeMetrics getJfrRuntimeMetrics(RuntimeMetrics runtimeMetrics) { + return (JfrConfig.JfrRuntimeMetrics) runtimeMetrics.getJfrRuntimeMetrics(); + } + + // Java17 legacy defaults: all non-overlapping features + // plus CPU_COUNT_METRICS (which is emitted as cpu.count.limit) + private static boolean isDefaultEnabled( + io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature feature) { + return !feature.overlapsWithJmx() + || feature + == io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrFeature + .CPU_COUNT_METRICS; + } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/build.gradle.kts b/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/build.gradle.kts index aa1653528255..cc30320b30c3 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/build.gradle.kts +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/build.gradle.kts @@ -2,11 +2,11 @@ plugins { id("otel.javaagent-instrumentation") } -dependencies { - implementation(project(":instrumentation:runtime-telemetry:runtime-telemetry-java8:library")) +// This module's main code has been consolidated into :instrumentation:runtime-telemetry:javaagent +// Tests are kept to verify backward compatibility with legacy property names - compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure") - compileOnly("io.opentelemetry:opentelemetry-api-incubator") +dependencies { + testInstrumentation(project(":instrumentation:runtime-telemetry:javaagent")) } tasks { diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarAnalyzerInstaller.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarAnalyzerInstaller.java deleted file mode 100644 index 118d67dee88a..000000000000 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarAnalyzerInstaller.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; -import io.opentelemetry.javaagent.bootstrap.InstrumentationHolder; -import io.opentelemetry.javaagent.tooling.BeforeAgentListener; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import java.lang.instrument.Instrumentation; - -/** Installs the {@link JarAnalyzer}. */ -@AutoService(BeforeAgentListener.class) -public class JarAnalyzerInstaller implements BeforeAgentListener { - - @Override - public void beforeAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { - OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); - DeclarativeConfigProperties config = - DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "runtime_telemetry"); - if (!config.get("package_emitter").getBoolean("enabled", false)) { - return; - } - Instrumentation inst = InstrumentationHolder.getInstrumentation(); - if (inst == null) { - return; - } - JarAnalyzer jarAnalyzer = - JarAnalyzer.create( - openTelemetry, config.get("package_emitter").getInt("jars_per_second", 10)); - inst.addTransformer(jarAnalyzer); - } -} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/Java8RuntimeMetricsInstaller.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/Java8RuntimeMetricsInstaller.java deleted file mode 100644 index 4b6a8c5b7030..000000000000 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/Java8RuntimeMetricsInstaller.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8; - -import com.google.auto.service.AutoService; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.instrumentation.runtimemetrics.java8.RuntimeMetrics; -import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.RuntimeMetricsConfigUtil; -import io.opentelemetry.javaagent.extension.AgentListener; -import io.opentelemetry.javaagent.tooling.config.AgentConfig; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; - -/** An {@link AgentListener} that enables runtime metrics during agent startup. */ -@AutoService(AgentListener.class) -public class Java8RuntimeMetricsInstaller implements AgentListener { - - @Override - public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) { - if (Double.parseDouble(System.getProperty("java.specification.version")) >= 17) { - return; - } - - RuntimeMetrics runtimeMetrics = - RuntimeMetricsConfigUtil.configure( - RuntimeMetrics.builder(GlobalOpenTelemetry.get()), - GlobalOpenTelemetry.get(), - AgentConfig.instrumentationMode()); - if (runtimeMetrics != null) { - Runtime.getRuntime() - .addShutdownHook( - new Thread(runtimeMetrics::close, "OpenTelemetry RuntimeMetricsShutdownHook")); - } - } -} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/README.md b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/README.md index 7ddde09e1fa6..a36864795d41 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/README.md +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/README.md @@ -1,5 +1,9 @@ # JVM Runtime Metrics +> **Deprecated:** This module is deprecated. Use +> [`opentelemetry-runtime-telemetry`](../library/README.md) instead, which provides a unified API +> for all Java versions. + This module provides JVM runtime metrics as documented in the [semantic conventions](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/runtime/jvm-metrics.md). ## Quickstart @@ -83,43 +87,7 @@ meter_provider: ## Garbage Collector Dependent Metrics -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 `*.used`, `*.committed`, and `*.limit` since not all memory pools report a limit. - -- CMS Garbage Collector - - `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 - - `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 - - `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 - - `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 - - `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 - - `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} +The attributes reported on memory metrics (`jvm.memory.*`) and GC metrics (`jvm.gc.*`) depend on +the garbage collector used by the application. See the +[runtime-telemetry library README](../../library/README.md#garbage-collector-dependent-metrics) +for details on attributes for various garbage collectors. diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/build.gradle.kts b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/build.gradle.kts index 24be66977afe..41f190e4376d 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/build.gradle.kts +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/build.gradle.kts @@ -3,5 +3,5 @@ plugins { } dependencies { - implementation(project(":instrumentation-api")) + implementation(project(":instrumentation:runtime-telemetry:library")) } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetrics.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetrics.java index 1542325c24c3..9f918a08f8f4 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetrics.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetrics.java @@ -5,25 +5,21 @@ package io.opentelemetry.instrumentation.runtimemetrics.java8; -import static java.util.logging.Level.WARNING; - import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsUtil; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.logging.Logger; +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetry; -/** The entry point class for runtime metrics support using JMX. */ +/** + * The entry point class for runtime metrics support using JMX. + * + * @deprecated Use {@link RuntimeTelemetry} in the {@code runtime-telemetry} module instead. + */ +@Deprecated public final class RuntimeMetrics implements AutoCloseable { - private static final Logger logger = Logger.getLogger(RuntimeMetrics.class.getName()); + private final RuntimeTelemetry delegate; - private final AtomicBoolean isClosed = new AtomicBoolean(); - private final List observables; - - RuntimeMetrics(List observables) { - this.observables = Collections.unmodifiableList(observables); + RuntimeMetrics(RuntimeTelemetry delegate) { + this.delegate = delegate; } /** @@ -33,7 +29,10 @@ public final class RuntimeMetrics implements AutoCloseable { * continue until {@link #close()} is called. * * @param openTelemetry the {@link OpenTelemetry} instance used to record telemetry + * @deprecated Use {@link RuntimeTelemetry#create(OpenTelemetry)} in the {@code runtime-telemetry} + * module instead. */ + @Deprecated public static RuntimeMetrics create(OpenTelemetry openTelemetry) { return new RuntimeMetricsBuilder(openTelemetry).build(); } @@ -42,7 +41,10 @@ public static RuntimeMetrics create(OpenTelemetry openTelemetry) { * Create a builder for configuring {@link RuntimeMetrics}. * * @param openTelemetry the {@link OpenTelemetry} instance used to record telemetry + * @deprecated Use {@link RuntimeTelemetry#builder(OpenTelemetry)} in the {@code + * runtime-telemetry} module instead. */ + @Deprecated public static RuntimeMetricsBuilder builder(OpenTelemetry openTelemetry) { return new RuntimeMetricsBuilder(openTelemetry); } @@ -50,11 +52,6 @@ public static RuntimeMetricsBuilder builder(OpenTelemetry openTelemetry) { /** Stop recording JMX metrics. */ @Override public void close() { - if (!isClosed.compareAndSet(false, true)) { - logger.log(WARNING, "RuntimeMetrics is already closed"); - return; - } - - JmxRuntimeMetricsUtil.closeObservers(observables); + delegate.close(); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java index 97b617d5713c..fbb4dcd15d03 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java @@ -7,40 +7,64 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.JmxRuntimeMetricsFactory; -import java.util.List; +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetry; +import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetryBuilder; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Experimental; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Internal; -/** Builder for {@link RuntimeMetrics}. */ +/** + * Builder for {@link RuntimeMetrics}. + * + * @deprecated Use {@link RuntimeTelemetryBuilder} in the {@code runtime-telemetry} module instead. + */ +@Deprecated public final class RuntimeMetricsBuilder { - private final OpenTelemetry openTelemetry; + private static final String INSTRUMENTATION_NAME = "io.opentelemetry.runtime-telemetry-java8"; - private boolean emitExperimentalTelemetry = false; - private boolean captureGcCause = false; + private final RuntimeTelemetryBuilder delegate; RuntimeMetricsBuilder(OpenTelemetry openTelemetry) { - this.openTelemetry = openTelemetry; + this.delegate = RuntimeTelemetry.builder(openTelemetry); + // Set instrumentation name for backward compatibility + Internal.setJmxInstrumentationName(delegate, INSTRUMENTATION_NAME); + // Disable all JFR features - java8 module was JMX-only. This also ensures backward + // compatibility if the unified module adds new default-enabled JFR features in the future. + Internal.setDisableAllJfrFeatures(delegate, true); + // java8 default for captureGcCause was false (unified module default is true) + Internal.setCaptureGcCause(delegate, false); } - /** Enable all JMX telemetry collection. */ + /** + * Enable experimental JMX telemetry collection. When running on Java 17+, this will also enable + * experimental JFR metrics. To drop unwanted JFR metrics, configure metric views. + * + * @deprecated Use {@link Experimental#setEmitExperimentalMetrics(RuntimeTelemetryBuilder, + * boolean)} instead. + */ + @Deprecated @CanIgnoreReturnValue public RuntimeMetricsBuilder emitExperimentalTelemetry() { - emitExperimentalTelemetry = true; + Experimental.setEmitExperimentalMetrics(delegate, true); return this; } - /** Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. */ + /** + * Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. + * + * @deprecated Use {@link RuntimeTelemetry#builder(OpenTelemetry)} in the {@code + * runtime-telemetry} module instead. The unified {@link RuntimeTelemetryBuilder} enables GC + * cause capture by default. + */ + @Deprecated @CanIgnoreReturnValue public RuntimeMetricsBuilder captureGcCause() { - captureGcCause = true; + Internal.setCaptureGcCause(delegate, true); return this; } /** Build and start an {@link RuntimeMetrics} with the config from this builder. */ public RuntimeMetrics build() { - List observables = - JmxRuntimeMetricsFactory.buildObservables( - openTelemetry, emitExperimentalTelemetry, captureGcCause); - return new RuntimeMetrics(observables); + return new RuntimeMetrics(delegate.build()); } } diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java deleted file mode 100644 index 8042bc2ea7c5..000000000000 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; - -import io.opentelemetry.api.OpenTelemetry; -import java.util.ArrayList; -import java.util.List; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public class JmxRuntimeMetricsFactory { - @SuppressWarnings("CatchingUnchecked") - public static List buildObservables( - OpenTelemetry openTelemetry, boolean emitExperimentalTelemetry, boolean captureGcCause) { - // Set up metrics gathered by JMX - List observables = new ArrayList<>(); - observables.addAll(Classes.registerObservers(openTelemetry)); - observables.addAll(Cpu.registerObservers(openTelemetry)); - observables.addAll(GarbageCollector.registerObservers(openTelemetry, captureGcCause)); - observables.addAll(MemoryPools.registerObservers(openTelemetry)); - observables.addAll(Threads.registerObservers(openTelemetry)); - if (emitExperimentalTelemetry) { - observables.addAll(BufferPools.registerObservers(openTelemetry)); - observables.addAll(SystemCpu.registerObservers(openTelemetry)); - observables.addAll(MemoryInit.registerObservers(openTelemetry)); - observables.addAll(FileDescriptor.registerObservers(openTelemetry)); - } - return observables; - } - - private JmxRuntimeMetricsFactory() {} -} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsUtil.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsUtil.java deleted file mode 100644 index 334d405ad26f..000000000000 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/JmxRuntimeMetricsUtil.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.metrics.Meter; -import io.opentelemetry.api.metrics.MeterBuilder; -import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; -import java.util.List; -import javax.annotation.Nullable; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public class JmxRuntimeMetricsUtil { - - private static final String INSTRUMENTATION_NAME = "io.opentelemetry.runtime-telemetry-java8"; - - @Nullable - private static final String INSTRUMENTATION_VERSION = - EmbeddedInstrumentationProperties.findVersion(INSTRUMENTATION_NAME); - - public static Meter getMeter(OpenTelemetry openTelemetry) { - MeterBuilder meterBuilder = openTelemetry.meterBuilder(INSTRUMENTATION_NAME); - if (INSTRUMENTATION_VERSION != null) { - meterBuilder.setInstrumentationVersion(INSTRUMENTATION_VERSION); - } - return meterBuilder.build(); - } - - public static String getInstrumentationName() { - return INSTRUMENTATION_NAME; - } - - @Nullable - public static String getInstrumentationVersion() { - return INSTRUMENTATION_VERSION; - } - - public static void closeObservers(List observables) { - observables.forEach( - observable -> { - try { - observable.close(); - } catch (Exception e) { - // Ignore - } - }); - } - - private JmxRuntimeMetricsUtil() {} -} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java deleted file mode 100644 index 2e1b4800df63..000000000000 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/internal/RuntimeMetricsConfigUtil.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.runtimemetrics.java8.internal; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; -import io.opentelemetry.instrumentation.runtimemetrics.java8.RuntimeMetrics; -import io.opentelemetry.instrumentation.runtimemetrics.java8.RuntimeMetricsBuilder; -import javax.annotation.Nullable; - -/** - * This class is internal and is hence not for public use. Its APIs are unstable and can change at - * any time. - */ -public final class RuntimeMetricsConfigUtil { - private RuntimeMetricsConfigUtil() {} - - @Nullable - public static RuntimeMetrics configure( - RuntimeMetricsBuilder builder, OpenTelemetry openTelemetry, String instrumentationMode) { - DeclarativeConfigProperties config = - DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "runtime_telemetry"); - if (!config.getBoolean("enabled", instrumentationMode.equals("default"))) { - // nothing is enabled - return null; - } - - if (config.getBoolean("emit_experimental_telemetry/development", false)) { - builder.emitExperimentalTelemetry(); - } - - if (config.getBoolean("capture_gc_cause", false)) { - builder.captureGcCause(); - } - - return builder.build(); - } -} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/ScopeUtil.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/ScopeUtil.java deleted file mode 100644 index 3769d2a4ce11..000000000000 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/test/java/io/opentelemetry/instrumentation/runtimemetrics/java8/ScopeUtil.java +++ /dev/null @@ -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() {} -} diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/testing/build.gradle.kts b/instrumentation/runtime-telemetry/testing/build.gradle.kts similarity index 96% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/testing/build.gradle.kts rename to instrumentation/runtime-telemetry/testing/build.gradle.kts index dc808ed744aa..284dbdddf59a 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/testing/build.gradle.kts +++ b/instrumentation/runtime-telemetry/testing/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } dependencies { - testImplementation(project(":instrumentation:runtime-telemetry:runtime-telemetry-java8:javaagent")) + testImplementation(project(":instrumentation:runtime-telemetry:javaagent")) testImplementation("io.opentelemetry:opentelemetry-sdk-testing") diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/testing/src/main/java/io/opentelemetry/instrumentation/testapp/DummyApplication.java b/instrumentation/runtime-telemetry/testing/src/main/java/io/opentelemetry/instrumentation/testapp/DummyApplication.java similarity index 100% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/testing/src/main/java/io/opentelemetry/instrumentation/testapp/DummyApplication.java rename to instrumentation/runtime-telemetry/testing/src/main/java/io/opentelemetry/instrumentation/testapp/DummyApplication.java diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarAnalyzerTest.java b/instrumentation/runtime-telemetry/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzerTest.java similarity index 90% rename from instrumentation/runtime-telemetry/runtime-telemetry-java8/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarAnalyzerTest.java rename to instrumentation/runtime-telemetry/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzerTest.java index 4b19e050e73b..e9ceecf1ff14 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/runtimemetrics/java8/JarAnalyzerTest.java +++ b/instrumentation/runtime-telemetry/testing/src/test/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzerTest.java @@ -3,15 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8; +package io.opentelemetry.javaagent.instrumentation.runtimetelemetry; -import static io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8.JarAnalyzer.PACKAGE_CHECKSUM; -import static io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8.JarAnalyzer.PACKAGE_CHECKSUM_ALGORITHM; -import static io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8.JarAnalyzer.PACKAGE_DESCRIPTION; -import static io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8.JarAnalyzer.PACKAGE_NAME; -import static io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8.JarAnalyzer.PACKAGE_PATH; -import static io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8.JarAnalyzer.PACKAGE_TYPE; -import static io.opentelemetry.javaagent.instrumentation.runtimemetrics.java8.JarAnalyzer.PACKAGE_VERSION; +import static io.opentelemetry.javaagent.instrumentation.runtimetelemetry.JarAnalyzer.PACKAGE_CHECKSUM; +import static io.opentelemetry.javaagent.instrumentation.runtimetelemetry.JarAnalyzer.PACKAGE_CHECKSUM_ALGORITHM; +import static io.opentelemetry.javaagent.instrumentation.runtimetelemetry.JarAnalyzer.PACKAGE_DESCRIPTION; +import static io.opentelemetry.javaagent.instrumentation.runtimetelemetry.JarAnalyzer.PACKAGE_NAME; +import static io.opentelemetry.javaagent.instrumentation.runtimetelemetry.JarAnalyzer.PACKAGE_PATH; +import static io.opentelemetry.javaagent.instrumentation.runtimetelemetry.JarAnalyzer.PACKAGE_TYPE; +import static io.opentelemetry.javaagent.instrumentation.runtimetelemetry.JarAnalyzer.PACKAGE_VERSION; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -21,7 +21,8 @@ import com.google.common.collect.ImmutableMap; import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.incubator.logs.ExtendedLogRecordBuilder; +import io.opentelemetry.api.logs.LogRecordBuilder; +import io.opentelemetry.api.logs.Logger; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.sdk.testing.assertj.AttributesAssert; import java.io.File; @@ -40,11 +41,13 @@ class JarAnalyzerTest { @ParameterizedTest @MethodSource("processUrlArguments") void processUrl_EmitsEvents(URL archiveUrl, Consumer attributesConsumer) { - ExtendedLogRecordBuilder builder = mock(ExtendedLogRecordBuilder.class); + Logger logger = mock(Logger.class); + LogRecordBuilder builder = mock(LogRecordBuilder.class); + when(logger.logRecordBuilder()).thenReturn(builder); when(builder.setEventName(eq("package.info"))).thenReturn(builder); when(builder.setAllAttributes((Attributes) any())).thenReturn(builder); - JarAnalyzer.processUrl(builder, archiveUrl); + JarAnalyzer.processUrl(logger, archiveUrl); ArgumentCaptor attributesArgumentCaptor = ArgumentCaptor.forClass(Attributes.class); verify(builder).setAllAttributes(attributesArgumentCaptor.capture()); @@ -66,7 +69,7 @@ private static Stream processUrlArguments() { path -> assertThat( path.matches( - "opentelemetry-javaagent-runtime-telemetry-java8-[0-9a-zA-Z-\\.]+\\.jar")) + "opentelemetry-javaagent-runtime-telemetry-[0-9a-zA-Z-\\.]+\\.jar")) .isTrue()) .containsEntry(PACKAGE_DESCRIPTION, "javaagent by OpenTelemetry") .containsEntry(PACKAGE_CHECKSUM_ALGORITHM, "SHA1") diff --git a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts index d0fed56bf949..f908e417f8a9 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts +++ b/instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts @@ -68,8 +68,7 @@ dependencies { implementation(project(":instrumentation:logback:logback-mdc-1.0:library")) compileOnly("ch.qos.logback:logback-classic:1.0.0") implementation(project(":instrumentation:jdbc:library")) - implementation(project(":instrumentation:runtime-telemetry:runtime-telemetry-java8:library")) - implementation(project(":instrumentation:runtime-telemetry:runtime-telemetry-java17:library")) + implementation(project(":instrumentation:runtime-telemetry:library")) library("org.springframework.boot:spring-boot-starter-actuator:$springBootVersion") library("org.springframework.boot:spring-boot-starter-aop:$springBootVersion") diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimemetrics/Java8RuntimeMetricsAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimemetrics/Java8RuntimeMetricsAutoConfiguration.java deleted file mode 100644 index 7cc748211058..000000000000 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimemetrics/Java8RuntimeMetricsAutoConfiguration.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.runtimemetrics; - -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; -import io.opentelemetry.instrumentation.runtimemetrics.java8.RuntimeMetrics; -import io.opentelemetry.instrumentation.runtimemetrics.java8.internal.RuntimeMetricsConfigUtil; -import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; -import javax.annotation.Nullable; -import javax.annotation.PreDestroy; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.event.EventListener; - -/** - * Configures runtime metrics collection for Java 8+. This is a fallback configuration that only - * activates when Java17RuntimeMetricsAutoConfiguration is not present (i.e., on Java versions older - * than 17). - * - *

This class is internal and is hence not for public use. Its APIs are unstable and can change - * at any time. - */ -@ConditionalOnEnabledInstrumentation(module = "runtime-telemetry") -@ConditionalOnMissingBean(Java17RuntimeMetricsAutoConfiguration.class) -@Configuration -public class Java8RuntimeMetricsAutoConfiguration { - - private static final Logger logger = - LoggerFactory.getLogger(Java8RuntimeMetricsAutoConfiguration.class); - - @Nullable private AutoCloseable closeable; - - @PreDestroy - public void stopMetrics() throws Exception { - if (closeable != null) { - closeable.close(); - } - } - - @EventListener - public void handleApplicationReadyEvent(ApplicationReadyEvent event) { - ConfigurableApplicationContext applicationContext = event.getApplicationContext(); - OpenTelemetry openTelemetry = applicationContext.getBean(OpenTelemetry.class); - - logger.debug("Use runtime metrics instrumentation for Java 8"); - this.closeable = - RuntimeMetricsConfigUtil.configure( - RuntimeMetrics.builder(openTelemetry), - openTelemetry, - instrumentationMode(openTelemetry)); - } - - private static String instrumentationMode(OpenTelemetry openTelemetry) { - String mode = - DeclarativeConfigUtil.getInstrumentationConfig(openTelemetry, "spring_starter") - .getString("instrumentation_mode", "default"); - if (!mode.equals("default") && !mode.equals("none")) { - throw new ConfigurationException("Unknown instrumentation mode: " + mode); - } - return mode; - } -} diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimemetrics/Java17RuntimeMetricsAutoConfiguration.java b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimetelemetry/RuntimeMetricsAutoConfiguration.java similarity index 67% rename from instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimemetrics/Java17RuntimeMetricsAutoConfiguration.java rename to instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimetelemetry/RuntimeMetricsAutoConfiguration.java index d9e595a82e00..9cdd5a826f25 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimemetrics/Java17RuntimeMetricsAutoConfiguration.java +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/java/io/opentelemetry/instrumentation/spring/autoconfigure/internal/instrumentation/runtimetelemetry/RuntimeMetricsAutoConfiguration.java @@ -3,39 +3,34 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.runtimemetrics; +package io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.runtimetelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; -import io.opentelemetry.instrumentation.runtimemetrics.java17.RuntimeMetrics; -import io.opentelemetry.instrumentation.runtimemetrics.java17.internal.RuntimeMetricsConfigUtil; +import io.opentelemetry.instrumentation.runtimetelemetry.internal.Internal; import io.opentelemetry.instrumentation.spring.autoconfigure.internal.ConditionalOnEnabledInstrumentation; import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; import javax.annotation.Nullable; import javax.annotation.PreDestroy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.boot.autoconfigure.condition.ConditionalOnJava; -import org.springframework.boot.autoconfigure.condition.ConditionalOnJava.Range; import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.boot.system.JavaVersion; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.EventListener; /** - * Configures runtime metrics collection for Java 17+. + * Configures runtime telemetry collection. * *

This class is internal and is hence not for public use. Its APIs are unstable and can change * at any time. */ @ConditionalOnEnabledInstrumentation(module = "runtime-telemetry") -@ConditionalOnJava(range = Range.EQUAL_OR_NEWER, value = JavaVersion.SEVENTEEN) @Configuration -public class Java17RuntimeMetricsAutoConfiguration { +public class RuntimeMetricsAutoConfiguration { private static final Logger logger = - LoggerFactory.getLogger(Java17RuntimeMetricsAutoConfiguration.class); + LoggerFactory.getLogger(RuntimeMetricsAutoConfiguration.class); @Nullable private AutoCloseable closeable; @@ -51,12 +46,8 @@ public void handleApplicationReadyEvent(ApplicationReadyEvent event) { ConfigurableApplicationContext applicationContext = event.getApplicationContext(); OpenTelemetry openTelemetry = applicationContext.getBean(OpenTelemetry.class); - logger.debug("Use runtime metrics instrumentation for Java 17+"); - this.closeable = - RuntimeMetricsConfigUtil.configure( - RuntimeMetrics.builder(openTelemetry), - openTelemetry, - instrumentationMode(openTelemetry)); + logger.debug("Start runtime telemetry instrumentation"); + this.closeable = Internal.configure(openTelemetry, instrumentationMode(openTelemetry)); } private static String instrumentationMode(OpenTelemetry openTelemetry) { diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index 277f707acb68..22b5b337c30f 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -14,8 +14,7 @@ io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.w io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webflux.SpringWebfluxInstrumentationAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc.SpringWebMvc5InstrumentationAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.scheduling.SpringSchedulingInstrumentationAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.runtimemetrics.Java17RuntimeMetricsAutoConfiguration,\ -io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.runtimemetrics.Java8RuntimeMetricsAutoConfiguration,\ +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.runtimetelemetry.RuntimeMetricsAutoConfiguration,\ io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.thread.ThreadDetailsAutoConfiguration org.springframework.context.ApplicationListener=\ diff --git a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 41ebb58077f3..6221095ec48c 100644 --- a/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/instrumentation/spring/spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -18,6 +18,5 @@ io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.w io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.web.RestClientInstrumentationSpringBoot4AutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.webmvc.SpringWebMvc6InstrumentationAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.scheduling.SpringSchedulingInstrumentationAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.runtimemetrics.Java17RuntimeMetricsAutoConfiguration -io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.runtimemetrics.Java8RuntimeMetricsAutoConfiguration +io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.runtimetelemetry.RuntimeMetricsAutoConfiguration io.opentelemetry.instrumentation.spring.autoconfigure.internal.instrumentation.thread.ThreadDetailsAutoConfiguration diff --git a/settings.gradle.kts b/settings.gradle.kts index 86398a53b1f8..bbd395ac0a6a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -580,9 +580,11 @@ include(":instrumentation:rocketmq:rocketmq-client-4.8:library") include(":instrumentation:rocketmq:rocketmq-client-4.8:testing") include(":instrumentation:rocketmq:rocketmq-client-5.0:javaagent") include(":instrumentation:rocketmq:rocketmq-client-5.0:testing") +include(":instrumentation:runtime-telemetry:javaagent") +include(":instrumentation:runtime-telemetry:library") +include(":instrumentation:runtime-telemetry:testing") include(":instrumentation:runtime-telemetry:runtime-telemetry-java8:javaagent") include(":instrumentation:runtime-telemetry:runtime-telemetry-java8:library") -include(":instrumentation:runtime-telemetry:runtime-telemetry-java8:testing") include(":instrumentation:runtime-telemetry:runtime-telemetry-java17:javaagent") include(":instrumentation:runtime-telemetry:runtime-telemetry-java17:library") include(":instrumentation:rxjava:rxjava-1.0:library") diff --git a/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/AbstractSpringStarterSmokeTest.java b/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/AbstractSpringStarterSmokeTest.java index cd528e3941af..eb93d7ba0a75 100644 --- a/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/AbstractSpringStarterSmokeTest.java +++ b/smoke-tests-otel-starter/spring-smoke-testing/src/main/java/io/opentelemetry/spring/smoketest/AbstractSpringStarterSmokeTest.java @@ -33,7 +33,10 @@ public abstract class AbstractSpringStarterSmokeTest { "Registering converter from interface java.util.List to interface org.springframework.data.domain.Vector as reading converter although it doesn't convert from a store-supported type; You might want to check your annotation setup at the converter implementation", "Node may not be available.", "Could not configure topics", - "(id: -1 rack: null isFenced: false) disconnected"); + "(id: -1 rack: null isFenced: false) disconnected", + // expected deprecation warnings from tests using old runtime-telemetry properties + "otel.instrumentation.runtime-telemetry-java17.enable-all is deprecated", + "otel.instrumentation.runtime-telemetry.emit-experimental-telemetry is deprecated"); @Autowired protected OpenTelemetry openTelemetry; From 1048c957664136c7cbc46dfc8e7f78fd504f335b Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 4 Feb 2026 15:26:08 -0800 Subject: [PATCH 02/14] updates --- instrumentation/runtime-telemetry/README.md | 28 ++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/instrumentation/runtime-telemetry/README.md b/instrumentation/runtime-telemetry/README.md index e36eab69fe3c..202543df8fbc 100644 --- a/instrumentation/runtime-telemetry/README.md +++ b/instrumentation/runtime-telemetry/README.md @@ -1,19 +1,19 @@ # Settings for the Runtime Telemetry instrumentation -| System property | Type | Default | Description | -|---------------------------------------------------------------------------------------|---------|---------|-----------------------------------------------------------------------------------| -| `otel.instrumentation.runtime-telemetry.emit-experimental-metrics` | Boolean | `false` | Enable the capture of experimental metrics. | -| `otel.instrumentation.runtime-telemetry.experimental.prefer-jfr` | Boolean | `false` | Use JFR instead of JMX for overlapping metrics (Java 17+). | -| `otel.instrumentation.runtime-telemetry.experimental.package-emitter.enabled` | Boolean | `false` | Enable creating events for JAR libraries used by the application. | -| `otel.instrumentation.runtime-telemetry.experimental.package-emitter.jars-per-second` | Integer | 10 | The number of JAR files processed per second. | +| System property | Type | Default | Description | +| ------------------------------------------------------------------------------------- | ------- | ------- | --------------------------------------------------------------------------------------- | +| `otel.instrumentation.runtime-telemetry.emit-experimental-metrics` | Boolean | `false` | Enable the capture of experimental metrics. | +| `otel.instrumentation.runtime-telemetry.experimental.prefer-jfr` | Boolean | `false` | Prefer JFR over JMX for metrics where both collection methods are available (Java 17+). | +| `otel.instrumentation.runtime-telemetry.experimental.package-emitter.enabled` | Boolean | `false` | Enable creating events for JAR libraries used by the application. | +| `otel.instrumentation.runtime-telemetry.experimental.package-emitter.jars-per-second` | Integer | 10 | The number of JAR files processed per second. | ## Deprecated Properties (to be removed in 3.0) -| System property | Type | Default | Description | -|------------------------------------------------------------------------------------|---------|---------|-----------------------------------------------------------------------------------| -| `otel.instrumentation.runtime-telemetry.capture-gc-cause` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute. Will always be captured in 3.0. | -| `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Use `emit-experimental-metrics` instead. | -| `otel.instrumentation.runtime-telemetry.package-emitter.enabled` | Boolean | `false` | Use `experimental.package-emitter.enabled` instead. | -| `otel.instrumentation.runtime-telemetry.package-emitter.jars-per-second` | Integer | 10 | Use `experimental.package-emitter.jars-per-second` instead. | -| `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Deprecated. Use `emit-experimental-metrics` for experimental JFR features. | -| `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Deprecated. Use `emit-experimental-metrics` and `experimental.prefer-jfr`. | +| System property | Type | Default | Description | +| ------------------------------------------------------------------------ | ------- | ------- | --------------------------------------------------------------------------------- | +| `otel.instrumentation.runtime-telemetry.capture-gc-cause` | Boolean | `false` | Enable the capture of the jvm.gc.cause attribute. Will always be captured in 3.0. | +| `otel.instrumentation.runtime-telemetry.emit-experimental-telemetry` | Boolean | `false` | Use `emit-experimental-metrics` instead. | +| `otel.instrumentation.runtime-telemetry.package-emitter.enabled` | Boolean | `false` | Use `experimental.package-emitter.enabled` instead. | +| `otel.instrumentation.runtime-telemetry.package-emitter.jars-per-second` | Integer | 10 | Use `experimental.package-emitter.jars-per-second` instead. | +| `otel.instrumentation.runtime-telemetry-java17.enabled` | Boolean | `false` | Deprecated. Use `emit-experimental-metrics` for experimental JFR features. | +| `otel.instrumentation.runtime-telemetry-java17.enable-all` | Boolean | `false` | Deprecated. Use `emit-experimental-metrics` and `experimental.prefer-jfr`. | From b66c28dde519cbf63fbb358f99d7d6795dd20e92 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Mon, 9 Feb 2026 09:57:18 -0800 Subject: [PATCH 03/14] Move capture_gc_cause default back to false --- .../runtimetelemetry/RuntimeTelemetryBuilder.java | 2 +- .../runtimemetrics/java17/RuntimeMetricsBuilder.java | 2 +- .../runtimemetrics/java8/RuntimeMetricsBuilder.java | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java index f023d4f5e68e..9494abbb8e27 100644 --- a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java @@ -28,7 +28,7 @@ public final class RuntimeTelemetryBuilder { private boolean emitExperimentalMetrics = false; private boolean preferJfrMetrics = false; private boolean disableJmx = false; - private boolean captureGcCause = true; + private boolean captureGcCause = false; // For backward compatibility: support separate instrumentation names for JMX and JFR metrics private String jmxInstrumentationName = null; private String jfrInstrumentationName = null; diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java index 86317c89a676..1bd31f3de318 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java17/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java17/RuntimeMetricsBuilder.java @@ -32,7 +32,7 @@ public final class RuntimeMetricsBuilder { Internal.setJfrInstrumentationName(delegate, "io.opentelemetry.runtime-telemetry-java17"); // Use legacy metric for backward compatibility (jvm.cpu.limit instead of jvm.cpu.count) Internal.setUseLegacyJfrCpuCountMetric(delegate, true); - // java17 default for captureGcCause was false (unified module default is true) + // Explicitly set to preserve backward compatibility if unified default changes Internal.setCaptureGcCause(delegate, false); // Disable all JFR features first, then selectively enable based on java17 defaults. diff --git a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java index fbb4dcd15d03..8a5bddebab1c 100644 --- a/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java +++ b/instrumentation/runtime-telemetry/runtime-telemetry-java8/library/src/main/java/io/opentelemetry/instrumentation/runtimemetrics/java8/RuntimeMetricsBuilder.java @@ -31,7 +31,7 @@ public final class RuntimeMetricsBuilder { // Disable all JFR features - java8 module was JMX-only. This also ensures backward // compatibility if the unified module adds new default-enabled JFR features in the future. Internal.setDisableAllJfrFeatures(delegate, true); - // java8 default for captureGcCause was false (unified module default is true) + // Explicitly set to preserve backward compatibility if unified default changes Internal.setCaptureGcCause(delegate, false); } @@ -53,8 +53,7 @@ public RuntimeMetricsBuilder emitExperimentalTelemetry() { * Enable the capture of the jvm.gc.cause attribute with the jvm.gc.duration metric. * * @deprecated Use {@link RuntimeTelemetry#builder(OpenTelemetry)} in the {@code - * runtime-telemetry} module instead. The unified {@link RuntimeTelemetryBuilder} enables GC - * cause capture by default. + * runtime-telemetry} module instead. */ @Deprecated @CanIgnoreReturnValue From 4cf6b5549381c9d8fd6322cc19e3a0e706e116ca Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 18 Feb 2026 10:47:11 -0800 Subject: [PATCH 04/14] spotless --- .../instrumentation/runtimetelemetry/JarAnalyzer.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzer.java b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzer.java index a431beb621f1..5435445bcbbb 100644 --- a/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzer.java +++ b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/JarAnalyzer.java @@ -210,8 +210,7 @@ static void processUrl(Logger logger, URL archiveUrl) { try { jarDetails = JarDetails.forUrl(archiveUrl); } catch (IOException e) { - JarAnalyzer.logger.log( - WARNING, "Error reading package for archive URL: " + archiveUrl, e); + JarAnalyzer.logger.log(WARNING, "Error reading package for archive URL: " + archiveUrl, e); return; } AttributesBuilder builder = Attributes.builder(); From 5bb0edd14584900d57c96117e71b3b800f5efa1e Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sun, 22 Feb 2026 17:07:30 -0800 Subject: [PATCH 05/14] spotless --- .../runtimetelemetry/RuntimeTelemetryBuilder.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java index 9494abbb8e27..43ad9b6a8e62 100644 --- a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.runtimetelemetry; +import static java.util.Collections.emptyList; + import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.metrics.Meter; @@ -14,7 +16,6 @@ import io.opentelemetry.instrumentation.runtimetelemetry.internal.Internal; import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrConfig; import io.opentelemetry.instrumentation.runtimetelemetry.internal.JmxRuntimeMetricsFactory; -import java.util.Collections; import java.util.List; /** Builder for {@link RuntimeTelemetry}. */ @@ -105,7 +106,7 @@ public RuntimeTelemetry build() { List observables = disableJmx - ? Collections.emptyList() + ? emptyList() : JmxRuntimeMetricsFactory.buildObservables( emitExperimentalMetrics, captureGcCause, preferJfrMetrics, jmxMeter); AutoCloseable jfrTelemetry = jfrConfig.buildJfrTelemetry(preferJfrMetrics, jfrMeter); From 0d7deb8fbc366e847c7d8d024b2524a5ab502f04 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Thu, 26 Feb 2026 11:12:11 -0800 Subject: [PATCH 06/14] Replace AgentConfig with AgentDistributionConfig after upstream removal AgentConfig was removed in upstream commit 3c573ea449 and replaced with AgentDistributionConfig. Update Internal.configure() to accept boolean defaultEnabled instead of String instrumentationMode, and update all callers accordingly. --- .../runtimetelemetry/RuntimeTelemetryInstaller.java | 6 ++++-- .../runtimetelemetry/internal/Internal.java | 6 +++--- .../RuntimeMetricsAutoConfiguration.java | 13 +------------ 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/RuntimeTelemetryInstaller.java b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/RuntimeTelemetryInstaller.java index c7d56189cf9e..0e99957a3144 100644 --- a/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/RuntimeTelemetryInstaller.java +++ b/instrumentation/runtime-telemetry/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/runtimetelemetry/RuntimeTelemetryInstaller.java @@ -10,7 +10,7 @@ import io.opentelemetry.instrumentation.runtimetelemetry.RuntimeTelemetry; import io.opentelemetry.instrumentation.runtimetelemetry.internal.Internal; import io.opentelemetry.javaagent.extension.AgentListener; -import io.opentelemetry.javaagent.tooling.config.AgentConfig; +import io.opentelemetry.javaagent.extension.instrumentation.internal.AgentDistributionConfig; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; /** An {@link AgentListener} that enables runtime metrics during agent startup. */ @@ -20,7 +20,9 @@ public class RuntimeTelemetryInstaller implements AgentListener { @Override public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredSdk) { RuntimeTelemetry runtimeTelemetry = - Internal.configure(GlobalOpenTelemetry.get(), AgentConfig.instrumentationMode()); + Internal.configure( + GlobalOpenTelemetry.get(), + AgentDistributionConfig.get().isInstrumentationDefaultEnabled()); if (runtimeTelemetry != null) { Runtime.getRuntime() .addShutdownHook( diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java index c98869a843b3..651814467166 100644 --- a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java @@ -242,19 +242,19 @@ public static void internalSetDisableJmx(BiConsumer Date: Thu, 26 Feb 2026 11:26:48 -0800 Subject: [PATCH 07/14] spotless --- .../instrumentation/runtimetelemetry/internal/Internal.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java index 651814467166..e83eec717f6c 100644 --- a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java @@ -246,8 +246,7 @@ public static void internalSetDisableJmx(BiConsumer Date: Sat, 28 Feb 2026 13:19:59 -0800 Subject: [PATCH 08/14] updates --- .../runtimetelemetry/RuntimeTelemetryBuilder.java | 13 +++++++------ .../runtimetelemetry/internal/Internal.java | 4 ++-- .../runtimetelemetry/GenerateDocs.java | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java index 43ad9b6a8e62..7cfd392517b4 100644 --- a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java @@ -12,6 +12,7 @@ import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.metrics.MeterBuilder; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; +import javax.annotation.Nullable; import io.opentelemetry.instrumentation.runtimetelemetry.internal.Experimental; import io.opentelemetry.instrumentation.runtimetelemetry.internal.Internal; import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrConfig; @@ -26,13 +27,13 @@ public final class RuntimeTelemetryBuilder { private final OpenTelemetry openTelemetry; private final JfrConfig jfrConfig; - private boolean emitExperimentalMetrics = false; - private boolean preferJfrMetrics = false; - private boolean disableJmx = false; - private boolean captureGcCause = false; + private boolean emitExperimentalMetrics; + private boolean preferJfrMetrics; + private boolean disableJmx; + private boolean captureGcCause; // For backward compatibility: support separate instrumentation names for JMX and JFR metrics - private String jmxInstrumentationName = null; - private String jfrInstrumentationName = null; + @Nullable private String jmxInstrumentationName; + @Nullable private String jfrInstrumentationName; static { Experimental.internalSetEmitExperimentalMetrics( diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java index e83eec717f6c..e3c87f4a7862 100644 --- a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/internal/Internal.java @@ -55,8 +55,6 @@ public final class Internal { @Nullable private static volatile BiConsumer setDisableJmx; - private Internal() {} - /** * Sets whether all JFR features should be enabled. This is used for backward compatibility with * the {@code runtime_telemetry_java17.enable_all} configuration option. @@ -373,4 +371,6 @@ private static void configureUnified( } Internal.setCaptureGcCause(builder, captureGcCause); } + + private Internal() {} } diff --git a/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/GenerateDocs.java b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/GenerateDocs.java index bee04137c5f5..1ff6ccae9a58 100644 --- a/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/GenerateDocs.java +++ b/instrumentation/runtime-telemetry/library/src/testJava17/java/io/opentelemetry/instrumentation/runtimetelemetry/GenerateDocs.java @@ -102,7 +102,7 @@ private static String generateMarkdownTable() throws InterruptedException { .append("| ") .append(feature.name()) .append(" | ") - .append(feature.overlapsWithJmx()) + .append(!feature.overlapsWithJmx() && !feature.isExperimental()) .append(" | ") .append(metricCol) .append(" |") From 1814e5c8e79e6ecca87c5813e04fdf85fdfd3554 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sat, 28 Feb 2026 18:40:05 -0800 Subject: [PATCH 09/14] spotless --- .../runtimetelemetry/RuntimeTelemetryBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java index 7cfd392517b4..e2640675f9b7 100644 --- a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetryBuilder.java @@ -12,12 +12,12 @@ import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.metrics.MeterBuilder; import io.opentelemetry.instrumentation.api.internal.EmbeddedInstrumentationProperties; -import javax.annotation.Nullable; import io.opentelemetry.instrumentation.runtimetelemetry.internal.Experimental; import io.opentelemetry.instrumentation.runtimetelemetry.internal.Internal; import io.opentelemetry.instrumentation.runtimetelemetry.internal.JfrConfig; import io.opentelemetry.instrumentation.runtimetelemetry.internal.JmxRuntimeMetricsFactory; import java.util.List; +import javax.annotation.Nullable; /** Builder for {@link RuntimeTelemetry}. */ public final class RuntimeTelemetryBuilder { From c7b3a898f4c1664173ba4f664b013f6684797089 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Mon, 2 Mar 2026 17:13:51 -0800 Subject: [PATCH 10/14] spotless --- .../instrumentation/runtimetelemetry/RuntimeTelemetry.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetry.java b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetry.java index 2cd832b8f46c..28fd0207b2c5 100644 --- a/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetry.java +++ b/instrumentation/runtime-telemetry/library/src/main/java/io/opentelemetry/instrumentation/runtimetelemetry/RuntimeTelemetry.java @@ -5,11 +5,12 @@ package io.opentelemetry.instrumentation.runtimetelemetry; +import static java.util.logging.Level.WARNING; + import io.opentelemetry.api.OpenTelemetry; import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; @@ -58,7 +59,7 @@ AutoCloseable getJfrTelemetry() { @Override public void close() { if (!isClosed.compareAndSet(false, true)) { - logger.log(Level.WARNING, "RuntimeTelemetry is already closed"); + logger.log(WARNING, "RuntimeTelemetry is already closed"); return; } @@ -66,7 +67,7 @@ public void close() { try { jfrTelemetry.close(); } catch (Exception e) { - logger.log(Level.WARNING, "Error closing JFR telemetry", e); + logger.log(WARNING, "Error closing JFR telemetry", e); } } From e5a4c100e13c31881aad72fc65351a9b7ac7b358 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Mon, 9 Mar 2026 08:14:45 -0700 Subject: [PATCH 11/14] expression-switch --- .../internal/HandlerRegistry.java | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java index 7b4a7c9e5a57..b5a1c58a1565 100644 --- a/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java @@ -35,7 +35,6 @@ final class HandlerRegistry { private HandlerRegistry() {} - @SuppressWarnings("StatementSwitchToExpressionSwitch") static List getHandlers( Meter meter, Predicate featurePredicate, boolean useLegacyCpuCountMetric) { @@ -43,28 +42,20 @@ static List getHandlers( for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) { String name = bean.getName(); switch (name) { - case "G1 Young Generation": + case "G1 Young Generation" -> { handlers.add(new G1HeapSummaryHandler(meter)); handlers.add(new G1GarbageCollectionHandler(meter)); - break; + } - case "Copy": - handlers.add(new YoungGarbageCollectionHandler(meter, name)); - break; + case "Copy" -> handlers.add(new YoungGarbageCollectionHandler(meter, name)); - case "PS Scavenge": + case "PS Scavenge" -> { handlers.add(new YoungGarbageCollectionHandler(meter, name)); handlers.add(new ParallelHeapSummaryHandler(meter)); - break; - - case "G1 Old Generation": - case "PS MarkSweep": - case "MarkSweepCompact": - handlers.add(new OldGarbageCollectionHandler(meter, name)); - break; + } - default: - // If none of the above GCs are detected, no action. + case "G1 Old Generation", "PS MarkSweep", "MarkSweepCompact" -> + handlers.add(new OldGarbageCollectionHandler(meter, name)); } } From 7b5c046f06e4cb069b038a7c6eeeebd5290111c2 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Mon, 9 Mar 2026 08:16:59 -0700 Subject: [PATCH 12/14] warning --- instrumentation/runtime-telemetry/library/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/instrumentation/runtime-telemetry/library/README.md b/instrumentation/runtime-telemetry/library/README.md index 29339b21382b..10800c87afb1 100644 --- a/instrumentation/runtime-telemetry/library/README.md +++ b/instrumentation/runtime-telemetry/library/README.md @@ -121,6 +121,11 @@ These metrics are enabled with `emitExperimentalMetrics()`: **JFR-based (Java 17+ only):** +> **Warning**: JFR events might not be available for all JVMs or with a GraalVM native image, +> therefore limiting the produced metrics. The original implementation was done for Hotspot. OpenJ9 +> currently (Nov. 2025) only has the VM-level JFR implementation. So events emitted at the Java +> level (ie. in jdk.jfr) will not be present. Meaning, jdk.SocketRead, jdk.SocketWrite won't work. + | Metric | Description | | -------- | ----------- | | `jvm.cpu.context_switch` | Context switch rate | From 18fb7a805686943b7b597e8556766bf7426849a1 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Mon, 9 Mar 2026 09:00:41 -0700 Subject: [PATCH 13/14] Add default case to switch in HandlerRegistry to fix MissingDefault error --- .../runtimetelemetry/internal/HandlerRegistry.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java index b5a1c58a1565..156b18d3b2b2 100644 --- a/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java +++ b/instrumentation/runtime-telemetry/library/src/main/java17/io/opentelemetry/instrumentation/runtimetelemetry/internal/HandlerRegistry.java @@ -56,6 +56,8 @@ static List getHandlers( case "G1 Old Generation", "PS MarkSweep", "MarkSweepCompact" -> handlers.add(new OldGarbageCollectionHandler(meter, name)); + + default -> {} } } From 3ae6d19781dfddbc0acf0795e34e7d6904b73968 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Mon, 9 Mar 2026 09:52:21 -0700 Subject: [PATCH 14/14] Fix checkstyle WhitespaceAround violation in HandlerRegistry.java --- buildscripts/checkstyle.xml | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/buildscripts/checkstyle.xml b/buildscripts/checkstyle.xml index 1513e1f92d4b..f15568cc72bd 100644 --- a/buildscripts/checkstyle.xml +++ b/buildscripts/checkstyle.xml @@ -88,26 +88,7 @@ value="COMMA, SEMI, TYPECAST, LITERAL_IF, LITERAL_ELSE, LITERAL_WHILE, LITERAL_DO, LITERAL_FOR, DO_WHILE"/> - - - - - - - - - - - +