Pārlūkot izejas kodu

Set up EarlyInitAgentConfig even earlier (#8413)

Mateusz Rzeszutek 1 gadu atpakaļ
vecāks
revīzija
9b82a01dd7
14 mainītis faili ar 120 papildinājumiem un 91 dzēšanām
  1. 3 4
      javaagent-internal-logging-application/src/main/java/io/opentelemetry/javaagent/logging/application/ApplicationLoggingCustomizer.java
  2. 3 25
      javaagent-internal-logging-simple/src/main/java/io/opentelemetry/javaagent/logging/simple/Slf4jSimpleLoggingCustomizer.java
  3. 3 3
      javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java
  4. 11 7
      javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java
  5. 12 15
      javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ExtensionClassLoader.java
  6. 3 2
      javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/LoggingCustomizer.java
  7. 2 1
      javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/NoopLoggingCustomizer.java
  8. 20 22
      javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigurationFile.java
  9. 25 0
      javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigurationPropertiesSupplier.java
  10. 26 1
      javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/EarlyInitAgentConfig.java
  11. 2 1
      javaagent-tooling/src/test/groovy/io/opentelemetry/javaagent/test/HelperInjectionTest.groovy
  12. 5 5
      javaagent-tooling/src/test/groovy/io/opentelemetry/javaagent/tooling/config/ConfigurationFileTest.groovy
  13. 3 3
      javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/config/ConfigurationPropertiesSupplierTest.java
  14. 2 2
      javaagent-tooling/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider

+ 3 - 4
javaagent-internal-logging-application/src/main/java/io/opentelemetry/javaagent/logging/application/ApplicationLoggingCustomizer.java

@@ -6,10 +6,10 @@
 package io.opentelemetry.javaagent.logging.application;
 package io.opentelemetry.javaagent.logging.application;
 
 
 import com.google.auto.service.AutoService;
 import com.google.auto.service.AutoService;
-import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
 import io.opentelemetry.javaagent.bootstrap.InternalLogger;
 import io.opentelemetry.javaagent.bootstrap.InternalLogger;
 import io.opentelemetry.javaagent.bootstrap.logging.ApplicationLoggerBridge;
 import io.opentelemetry.javaagent.bootstrap.logging.ApplicationLoggerBridge;
 import io.opentelemetry.javaagent.tooling.LoggingCustomizer;
 import io.opentelemetry.javaagent.tooling.LoggingCustomizer;
+import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig;
 
 
 @AutoService(LoggingCustomizer.class)
 @AutoService(LoggingCustomizer.class)
 public final class ApplicationLoggingCustomizer implements LoggingCustomizer {
 public final class ApplicationLoggingCustomizer implements LoggingCustomizer {
@@ -20,10 +20,9 @@ public final class ApplicationLoggingCustomizer implements LoggingCustomizer {
   }
   }
 
 
   @Override
   @Override
-  public void init() {
+  public void init(EarlyInitAgentConfig earlyConfig) {
     int limit =
     int limit =
-        ConfigPropertiesUtil.getInt(
-            "otel.javaagent.logging.application.logs-buffer-max-records", 2048);
+        earlyConfig.getInt("otel.javaagent.logging.application.logs-buffer-max-records", 2048);
     InMemoryLogStore inMemoryLogStore = new InMemoryLogStore(limit);
     InMemoryLogStore inMemoryLogStore = new InMemoryLogStore(limit);
     ApplicationLoggerFactory loggerFactory = new ApplicationLoggerFactory(inMemoryLogStore);
     ApplicationLoggerFactory loggerFactory = new ApplicationLoggerFactory(inMemoryLogStore);
     // register a shutdown hook that'll dump the logs to stderr in case something goes wrong
     // register a shutdown hook that'll dump the logs to stderr in case something goes wrong

+ 3 - 25
javaagent-internal-logging-simple/src/main/java/io/opentelemetry/javaagent/logging/simple/Slf4jSimpleLoggingCustomizer.java

@@ -8,7 +8,7 @@ package io.opentelemetry.javaagent.logging.simple;
 import com.google.auto.service.AutoService;
 import com.google.auto.service.AutoService;
 import io.opentelemetry.javaagent.bootstrap.InternalLogger;
 import io.opentelemetry.javaagent.bootstrap.InternalLogger;
 import io.opentelemetry.javaagent.tooling.LoggingCustomizer;
 import io.opentelemetry.javaagent.tooling.LoggingCustomizer;
-import java.util.Locale;
+import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig;
 import org.slf4j.LoggerFactory;
 import org.slf4j.LoggerFactory;
 
 
 @AutoService(LoggingCustomizer.class)
 @AutoService(LoggingCustomizer.class)
@@ -31,12 +31,12 @@ public final class Slf4jSimpleLoggingCustomizer implements LoggingCustomizer {
   }
   }
 
 
   @Override
   @Override
-  public void init() {
+  public void init(EarlyInitAgentConfig earlyConfig) {
     setSystemPropertyDefault(SIMPLE_LOGGER_SHOW_DATE_TIME_PROPERTY, "true");
     setSystemPropertyDefault(SIMPLE_LOGGER_SHOW_DATE_TIME_PROPERTY, "true");
     setSystemPropertyDefault(
     setSystemPropertyDefault(
         SIMPLE_LOGGER_DATE_TIME_FORMAT_PROPERTY, SIMPLE_LOGGER_DATE_TIME_FORMAT_DEFAULT);
         SIMPLE_LOGGER_DATE_TIME_FORMAT_PROPERTY, SIMPLE_LOGGER_DATE_TIME_FORMAT_DEFAULT);
 
 
-    if (isDebugMode()) {
+    if (earlyConfig.getBoolean("otel.javaagent.debug", false)) {
       setSystemPropertyDefault(SIMPLE_LOGGER_DEFAULT_LOG_LEVEL_PROPERTY, "DEBUG");
       setSystemPropertyDefault(SIMPLE_LOGGER_DEFAULT_LOG_LEVEL_PROPERTY, "DEBUG");
       setSystemPropertyDefault(SIMPLE_LOGGER_PREFIX + "okhttp3.internal.http2", "INFO");
       setSystemPropertyDefault(SIMPLE_LOGGER_PREFIX + "okhttp3.internal.http2", "INFO");
     }
     }
@@ -63,26 +63,4 @@ public final class Slf4jSimpleLoggingCustomizer implements LoggingCustomizer {
       System.setProperty(property, value);
       System.setProperty(property, value);
     }
     }
   }
   }
-
-  /**
-   * Determine if we should log in debug level according to otel.javaagent.debug
-   *
-   * @return true if we should
-   */
-  private static boolean isDebugMode() {
-    String tracerDebugLevelSysprop = "otel.javaagent.debug";
-    String tracerDebugLevelProp = System.getProperty(tracerDebugLevelSysprop);
-
-    if (tracerDebugLevelProp != null) {
-      return Boolean.parseBoolean(tracerDebugLevelProp);
-    }
-
-    String tracerDebugLevelEnv =
-        System.getenv(tracerDebugLevelSysprop.replace('.', '_').toUpperCase(Locale.ROOT));
-
-    if (tracerDebugLevelEnv != null) {
-      return Boolean.parseBoolean(tracerDebugLevelEnv);
-    }
-    return false;
-  }
 }
 }

