Skip to content

declarative config: early init and property mapping #14184

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

Open
wants to merge 33 commits into
base: main
Choose a base branch
from

Conversation

zeitlinger
Copy link
Member

@zeitlinger zeitlinger commented Jul 4, 2025

Fixes #14133
Fixes #14134
Fixes #14132

Integration test already existed before:

testing {
suites {
val declarativeConfigTest by registering(JvmTestSuite::class) {
targets {
all {
testTask.configure {
jvmArgs(
"-Dotel.experimental.config.file=$projectDir/src/declarativeConfigTest/resources/declarative-config.yaml"
)
}
}
}
}
}
}

@zeitlinger zeitlinger requested a review from a team as a code owner July 4, 2025 16:56
@zeitlinger zeitlinger marked this pull request as draft July 4, 2025 16:56
@zeitlinger zeitlinger self-assigned this Jul 4, 2025
@zeitlinger zeitlinger marked this pull request as ready for review July 7, 2025 08:14
@zeitlinger
Copy link
Member Author

zeitlinger commented Jul 7, 2025

@laurit @trask please have a look 😄

I will create a bunch of follow up tasks to not make this PR bigger.

this.configurationModel, SpiHelper.serviceComponentLoader(extensionClassLoader));
Runtime.getRuntime().addShutdownHook(new Thread(sdk::close));
GlobalOpenTelemetry.set(sdk);
GlobalConfigProvider.set(this.configProvider);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created #14191 for the corresponding instrumentation

"otel.javaagent.logging.application.logs-buffer-max-records",
"agent.logging.output.application.logs_buffer_max_records");

// todo not supported in SDK yet (this is strictly typed)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zeitlinger zeitlinger force-pushed the declarative-config-underscore branch from ea7fdfd to a36770e Compare July 7, 2025 11:37
* io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties}) is initialized.
*/
public final class EarlyInitAgentConfig {
public interface EarlyInitAgentConfig {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is some brave stuff. I suspect that you don't fully comprehend why the original code was written the way it is now and where the footgun lays.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall I make a walkthrough in the SIG meeting?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall I make a walkthrough in the SIG meeting?

I don't think it is necessary, it is not hard to see what your goal is.
If you look at how the EarlyInitAgentConfig is currently used you'll see that it is mostly about logging. The problem with logging is that currently it should be configured before anything is logged. You should check what will happen when you try to log anything before. Idk might not be too bad, could be that only the logger that was created before logging is configured will end up as a nop logger. Then would need to hope that nothing important is logged with that logger. The more code you need to run the harder it is to verify that that code does not use logging before it is configured. Even if you manage to verify that currently the declarative config code and all the libraries it uses doesn't use logging before it is configured you can't guarantee that it won't happen in a future version. Currently we have tried not to use logging before it is configured, you should try to figure out whether this is sustainable or maybe a different approach is needed. For example could buffer log messages before logging is configured.
Another issue is that we wish to install virtual fields into some jdk classes in

. For this we need to set up the transformations before these classes are loaded, otherwise virtual fields will fall back to a map which is undesirable. Reading the declarative config is going to pull in a bunch of classes which could load the classes we wish to transform. We may need to rearrange the code to install the early instrumentations before configuration is available to ensure that we can transform the classes before they are loaded.
There are some configuration options like that aren't really useful for end users, imo it is not important for these to be configurable from declarative config (if needed could consider removing the option).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shall I make a walkthrough in the SIG meeting?

I don't think it is necessary, it is not hard to see what your goal is. If you look at how the EarlyInitAgentConfig is currently used you'll see that it is mostly about logging.

so we have

  • logging
  • bytecode transformation
  • early return (if agent is disabled)

The motivation for my change is the early return, which is done differently in case of the config file.
Maybe this is not worth it - and we should go back to using sys properties for this.

that aren't really useful for end users

great point - can you list which properties are actually relevant for users from the list in #14132 ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The motivation for my change is the early return, which is done differently in case of the config file.
Maybe this is not worth it - and we should go back to using sys properties for this.

It could be done, but it requires careful handling.

great point - can you list which properties are actually relevant for users from the list in #14132 ?

I think the following could be useful for endusers
otel.javaagent.add-thread-details
otel.javaagent.configuration-file
otel.javaagent.debug
otel.javaagent.enabled
otel.javaagent.exclude-class-loaders
otel.javaagent.exclude-classes
otel.javaagent.experimental.security-manager-support.enabled
otel.javaagent.experimental.thread-propagation-debugger.enabled
otel.javaagent.extensions
otel.javaagent.logging.application.logs-buffer-max-records
otel.javaagent.logging

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not read from config file with current PR

  • otel.javaagent.experimental.security-manager-support.enabled
  • otel.javaagent.experimental.thread-propagation-debugger.enabled

would not be read from config file if we choose a simpler approach

  • otel.javaagent.extensions
  • otel.javaagent.logging.application.logs-buffer-max-records
  • otel.javaagent.logging
  • otel.javaagent.enabled

is read from config file either way

  • otel.javaagent.exclude-classes
  • otel.javaagent.exclude-class-loaders
  • otel.javaagent.add-thread-details

mix of all of the above

  • otel.javaagent.debug

disallowed with declarative config

  • otel.javaagent.configuration-file

@zeitlinger
Copy link
Member Author

We may need to rearrange the code to install the early instrumentations before configuration is available to ensure that we can transform the classes before they are loaded.

This still leaves "otel.javaagent.enabled" - which promises not to touch anything if the value is false.

@zeitlinger
Copy link
Member Author

The problem with logging is that currently it should be configured before anything is logged

https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/DeclarativeConfiguration.java doesn't log for the method that we call - but jackson can throw exceptions (which I can buffer like ConfigurationFile)

@zeitlinger
Copy link
Member Author

Reading the declarative config is going to pull in a bunch of classes which could load the classes we wish to transform

How can we find out if that's the case? E.g. a tool to compare loaded classes against what we want to transform.

@zeitlinger
Copy link
Member Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants