-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Unify runtime-telemetry modules #16087
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
82b07aa
1048c95
b66c28d
4cf6b55
783dcf5
5bb0edd
7bfa164
0d7deb8
b8b12fb
d973779
9828150
1814e5c
c44e38c
c7b3a89
e5a4c10
7b5c046
856f20d
18fb7a8
3ae6d19
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +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` | 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 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. | | ||
| | ------------------------------------------------------------------------ | ------- | ------- | --------------------------------------------------------------------------------- | | ||
| | `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`. | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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") | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 = | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use import
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can't because also using |
||
| java.util.logging.Logger.getLogger(JarAnalyzer.class.getName()); | ||
|
|
||
| private static final String EVENT_NAME_INFO = "package.info"; | ||
| static final AttributeKey<String> PACKAGE_NAME = AttributeKey.stringKey("package.name"); | ||
|
|
@@ -59,25 +59,27 @@ final class JarAnalyzer implements ClassFileTransformer { | |
| private final Set<URI> seenUris = new HashSet<>(); | ||
| private final BlockingQueue<URL> 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 = | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. version is nullable - add requireNonNull
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why? |
||
| EmbeddedInstrumentationProperties.findVersion(instrumentationName); | ||
| Logger logger = | ||
| openTelemetry | ||
| .getLogsBridge() | ||
| .loggerBuilder(instrumentationName) | ||
| .setInstrumentationVersion(instrumentationVersion) | ||
| .build(); | ||
| Worker worker = new Worker(logger, toProcess, jarsPerSecond); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unrelated improvement: Using Logger instead LogRecordBuilder (since it's used to emit multiple logs) |
||
| Thread workerThread = | ||
| new DaemonThreadFactory(JarAnalyzer.class.getSimpleName() + "_WorkerThread") | ||
| .newThread(worker); | ||
| workerThread.start(); | ||
| } | ||
|
|
||
| /** 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<URL> toProcess; | ||
| private final RateLimiter rateLimiter; | ||
|
|
||
| private Worker( | ||
| ExtendedLogRecordBuilder eventLogger, BlockingQueue<URL> toProcess, int jarsPerSecond) { | ||
| this.eventLogger = eventLogger; | ||
| private Worker(Logger logger, BlockingQueue<URL> 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,25 +191,26 @@ 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"); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * 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 +244,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(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 = | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do I get it right that we're no longer checking if a module is active?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's still being checked, a few lines down |
||
| 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); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this rule conflicted with spotless handling of empty default expression in Java 17 switch statement
we could probably get rid of a lot of checkstyle checks that are already covered by spotless