+ 3 - 3
javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentInstaller.java

@@ -80,7 +80,8 @@ public class AgentInstaller {
 
 
   private static final Map<String, List<Runnable>> CLASS_LOAD_CALLBACKS = new HashMap<>();
   private static final Map<String, List<Runnable>> CLASS_LOAD_CALLBACKS = new HashMap<>();
 
 
-  public static void installBytebuddyAgent(Instrumentation inst, ClassLoader extensionClassLoader) {
+  public static void installBytebuddyAgent(
+      Instrumentation inst, ClassLoader extensionClassLoader, EarlyInitAgentConfig earlyConfig) {
     addByteBuddyRawSetting();
     addByteBuddyRawSetting();
 
 
     Integer strictContextStressorMillis = Integer.getInteger(STRICT_CONTEXT_STRESSOR_MILLIS);
     Integer strictContextStressorMillis = Integer.getInteger(STRICT_CONTEXT_STRESSOR_MILLIS);
@@ -90,8 +91,7 @@ public class AgentInstaller {
     }
     }
 
 
     logVersionInfo();
     logVersionInfo();
-    EarlyInitAgentConfig agentConfig = EarlyInitAgentConfig.create();
-    if (agentConfig.getBoolean(JAVAAGENT_ENABLED_CONFIG, true)) {
+    if (earlyConfig.getBoolean(JAVAAGENT_ENABLED_CONFIG, true)) {
       setupUnsafe(inst);
       setupUnsafe(inst);
       List<AgentListener> agentListeners = loadOrdered(AgentListener.class, extensionClassLoader);
       List<AgentListener> agentListeners = loadOrdered(AgentListener.class, extensionClassLoader);
       installBytebuddyAgent(inst, extensionClassLoader, agentListeners);
       installBytebuddyAgent(inst, extensionClassLoader, agentListeners);

+ 11 - 7
javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java

@@ -6,10 +6,10 @@
 package io.opentelemetry.javaagent.tooling;
 package io.opentelemetry.javaagent.tooling;
 
 
 import io.opentelemetry.context.Context;
 import io.opentelemetry.context.Context;
-import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
 import io.opentelemetry.instrumentation.api.internal.cache.weaklockfree.WeakConcurrentMapCleaner;
 import io.opentelemetry.instrumentation.api.internal.cache.weaklockfree.WeakConcurrentMapCleaner;
 import io.opentelemetry.javaagent.bootstrap.AgentInitializer;
 import io.opentelemetry.javaagent.bootstrap.AgentInitializer;
 import io.opentelemetry.javaagent.bootstrap.AgentStarter;
 import io.opentelemetry.javaagent.bootstrap.AgentStarter;
+import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig;
 import java.io.File;
 import java.io.File;
 import java.lang.instrument.ClassFileTransformer;
 import java.lang.instrument.ClassFileTransformer;
 import java.lang.instrument.Instrumentation;
 import java.lang.instrument.Instrumentation;
@@ -67,9 +67,10 @@ public class AgentStarterImpl implements AgentStarter {
 
 
   @Override
   @Override
   public void start() {
   public void start() {
-    extensionClassLoader = createExtensionClassLoader(getClass().getClassLoader());
+    EarlyInitAgentConfig earlyConfig = EarlyInitAgentConfig.create();
+    extensionClassLoader = createExtensionClassLoader(getClass().getClassLoader(), earlyConfig);
 
 
-    String loggerImplementationName = ConfigPropertiesUtil.getString("otel.javaagent.logging");
+    String loggerImplementationName = earlyConfig.getString("otel.javaagent.logging");
     // default to the built-in stderr slf4j-simple logger
     // default to the built-in stderr slf4j-simple logger
     if (loggerImplementationName == null) {
     if (loggerImplementationName == null) {
       loggerImplementationName = "simple";
       loggerImplementationName = "simple";
@@ -91,8 +92,10 @@ public class AgentStarterImpl implements AgentStarter {
 
 
     Throwable startupError = null;
     Throwable startupError = null;
     try {
     try {
-      loggingCustomizer.init();
-      AgentInstaller.installBytebuddyAgent(instrumentation, extensionClassLoader);
+      loggingCustomizer.init(earlyConfig);
+      earlyConfig.logEarlyConfigErrorsIfAny();
+
+      AgentInstaller.installBytebuddyAgent(instrumentation, extensionClassLoader, earlyConfig);
       WeakConcurrentMapCleaner.start();
       WeakConcurrentMapCleaner.start();
 
 
       // LazyStorage reads system properties. Initialize it here where we have permissions to avoid
       // LazyStorage reads system properties. Initialize it here where we have permissions to avoid
@@ -124,9 +127,10 @@ public class AgentStarterImpl implements AgentStarter {
     return extensionClassLoader;
     return extensionClassLoader;
   }
   }
 
 
-  private ClassLoader createExtensionClassLoader(ClassLoader agentClassLoader) {
+  private ClassLoader createExtensionClassLoader(
+      ClassLoader agentClassLoader, EarlyInitAgentConfig earlyConfig) {
     return ExtensionClassLoader.getInstance(
     return ExtensionClassLoader.getInstance(
-        agentClassLoader, javaagentFile, isSecurityManagerSupportEnabled);
+        agentClassLoader, javaagentFile, isSecurityManagerSupportEnabled, earlyConfig);
   }
   }
 
 
   private static class LaunchHelperClassFileTransformer implements ClassFileTransformer {
   private static class LaunchHelperClassFileTransformer implements ClassFileTransformer {

+ 12 - 15
javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/ExtensionClassLoader.java

@@ -5,6 +5,7 @@
 
 
 package io.opentelemetry.javaagent.tooling;
 package io.opentelemetry.javaagent.tooling;
 
 
+import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig;
 import java.io.File;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.IOException;
@@ -25,6 +26,7 @@ import java.util.Enumeration;
 import java.util.List;
 import java.util.List;
 import java.util.jar.JarEntry;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.JarFile;
+import javax.annotation.Nullable;
 import net.bytebuddy.dynamic.loading.MultipleParentClassLoader;
 import net.bytebuddy.dynamic.loading.MultipleParentClassLoader;
 
 
 /**
 /**
@@ -36,8 +38,7 @@ import net.bytebuddy.dynamic.loading.MultipleParentClassLoader;
  * MultipleParentClassLoader}.
  * MultipleParentClassLoader}.
  */
  */
 // TODO find a way to initialize logging before using this class
 // TODO find a way to initialize logging before using this class
-// Used by AgentInitializer
-@SuppressWarnings({"unused", "SystemOut"})
+@SuppressWarnings("SystemOut")
 public class ExtensionClassLoader extends URLClassLoader {
 public class ExtensionClassLoader extends URLClassLoader {
   public static final String EXTENSIONS_CONFIG = "otel.javaagent.extensions";
   public static final String EXTENSIONS_CONFIG = "otel.javaagent.extensions";
 
 
@@ -51,22 +52,19 @@ public class ExtensionClassLoader extends URLClassLoader {
   }
   }
 
 
   public static ClassLoader getInstance(
   public static ClassLoader getInstance(
-      ClassLoader parent, File javaagentFile, boolean isSecurityManagerSupportEnabled) {
+      ClassLoader parent,
+      File javaagentFile,
+      boolean isSecurityManagerSupportEnabled,
+      EarlyInitAgentConfig earlyConfig) {
     List<URL> extensions = new ArrayList<>();
     List<URL> extensions = new ArrayList<>();
 
 
-    includeEmbeddedExtensionsIfFound(parent, extensions, javaagentFile);
+    includeEmbeddedExtensionsIfFound(extensions, javaagentFile);
 
 
-    extensions.addAll(
-        parseLocation(
-            System.getProperty(EXTENSIONS_CONFIG, System.getenv("OTEL_JAVAAGENT_EXTENSIONS")),
-            javaagentFile));
+    extensions.addAll(parseLocation(earlyConfig.getString(EXTENSIONS_CONFIG), javaagentFile));
 
 
     extensions.addAll(
     extensions.addAll(
         parseLocation(
         parseLocation(
-            System.getProperty(
-                "otel.javaagent.experimental.extensions",
-                System.getenv("OTEL_JAVAAGENT_EXPERIMENTAL_EXTENSIONS")),
-            javaagentFile));
+            earlyConfig.getString("otel.javaagent.experimental.extensions"), javaagentFile));
 
 
     // TODO when logging is configured add warning about deprecated property
     // TODO when logging is configured add warning about deprecated property
 
 
@@ -81,8 +79,7 @@ public class ExtensionClassLoader extends URLClassLoader {
     return new MultipleParentClassLoader(parent, delegates);
     return new MultipleParentClassLoader(parent, delegates);
   }
   }
 
 
-  private static void includeEmbeddedExtensionsIfFound(
-      ClassLoader parent, List<URL> extensions, File javaagentFile) {
+  private static void includeEmbeddedExtensionsIfFound(List<URL> extensions, File javaagentFile) {
     try {
     try {
       JarFile jarFile = new JarFile(javaagentFile, false);
       JarFile jarFile = new JarFile(javaagentFile, false);
       Enumeration<JarEntry> entryEnumeration = jarFile.entries();
       Enumeration<JarEntry> entryEnumeration = jarFile.entries();
@@ -132,7 +129,7 @@ public class ExtensionClassLoader extends URLClassLoader {
   }
   }
 
 
   // visible for testing
   // visible for testing
-  static List<URL> parseLocation(String locationName, File javaagentFile) {
+  static List<URL> parseLocation(@Nullable String locationName, File javaagentFile) {
     if (locationName == null) {
     if (locationName == null) {
       return Collections.emptyList();
       return Collections.emptyList();
     }
     }

+ 3 - 2
javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/LoggingCustomizer.java

@@ -5,6 +5,7 @@
 
 
 package io.opentelemetry.javaagent.tooling;
 package io.opentelemetry.javaagent.tooling;
 
 
+import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig;
 import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
 import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
 
 
 // only one LoggingCustomizer is allowed, and its presence will suppress the
 // only one LoggingCustomizer is allowed, and its presence will suppress the
@@ -21,7 +22,7 @@ public interface LoggingCustomizer {
   // note that if this throws an exception, it will end up calling onStartupFailure, because
   // note that if this throws an exception, it will end up calling onStartupFailure, because
   // otherwise that exception will bubble up to OpenTelemetryAgent where a distro cannot control the
   // otherwise that exception will bubble up to OpenTelemetryAgent where a distro cannot control the
   // logging of it.
   // logging of it.
-  void init();
+  void init(EarlyInitAgentConfig earlyConfig);
 
 
   /**
   /**
    * Register a callback which will be called on synchronous startup success.
    * Register a callback which will be called on synchronous startup success.
@@ -34,7 +35,7 @@ public interface LoggingCustomizer {
 
 
   /**
   /**
    * Register a callback which will be called on synchronous startup failure (including if {@link
    * Register a callback which will be called on synchronous startup failure (including if {@link
-   * #init()} fails).
+   * #init(EarlyInitAgentConfig)} fails).
    *
    *
    * <p>Synchronous startup may or may not include running {@link
    * <p>Synchronous startup may or may not include running {@link
    * io.opentelemetry.javaagent.extension.AgentListener#afterAgent(
    * io.opentelemetry.javaagent.extension.AgentListener#afterAgent(

+ 2 - 1
javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/NoopLoggingCustomizer.java

@@ -6,6 +6,7 @@
 package io.opentelemetry.javaagent.tooling;
 package io.opentelemetry.javaagent.tooling;
 
 
 import com.google.auto.service.AutoService;
 import com.google.auto.service.AutoService;
+import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig;
 
 
 @AutoService(LoggingCustomizer.class)
 @AutoService(LoggingCustomizer.class)
 public final class NoopLoggingCustomizer implements LoggingCustomizer {
 public final class NoopLoggingCustomizer implements LoggingCustomizer {
@@ -16,7 +17,7 @@ public final class NoopLoggingCustomizer implements LoggingCustomizer {
   }
   }
 
 
   @Override
   @Override
-  public void init() {}
+  public void init(EarlyInitAgentConfig earlyConfig) {}
 
 
   @Override
   @Override
   @SuppressWarnings("SystemOut")
   @SuppressWarnings("SystemOut")

+ 20 - 22
javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigurationFileLoader.java → javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigurationFile.java

@@ -8,10 +8,7 @@ package io.opentelemetry.javaagent.tooling.config;
 import static java.util.Collections.emptyMap;
 import static java.util.Collections.emptyMap;
 import static java.util.logging.Level.SEVERE;
 import static java.util.logging.Level.SEVERE;
 
 
-import com.google.auto.service.AutoService;
 import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
 import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
-import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
-import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
 import java.io.File;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileNotFoundException;
@@ -22,22 +19,20 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.Properties;
 import java.util.logging.Logger;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
+import javax.annotation.Nullable;
 
 
-@AutoService(AutoConfigurationCustomizerProvider.class)
-public final class ConfigurationFileLoader implements AutoConfigurationCustomizerProvider {
-
-  private static final Logger logger = Logger.getLogger(ConfigurationFileLoader.class.getName());
+final class ConfigurationFile {
 
 
   static final String CONFIGURATION_FILE_PROPERTY = "otel.javaagent.configuration-file";
   static final String CONFIGURATION_FILE_PROPERTY = "otel.javaagent.configuration-file";
 
 
   private static Map<String, String> configFileContents;
   private static Map<String, String> configFileContents;
 
 
-  @Override
-  public void customize(AutoConfigurationCustomizer autoConfiguration) {
-    autoConfiguration.addPropertiesSupplier(ConfigurationFileLoader::getConfigFileContents);
-  }
+  // this class is used early, and must not use logging in most of its methods
+  // in case any file loading/parsing error occurs, we save the error message and log it later, when
+  // the logging subsystem is initialized
+  @Nullable private static String fileLoadErrorMessage;
 
 
-  static Map<String, String> getConfigFileContents() {
+  static Map<String, String> getProperties() {
     if (configFileContents == null) {
     if (configFileContents == null) {
       configFileContents = loadConfigFile();
       configFileContents = loadConfigFile();
     }
     }
@@ -59,7 +54,7 @@ public final class ConfigurationFileLoader implements AutoConfigurationCustomize
     // Configuration properties file is optional
     // Configuration properties file is optional
     File configurationFile = new File(configurationFilePath);
     File configurationFile = new File(configurationFilePath);
     if (!configurationFile.exists()) {
     if (!configurationFile.exists()) {
-      logger.log(SEVERE, "Configuration file \"{0}\" not found.", configurationFilePath);
+      fileLoadErrorMessage = "Configuration file \"" + configurationFilePath + "\" not found.";
       return emptyMap();
       return emptyMap();
     }
     }
 
 
@@ -68,21 +63,24 @@ public final class ConfigurationFileLoader implements AutoConfigurationCustomize
         new InputStreamReader(new FileInputStream(configurationFile), StandardCharsets.UTF_8)) {
         new InputStreamReader(new FileInputStream(configurationFile), StandardCharsets.UTF_8)) {
       properties.load(reader);
       properties.load(reader);
     } catch (FileNotFoundException fnf) {
     } catch (FileNotFoundException fnf) {
-      logger.log(SEVERE, "Configuration file \"{0}\" not found.", configurationFilePath);
+      fileLoadErrorMessage = "Configuration file \"" + configurationFilePath + "\" not found.";
     } catch (IOException ioe) {
     } catch (IOException ioe) {
-      logger.log(
-          SEVERE,
-          "Configuration file \"{0}\" cannot be accessed or correctly parsed.",
-          configurationFilePath);
+      fileLoadErrorMessage =
+          "Configuration file \""
+              + configurationFilePath
+              + "\" cannot be accessed or correctly parsed.";
     }
     }
 
 
     return properties.entrySet().stream()
     return properties.entrySet().stream()
         .collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue().toString()));
         .collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue().toString()));
   }
   }
 
 
-  @Override
-  public int order() {
-    // make sure it runs after all the user-provided customizers
-    return Integer.MAX_VALUE;
+  static void logErrorIfAny() {
+    if (fileLoadErrorMessage != null) {
+      Logger.getLogger(ConfigurationPropertiesSupplier.class.getName())
+          .log(SEVERE, fileLoadErrorMessage);
+    }
   }
   }
+
+  private ConfigurationFile() {}
 }
 }

+ 25 - 0
javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigurationPropertiesSupplier.java

@@ -0,0 +1,25 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.tooling.config;
+
+import com.google.auto.service.AutoService;
+import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
+import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
+
+@AutoService(AutoConfigurationCustomizerProvider.class)
+public final class ConfigurationPropertiesSupplier implements AutoConfigurationCustomizerProvider {
+
+  @Override
+  public void customize(AutoConfigurationCustomizer autoConfiguration) {
+    autoConfiguration.addPropertiesSupplier(ConfigurationFile::getProperties);
+  }
+
+  @Override
+  public int order() {
+    // make sure it runs after all the user-provided customizers
+    return Integer.MAX_VALUE;
+  }
+}

+ 26 - 1
javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/EarlyInitAgentConfig.java

@@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.tooling.config;
 
 
 import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
 import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
 import java.util.Map;
 import java.util.Map;
+import javax.annotation.Nullable;
 
 
 /**
 /**
  * Agent config class that is only supposed to be used before the SDK (and {@link
  * Agent config class that is only supposed to be used before the SDK (and {@link
@@ -15,7 +16,7 @@ import java.util.Map;
 public final class EarlyInitAgentConfig {
 public final class EarlyInitAgentConfig {
 
 
   public static EarlyInitAgentConfig create() {
   public static EarlyInitAgentConfig create() {
-    return new EarlyInitAgentConfig(ConfigurationFileLoader.getConfigFileContents());
+    return new EarlyInitAgentConfig(ConfigurationFile.getProperties());
   }
   }
 
 
   private final Map<String, String> configFileContents;
   private final Map<String, String> configFileContents;
@@ -24,10 +25,34 @@ public final class EarlyInitAgentConfig {
     this.configFileContents = configFileContents;
     this.configFileContents = configFileContents;
   }
   }
 
 
+  @Nullable
+  public String getString(String propertyName) {
+    String value = ConfigPropertiesUtil.getString(propertyName);
+    if (value != null) {
+      return value;
+    }
+    return configFileContents.get(propertyName);
+  }
+
   public boolean getBoolean(String propertyName, boolean defaultValue) {
   public boolean getBoolean(String propertyName, boolean defaultValue) {
     String configFileValueStr = configFileContents.get(propertyName);
     String configFileValueStr = configFileContents.get(propertyName);
     boolean configFileValue =
     boolean configFileValue =
         configFileValueStr == null ? defaultValue : Boolean.parseBoolean(configFileValueStr);
         configFileValueStr == null ? defaultValue : Boolean.parseBoolean(configFileValueStr);
     return ConfigPropertiesUtil.getBoolean(propertyName, configFileValue);
     return ConfigPropertiesUtil.getBoolean(propertyName, configFileValue);
   }
   }
+
+  public int getInt(String propertyName, int defaultValue) {
+    try {
+      String configFileValueStr = configFileContents.get(propertyName);
+      int configFileValue =
+          configFileValueStr == null ? defaultValue : Integer.parseInt(configFileValueStr);
+      return ConfigPropertiesUtil.getInt(propertyName, configFileValue);
+    } catch (NumberFormatException ignored) {
+      return defaultValue;
+    }
+  }
+
+  public void logEarlyConfigErrorsIfAny() {
+    ConfigurationFile.logErrorIfAny();
+  }
 }
 }

+ 2 - 1
javaagent-tooling/src/test/groovy/io/opentelemetry/javaagent/test/HelperInjectionTest.groovy

@@ -9,6 +9,7 @@ package io.opentelemetry.javaagent.test
 import io.opentelemetry.javaagent.tooling.AgentInstaller
 import io.opentelemetry.javaagent.tooling.AgentInstaller
 import io.opentelemetry.javaagent.tooling.HelperInjector
 import io.opentelemetry.javaagent.tooling.HelperInjector
 import io.opentelemetry.javaagent.tooling.Utils
 import io.opentelemetry.javaagent.tooling.Utils
+import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig
 import net.bytebuddy.agent.ByteBuddyAgent
 import net.bytebuddy.agent.ByteBuddyAgent
 import net.bytebuddy.description.type.TypeDescription
 import net.bytebuddy.description.type.TypeDescription
 import net.bytebuddy.dynamic.ClassFileLocator
 import net.bytebuddy.dynamic.ClassFileLocator
@@ -61,7 +62,7 @@ class HelperInjectionTest extends Specification {
   def "helpers injected on bootstrap classloader"() {
   def "helpers injected on bootstrap classloader"() {
     setup:
     setup:
     ByteBuddyAgent.install()
     ByteBuddyAgent.install()
-    AgentInstaller.installBytebuddyAgent(ByteBuddyAgent.getInstrumentation(), this.class.classLoader)
+    AgentInstaller.installBytebuddyAgent(ByteBuddyAgent.getInstrumentation(), this.class.classLoader, EarlyInitAgentConfig.create())
     String helperClassName = HelperInjectionTest.getPackage().getName() + '.HelperClass'
     String helperClassName = HelperInjectionTest.getPackage().getName() + '.HelperClass'
     HelperInjector injector = new HelperInjector("test", [helperClassName], [], this.class.classLoader, ByteBuddyAgent.getInstrumentation())
     HelperInjector injector = new HelperInjector("test", [helperClassName], [], this.class.classLoader, ByteBuddyAgent.getInstrumentation())
     URLClassLoader bootstrapChild = new URLClassLoader(new URL[0], (ClassLoader) null)
     URLClassLoader bootstrapChild = new URLClassLoader(new URL[0], (ClassLoader) null)

+ 5 - 5
javaagent-tooling/src/test/groovy/io/opentelemetry/javaagent/tooling/config/ConfigurationFileTest.groovy

@@ -28,7 +28,7 @@ class ConfigurationFileTest extends Specification {
     environmentVariables.set("OTEL_JAVAAGENT_CONFIGURATION_FILE", path)
     environmentVariables.set("OTEL_JAVAAGENT_CONFIGURATION_FILE", path)
 
 
     when:
     when:
-    def properties = ConfigurationFileLoader.loadConfigFile()
+    def properties = ConfigurationFile.loadConfigFile()
 
 
     then:
     then:
     properties.get("property1") == "val-env"
     properties.get("property1") == "val-env"
@@ -40,7 +40,7 @@ class ConfigurationFileTest extends Specification {
     System.setProperty("otel.javaagent.configuration-file", path)
     System.setProperty("otel.javaagent.configuration-file", path)
 
 
     when:
     when:
-    def properties = ConfigurationFileLoader.loadConfigFile()
+    def properties = ConfigurationFile.loadConfigFile()
 
 
     then:
     then:
     properties.get("property1") == "val-sys"
     properties.get("property1") == "val-sys"
@@ -55,7 +55,7 @@ class ConfigurationFileTest extends Specification {
     System.setProperty("otel.javaagent.configuration-file", pathSys)
     System.setProperty("otel.javaagent.configuration-file", pathSys)
 
 
     when:
     when:
-    def properties = ConfigurationFileLoader.loadConfigFile()
+    def properties = ConfigurationFile.loadConfigFile()
 
 
     then:
     then:
     properties.get("property1") == "val-sys"
     properties.get("property1") == "val-sys"
@@ -67,7 +67,7 @@ class ConfigurationFileTest extends Specification {
     environmentVariables.set("OTEL_JAVAAGENT_CONFIGURATION_FILE", "somePath")
     environmentVariables.set("OTEL_JAVAAGENT_CONFIGURATION_FILE", "somePath")
 
 
     when:
     when:
-    def properties = ConfigurationFileLoader.loadConfigFile()
+    def properties = ConfigurationFile.loadConfigFile()
 
 
     then:
     then:
     properties.isEmpty()
     properties.isEmpty()
@@ -75,7 +75,7 @@ class ConfigurationFileTest extends Specification {
 
 
   def "should return empty properties if property is not set"() {
   def "should return empty properties if property is not set"() {
     when:
     when:
-    def properties = ConfigurationFileLoader.loadConfigFile()
+    def properties = ConfigurationFile.loadConfigFile()
 
 
     then:
     then:
     properties.isEmpty()
     properties.isEmpty()

+ 3 - 3
javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/config/ConfigurationFileLoaderTest.java → javaagent-tooling/src/test/java/io/opentelemetry/javaagent/tooling/config/ConfigurationPropertiesSupplierTest.java

@@ -26,8 +26,8 @@ import org.junit.jupiter.api.io.TempDir;
 import org.junitpioneer.jupiter.ClearSystemProperty;
 import org.junitpioneer.jupiter.ClearSystemProperty;
 import org.junitpioneer.jupiter.SetSystemProperty;
 import org.junitpioneer.jupiter.SetSystemProperty;
 
 
-@ClearSystemProperty(key = ConfigurationFileLoader.CONFIGURATION_FILE_PROPERTY)
-class ConfigurationFileLoaderTest {
+@ClearSystemProperty(key = ConfigurationFile.CONFIGURATION_FILE_PROPERTY)
+class ConfigurationPropertiesSupplierTest {
 
 
   @BeforeAll
   @BeforeAll
   @AfterAll
   @AfterAll
@@ -44,7 +44,7 @@ class ConfigurationFileLoaderTest {
     // given
     // given
     Path configFile = tempDir.resolve("test-config.properties");
     Path configFile = tempDir.resolve("test-config.properties");
     Files.write(configFile, singleton("custom.key = 42"));
     Files.write(configFile, singleton("custom.key = 42"));
-    System.setProperty(ConfigurationFileLoader.CONFIGURATION_FILE_PROPERTY, configFile.toString());
+    System.setProperty(ConfigurationFile.CONFIGURATION_FILE_PROPERTY, configFile.toString());
 
 
     // when
     // when
     AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
     AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =

+ 2 - 2
javaagent-tooling/src/test/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider

@@ -1,2 +1,2 @@
-io.opentelemetry.javaagent.tooling.config.ConfigurationFileLoader
-io.opentelemetry.javaagent.tooling.config.ConfigurationFileLoaderTest$UserCustomPropertiesSupplier
+io.opentelemetry.javaagent.tooling.config.ConfigurationPropertiesSupplier
+io.opentelemetry.javaagent.tooling.config.ConfigurationPropertiesSupplierTest$UserCustomPropertiesSupplier