Skip to content

Commit 3e64f73

Browse files
committed
decide if declarative config file is loaded later - because distros might use a customizer to set the config file property
1 parent b31bb6d commit 3e64f73

12 files changed

+158
-260
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package io.opentelemetry.javaagent.tooling;
77

8+
import static io.opentelemetry.javaagent.tooling.OpenTelemetryInstaller.installOpenTelemetrySdk;
89
import static io.opentelemetry.javaagent.tooling.SafeServiceLoader.load;
910
import static io.opentelemetry.javaagent.tooling.SafeServiceLoader.loadOrdered;
1011
import static io.opentelemetry.javaagent.tooling.Utils.getResourceName;
@@ -162,8 +163,7 @@ private static void installBytebuddyAgent(
162163
installEarlyInstrumentation(agentBuilder, inst);
163164

164165
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
165-
earlyConfig.installOpenTelemetrySdk(extensionClassLoader);
166-
EarlyInitAgentConfig.setForceFlush(autoConfiguredSdk.getOpenTelemetrySdk());
166+
installOpenTelemetrySdk(extensionClassLoader, earlyConfig);
167167

168168
ConfigProperties sdkConfig = AutoConfigureUtil.getConfig(autoConfiguredSdk);
169169
AgentInstrumentationConfig.internalInitializeConfig(

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentStarterImpl.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import io.opentelemetry.javaagent.bootstrap.AgentStarter;
1212
import io.opentelemetry.javaagent.extension.instrumentation.internal.AsmApi;
1313
import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig;
14-
import io.opentelemetry.javaagent.tooling.config.ErrorBuffer;
1514
import java.io.File;
1615
import java.lang.instrument.ClassFileTransformer;
1716
import java.lang.instrument.Instrumentation;
@@ -97,7 +96,7 @@ public void start() {
9796
Throwable startupError = null;
9897
try {
9998
loggingCustomizer.init(earlyConfig);
100-
ErrorBuffer.logErrorIfAny();
99+
earlyConfig.logEarlyConfigErrorsIfAny();
101100

102101
AgentInstaller.installBytebuddyAgent(instrumentation, extensionClassLoader, earlyConfig);
103102
WeakConcurrentMapCleaner.start();

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/AgentTracerProviderConfigurer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
package io.opentelemetry.javaagent.tooling;
77

8-
import static io.opentelemetry.javaagent.tooling.config.LegacyConfigFileEarlyInitAgentConfig.JAVAAGENT_ENABLED_CONFIG;
8+
import static io.opentelemetry.javaagent.tooling.AgentInstaller.JAVAAGENT_ENABLED_CONFIG;
99
import static java.util.Collections.emptyList;
1010

1111
import com.google.auto.service.AutoService;
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.tooling;
7+
8+
import io.opentelemetry.api.incubator.config.ConfigProvider;
9+
import io.opentelemetry.javaagent.bootstrap.OpenTelemetrySdkAccess;
10+
import io.opentelemetry.javaagent.extension.DeclarativeConfigPropertiesBridge;
11+
import io.opentelemetry.javaagent.tooling.config.EarlyInitAgentConfig;
12+
import io.opentelemetry.sdk.OpenTelemetrySdk;
13+
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
14+
import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess;
15+
import io.opentelemetry.sdk.autoconfigure.internal.AutoConfigureUtil;
16+
import io.opentelemetry.sdk.common.CompletableResultCode;
17+
import io.opentelemetry.sdk.resources.Resource;
18+
import java.util.Arrays;
19+
import java.util.HashMap;
20+
import java.util.Map;
21+
22+
public final class OpenTelemetryInstaller {
23+
24+
/**
25+
* Install the {@link OpenTelemetrySdk} using autoconfigure, and return the {@link
26+
* AutoConfiguredOpenTelemetrySdk}.
27+
*
28+
* @return the {@link AutoConfiguredOpenTelemetrySdk}
29+
*/
30+
public static AutoConfiguredOpenTelemetrySdk installOpenTelemetrySdk(
31+
ClassLoader extensionClassLoader, EarlyInitAgentConfig earlyConfig) {
32+
33+
AutoConfiguredOpenTelemetrySdk autoConfiguredSdk =
34+
AutoConfiguredOpenTelemetrySdk.builder()
35+
.setResultAsGlobal()
36+
.setServiceClassLoader(extensionClassLoader)
37+
.build();
38+
ConfigProvider configProvider = AutoConfigureUtil.getConfigProvider(autoConfiguredSdk);
39+
OpenTelemetrySdk sdk = autoConfiguredSdk.getOpenTelemetrySdk();
40+
41+
setForceFlush(sdk);
42+
43+
if (configProvider != null) {
44+
return SdkAutoconfigureAccess.create(
45+
sdk,
46+
Resource.getDefault(),
47+
new DeclarativeConfigPropertiesBridge(
48+
configProvider, getEarlyInitProperties(earlyConfig)),
49+
configProvider);
50+
}
51+
52+
return autoConfiguredSdk;
53+
}
54+
55+
// these properties are used to initialize the SDK before the configuration file is loaded
56+
// for consistency, we pass them to the bridge, so that they can be read later with the same
57+
// value from the {@link DeclarativeConfigPropertiesBridge}
58+
private static Map<String, Object> getEarlyInitProperties(EarlyInitAgentConfig config) {
59+
Map<String, Object> earlyInitProperties = new HashMap<>();
60+
earlyInitProperties.put(
61+
"otel.javaagent.debug", config.getBoolean("otel.javaagent.debug", false));
62+
earlyInitProperties.put("otel.javaagent.logging", config.getString("otel.javaagent.logging"));
63+
return earlyInitProperties;
64+
}
65+
66+
private static void setForceFlush(OpenTelemetrySdk sdk) {
67+
OpenTelemetrySdkAccess.internalSetForceFlush(
68+
(timeout, unit) -> {
69+
CompletableResultCode traceResult = sdk.getSdkTracerProvider().forceFlush();
70+
CompletableResultCode metricsResult = sdk.getSdkMeterProvider().forceFlush();
71+
CompletableResultCode logsResult = sdk.getSdkLoggerProvider().forceFlush();
72+
CompletableResultCode.ofAll(Arrays.asList(traceResult, metricsResult, logsResult))
73+
.join(timeout, unit);
74+
});
75+
}
76+
77+
private OpenTelemetryInstaller() {}
78+
}

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/ConfigurationFile.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
package io.opentelemetry.javaagent.tooling.config;
77

8-
import static io.opentelemetry.javaagent.tooling.config.ErrorBuffer.addErrorMessage;
98
import static java.util.Collections.emptyMap;
9+
import static java.util.logging.Level.SEVERE;
1010

1111
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
1212
import java.io.File;
@@ -17,14 +17,21 @@
1717
import java.nio.charset.StandardCharsets;
1818
import java.util.Map;
1919
import java.util.Properties;
20+
import java.util.logging.Logger;
2021
import java.util.stream.Collectors;
22+
import javax.annotation.Nullable;
2123

2224
final class ConfigurationFile {
2325

2426
static final String CONFIGURATION_FILE_PROPERTY = "otel.javaagent.configuration-file";
2527

2628
private static Map<String, String> configFileContents;
2729

30+
// this class is used early, and must not use logging in most of its methods
31+
// in case any file loading/parsing error occurs, we save the error message and log it later, when
32+
// the logging subsystem is initialized
33+
@Nullable private static String fileLoadErrorMessage;
34+
2835
static Map<String, String> getProperties() {
2936
if (configFileContents == null) {
3037
configFileContents = loadConfigFile();
@@ -52,7 +59,7 @@ static Map<String, String> loadConfigFile() {
5259
// Configuration properties file is optional
5360
File configurationFile = new File(configurationFilePath);
5461
if (!configurationFile.exists()) {
55-
addErrorMessage("Configuration file \"" + configurationFilePath + "\" not found.");
62+
fileLoadErrorMessage = "Configuration file \"" + configurationFilePath + "\" not found.";
5663
return emptyMap();
5764
}
5865

@@ -61,17 +68,24 @@ static Map<String, String> loadConfigFile() {
6168
new InputStreamReader(new FileInputStream(configurationFile), StandardCharsets.UTF_8)) {
6269
properties.load(reader);
6370
} catch (FileNotFoundException fnf) {
64-
addErrorMessage("Configuration file \"" + configurationFilePath + "\" not found.");
71+
fileLoadErrorMessage = "Configuration file \"" + configurationFilePath + "\" not found.";
6572
} catch (IOException ioe) {
66-
addErrorMessage(
73+
fileLoadErrorMessage =
6774
"Configuration file \""
6875
+ configurationFilePath
69-
+ "\" cannot be accessed or correctly parsed.");
76+
+ "\" cannot be accessed or correctly parsed.";
7077
}
7178

7279
return properties.entrySet().stream()
7380
.collect(Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue().toString()));
7481
}
7582

83+
static void logErrorIfAny() {
84+
if (fileLoadErrorMessage != null) {
85+
Logger.getLogger(ConfigurationPropertiesSupplier.class.getName())
86+
.log(SEVERE, fileLoadErrorMessage);
87+
}
88+
}
89+
7690
private ConfigurationFile() {}
7791
}

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/config/DeclarativeConfigEarlyInitAgentConfig.java

Lines changed: 0 additions & 96 deletions
This file was deleted.

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

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,51 +5,54 @@
55

66
package io.opentelemetry.javaagent.tooling.config;
77

8-
import static java.util.Arrays.asList;
9-
10-
import io.opentelemetry.javaagent.bootstrap.OpenTelemetrySdkAccess;
11-
import io.opentelemetry.sdk.OpenTelemetrySdk;
12-
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
13-
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
14-
import io.opentelemetry.sdk.common.CompletableResultCode;
15-
import java.util.Collections;
8+
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
9+
import java.util.Map;
1610
import javax.annotation.Nullable;
1711

18-
public interface EarlyInitAgentConfig {
12+
/**
13+
* Agent config class that is only supposed to be used before the SDK (and {@link
14+
* io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties}) is initialized.
15+
*/
16+
public final class EarlyInitAgentConfig {
1917

20-
@Nullable
21-
String getString(String propertyName);
18+
public static EarlyInitAgentConfig create() {
19+
return new EarlyInitAgentConfig(ConfigurationFile.getProperties());
20+
}
2221

23-
boolean getBoolean(String propertyName, boolean defaultValue);
22+
private final Map<String, String> configFileContents;
2423

25-
int getInt(String propertyName, int defaultValue);
24+
private EarlyInitAgentConfig(Map<String, String> configFileContents) {
25+
this.configFileContents = configFileContents;
26+
}
2627

27-
/**
28-
* Install the {@link OpenTelemetrySdk} using autoconfigure, and return the {@link
29-
* AutoConfiguredOpenTelemetrySdk}.
30-
*
31-
* @return the {@link AutoConfiguredOpenTelemetrySdk}
32-
*/
33-
AutoConfiguredOpenTelemetrySdk installOpenTelemetrySdk(ClassLoader extensionClassLoader);
28+
@Nullable
29+
public String getString(String propertyName) {
30+
String value = ConfigPropertiesUtil.getString(propertyName);
31+
if (value != null) {
32+
return value;
33+
}
34+
return configFileContents.get(propertyName);
35+
}
3436

35-
static EarlyInitAgentConfig create() {
36-
String configurationFile =
37-
DefaultConfigProperties.create(Collections.emptyMap())
38-
.getString("otel.experimental.config.file");
37+
public boolean getBoolean(String propertyName, boolean defaultValue) {
38+
String configFileValueStr = configFileContents.get(propertyName);
39+
boolean configFileValue =
40+
configFileValueStr == null ? defaultValue : Boolean.parseBoolean(configFileValueStr);
41+
return ConfigPropertiesUtil.getBoolean(propertyName, configFileValue);
42+
}
3943

40-
return configurationFile != null
41-
? DeclarativeConfigEarlyInitAgentConfig.create(configurationFile)
42-
: LegacyConfigFileEarlyInitAgentConfig.create();
44+
public int getInt(String propertyName, int defaultValue) {
45+
try {
46+
String configFileValueStr = configFileContents.get(propertyName);
47+
int configFileValue =
48+
configFileValueStr == null ? defaultValue : Integer.parseInt(configFileValueStr);
49+
return ConfigPropertiesUtil.getInt(propertyName, configFileValue);
50+
} catch (NumberFormatException ignored) {
51+
return defaultValue;
52+
}
4353
}
4454

45-
static void setForceFlush(OpenTelemetrySdk sdk) {
46-
OpenTelemetrySdkAccess.internalSetForceFlush(
47-
(timeout, unit) -> {
48-
CompletableResultCode traceResult = sdk.getSdkTracerProvider().forceFlush();
49-
CompletableResultCode metricsResult = sdk.getSdkMeterProvider().forceFlush();
50-
CompletableResultCode logsResult = sdk.getSdkLoggerProvider().forceFlush();
51-
CompletableResultCode.ofAll(asList(traceResult, metricsResult, logsResult))
52-
.join(timeout, unit);
53-
});
55+
public void logEarlyConfigErrorsIfAny() {
56+
ConfigurationFile.logErrorIfAny();
5457
}
5558
}

0 commit comments

Comments
 (0)