diff --git a/instrumentation/jvm-metrics/src/main/java/com/splunk/opentelemetry/instrumentation/jvmmetrics/JvmMetricsInstaller.java b/instrumentation/jvm-metrics/src/main/java/com/splunk/opentelemetry/instrumentation/jvmmetrics/JvmMetricsInstaller.java index fed727687..c0e0980ec 100644 --- a/instrumentation/jvm-metrics/src/main/java/com/splunk/opentelemetry/instrumentation/jvmmetrics/JvmMetricsInstaller.java +++ b/instrumentation/jvm-metrics/src/main/java/com/splunk/opentelemetry/instrumentation/jvmmetrics/JvmMetricsInstaller.java @@ -22,8 +22,6 @@ import com.splunk.opentelemetry.instrumentation.jvmmetrics.otel.OtelAllocatedMemoryMetrics; import com.splunk.opentelemetry.instrumentation.jvmmetrics.otel.OtelGcMemoryMetrics; import com.splunk.opentelemetry.profiler.ProfilerConfiguration; -import com.splunk.opentelemetry.profiler.ProfilerDeclarativeConfiguration; -import com.splunk.opentelemetry.profiler.ProfilerEnvVarsConfiguration; import io.opentelemetry.javaagent.extension.AgentListener; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -33,7 +31,7 @@ public class JvmMetricsInstaller implements AgentListener { @Override public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { ConfigProperties config = getConfig(autoConfiguredOpenTelemetrySdk); - boolean metricsEnabled = isProfilerMemoryEnabled(config); + boolean metricsEnabled = isProfilerMemoryEnabled(); if (!config.getBoolean("otel.instrumentation.jvm-metrics-splunk.enabled", metricsEnabled)) { return; @@ -43,12 +41,7 @@ public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetr new OtelGcMemoryMetrics().install(); } - private boolean isProfilerMemoryEnabled(ConfigProperties config) { - ProfilerConfiguration profilerConfiguration = - ProfilerDeclarativeConfiguration.SUPPLIER.isConfigured() - ? ProfilerDeclarativeConfiguration.SUPPLIER.get() - : new ProfilerEnvVarsConfiguration(config); - - return profilerConfiguration.getMemoryEnabled(); + private boolean isProfilerMemoryEnabled() { + return ProfilerConfiguration.SUPPLIER.get().getMemoryEnabled(); } } diff --git a/instrumentation/jvm-metrics/src/test/java/com/splunk/opentelemetry/instrumentation/jvmmetrics/JvmMetricsInstallerTest.java b/instrumentation/jvm-metrics/src/test/java/com/splunk/opentelemetry/instrumentation/jvmmetrics/JvmMetricsInstallerTest.java index 7aa2c2e95..21b67dbb8 100644 --- a/instrumentation/jvm-metrics/src/test/java/com/splunk/opentelemetry/instrumentation/jvmmetrics/JvmMetricsInstallerTest.java +++ b/instrumentation/jvm-metrics/src/test/java/com/splunk/opentelemetry/instrumentation/jvmmetrics/JvmMetricsInstallerTest.java @@ -23,6 +23,8 @@ import static org.mockito.Mockito.verify; import com.splunk.opentelemetry.instrumentation.jvmmetrics.otel.OtelAllocatedMemoryMetrics; +import com.splunk.opentelemetry.profiler.ProfilerConfiguration; +import com.splunk.opentelemetry.profiler.ProfilerEnvVarsConfiguration; import com.splunk.opentelemetry.testing.declarativeconfig.DeclarativeConfigTestUtil; import io.opentelemetry.instrumentation.config.bridge.DeclarativeConfigPropertiesBridgeBuilder; import io.opentelemetry.sdk.autoconfigure.AutoConfigureUtil; @@ -30,12 +32,18 @@ import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.util.Map; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.mockito.MockedConstruction; import org.mockito.MockedStatic; class JvmMetricsInstallerTest { + @AfterEach + void tearDown() { + ProfilerConfiguration.SUPPLIER.reset(); + } + @Test void shouldInstallJvmMetrics_declarativeConfig() { // given @@ -53,6 +61,7 @@ void shouldInstallJvmMetrics_declarativeConfig() { new DeclarativeConfigPropertiesBridgeBuilder() .build( AutoConfigureUtil.getInstrumentationConfig(DeclarativeConfigTestUtil.parse(yaml))); + ProfilerConfiguration.SUPPLIER.configure(new ProfilerEnvVarsConfiguration(config)); try (MockedStatic autoConfigureUtil = mockStatic(AutoConfigureUtil.class); MockedConstruction allocatedMetrics = @@ -78,6 +87,7 @@ void shouldInstallJvmMetrics_envVarsConfig() { ConfigProperties config = DefaultConfigProperties.createFromMap( Map.of("otel.instrumentation.jvm-metrics-splunk.enabled", "true")); + ProfilerConfiguration.SUPPLIER.configure(new ProfilerEnvVarsConfiguration(config)); try (MockedStatic autoConfigureUtil = mockStatic(AutoConfigureUtil.class); MockedConstruction allocatedMetrics = diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/DeclarativeConfigurationInterceptor.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/DeclarativeConfigurationInterceptor.java index b3a46a6e1..ffb3e452b 100644 --- a/opamp/src/main/java/com/splunk/opentelemetry/opamp/DeclarativeConfigurationInterceptor.java +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/DeclarativeConfigurationInterceptor.java @@ -35,7 +35,7 @@ public static OpenTelemetryConfigurationModel getConfigurationModel() { } @VisibleForTesting - static void reset() { + public static void reset() { configurationModel = null; } diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/OpampActivator.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/OpampActivator.java index b7d4452ef..c1bdc7569 100644 --- a/opamp/src/main/java/com/splunk/opentelemetry/opamp/OpampActivator.java +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/OpampActivator.java @@ -17,11 +17,13 @@ package com.splunk.opentelemetry.opamp; import static io.opentelemetry.opamp.client.internal.request.service.HttpRequestService.DEFAULT_DELAY_BETWEEN_RETRIES; -import static io.opentelemetry.sdk.autoconfigure.AutoConfigureUtil.getConfig; import static io.opentelemetry.sdk.autoconfigure.AutoConfigureUtil.getResource; import static java.util.logging.Level.WARNING; import com.google.auto.service.AutoService; +import com.splunk.opentelemetry.opamp.effectiveconfig.EffectiveConfigReporter; +import com.splunk.opentelemetry.opamp.effectiveconfig.UpdatableEffectiveConfigState; +import com.splunk.opentelemetry.profiler.ProfilerConfiguration; import com.splunk.opentelemetry.profiler.ProfilingSupervisor; import io.opentelemetry.javaagent.extension.AgentListener; import io.opentelemetry.opamp.client.OpampClient; @@ -31,7 +33,6 @@ import io.opentelemetry.opamp.client.internal.request.service.HttpRequestService; import io.opentelemetry.opamp.client.internal.response.MessageData; import io.opentelemetry.opamp.client.internal.state.State; -import io.opentelemetry.sdk.autoconfigure.AutoConfigureUtil; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.resources.Resource; import java.io.IOException; @@ -54,19 +55,24 @@ public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetr return; } + ProfilerRemoteConfiguration profilerRemoteConfiguration = setupProfilerConfiguration(); Resource resource = getResource(autoConfiguredOpenTelemetrySdk); - EffectiveConfigFactory effectiveConfigFactory = - createEffectiveConfigFactory(autoConfiguredOpenTelemetrySdk); - State.EffectiveConfig effectiveConfig = buildEffectiveConfig(effectiveConfigFactory); + UpdatableEffectiveConfigState effectiveConfigState = new UpdatableEffectiveConfigState(); + EffectiveConfigReporter effectiveConfigReporter = + EffectiveConfigReporter.create(autoConfiguredOpenTelemetrySdk, effectiveConfigState); + effectiveConfigReporter.reportEffectiveConfigIfChanged(); ServerToAgentMessageHandler serverToAgentMessageHandler = - new ServerToAgentMessageHandler(ProfilingSupervisor.SUPPLIER.get()); + new ServerToAgentMessageHandler( + profilerRemoteConfiguration, + ProfilingSupervisor.SUPPLIER.get(), + effectiveConfigReporter); OpampClient client = startOpampClient( opampClientConfiguration, resource, - effectiveConfig, + effectiveConfigState, new OpampClient.Callbacks() { @Override public void onConnect(OpampClient opampClient) { @@ -103,18 +109,20 @@ public void onMessage(OpampClient opampClient, MessageData messageData) { })); } + private ProfilerRemoteConfiguration setupProfilerConfiguration() { + ProfilerConfiguration originalConfig = ProfilerConfiguration.SUPPLIER.get(); + ProfilerRemoteConfiguration remoteConfig = new ProfilerRemoteConfiguration(originalConfig); + + ProfilerConfiguration.SUPPLIER.configure(remoteConfig); + + return remoteConfig; + } + @Override public int order() { return Integer.MAX_VALUE; } - private EffectiveConfigFactory createEffectiveConfigFactory(AutoConfiguredOpenTelemetrySdk sdk) { - if (AutoConfigureUtil.isDeclarativeConfig(sdk)) { - return new DeclarativeEffectiveConfigFileFactory(); - } - return new EnvVarsEffectiveConfigFileFactory(getConfig(sdk)); - } - static OpampClient startOpampClient( OpampClientConfiguration opampClientConfiguration, Resource resource, @@ -146,15 +154,6 @@ static OpampClient startOpampClient( return builder.build(callbacks); } - static State.EffectiveConfig buildEffectiveConfig(EffectiveConfigFactory effectiveConfigFactory) { - return new State.EffectiveConfig() { - @Override - public opamp.proto.EffectiveConfig get() { - return new opamp.proto.EffectiveConfig(effectiveConfigFactory.createEffectiveConfigMap()); - } - }; - } - private static ComponentHealth createInitialHealthReport() { Instant now = Instant.now(); long nowNanos = now.getEpochSecond() * 1_000_000_000L + now.getNano(); diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/ProfilerRemoteConfiguration.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/ProfilerRemoteConfiguration.java new file mode 100644 index 000000000..7dfe8fce5 --- /dev/null +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/ProfilerRemoteConfiguration.java @@ -0,0 +1,135 @@ +/* + * Copyright Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.splunk.opentelemetry.opamp; + +import com.splunk.opentelemetry.profiler.ProfilerConfiguration; +import java.time.Duration; +import java.util.Objects; +import java.util.logging.Logger; +import javax.annotation.Nullable; + +public class ProfilerRemoteConfiguration implements ProfilerConfiguration { + private static final Logger logger = + Logger.getLogger(ProfilerRemoteConfiguration.class.getName()); + + private final ProfilerConfiguration delegate; + + private boolean enabled; + + ProfilerRemoteConfiguration(ProfilerConfiguration delegate) { + this.delegate = Objects.requireNonNull(delegate); + + enabled = delegate.isEnabled(); + } + + void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public void log() { + logger.info("-----------------------"); + logger.info("Remote profiler configuration overwrites:"); + log("Enabled", isEnabled()); + logger.info("Base profiler configuration:"); + delegate.log(); + } + + private static void log(String key, @Nullable Object value) { + logger.info(String.format("%30s : %s", key, value)); + } + + @Override + public String getIngestUrl() { + return delegate.getIngestUrl(); + } + + @Override + public String getOtlpProtocol() { + return delegate.getOtlpProtocol(); + } + + @Override + public boolean getMemoryEnabled() { + return delegate.getMemoryEnabled(); + } + + @Override + public boolean getMemoryEventRateLimitEnabled() { + return delegate.getMemoryEventRateLimitEnabled(); + } + + @Override + public String getMemoryEventRate() { + return delegate.getMemoryEventRate(); + } + + @Override + public boolean getUseAllocationSampleEvent() { + return delegate.getUseAllocationSampleEvent(); + } + + @Override + public Duration getCallStackInterval() { + return delegate.getCallStackInterval(); + } + + @Override + public boolean getIncludeAgentInternalStacks() { + return delegate.getIncludeAgentInternalStacks(); + } + + @Override + public boolean getIncludeJvmInternalStacks() { + return delegate.getIncludeJvmInternalStacks(); + } + + @Override + public boolean getTracingStacksOnly() { + return delegate.getTracingStacksOnly(); + } + + @Override + public int getStackDepth() { + return delegate.getStackDepth(); + } + + @Override + public boolean getKeepFiles() { + return delegate.getKeepFiles(); + } + + @Override + public String getProfilerDirectory() { + return delegate.getProfilerDirectory(); + } + + @Override + public Duration getRecordingDuration() { + return delegate.getRecordingDuration(); + } + + @Override + public Object getConfigProperties() { + return delegate.getConfigProperties(); + } +} diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/RemoteConfigProcessor.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/RemoteConfigProcessor.java index d25adfff0..11585577d 100644 --- a/opamp/src/main/java/com/splunk/opentelemetry/opamp/RemoteConfigProcessor.java +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/RemoteConfigProcessor.java @@ -19,6 +19,7 @@ import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import com.google.common.annotations.VisibleForTesting; +import com.splunk.opentelemetry.opamp.effectiveconfig.EffectiveConfigReporter; import com.splunk.opentelemetry.profiler.ProfilerDeclarativeConfiguration; import com.splunk.opentelemetry.profiler.ProfilingSupervisor; import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; @@ -28,6 +29,7 @@ import java.util.Map; import java.util.Objects; import java.util.logging.Logger; +import okio.ByteString; import opamp.proto.AgentConfigFile; import opamp.proto.AgentRemoteConfig; import opamp.proto.RemoteConfigStatus; @@ -39,10 +41,17 @@ public class RemoteConfigProcessor { private static final String REMOTE_CONFIG_FILE_NAME = "splunk.remote.config"; private static final String PROFILING_NODE_NAME = "profiling"; - public ProfilingSupervisor profilingSupervisor; + private final ProfilerRemoteConfiguration profilerRemoteConfiguration; + private final ProfilingSupervisor profilingSupervisor; + private final EffectiveConfigReporter effectiveConfigReporter; - public RemoteConfigProcessor(ProfilingSupervisor profilingSupervisor) { + public RemoteConfigProcessor( + ProfilerRemoteConfiguration profilerRemoteConfiguration, + ProfilingSupervisor profilingSupervisor, + EffectiveConfigReporter effectiveConfigReporter) { + this.profilerRemoteConfiguration = Objects.requireNonNull(profilerRemoteConfiguration); this.profilingSupervisor = Objects.requireNonNull(profilingSupervisor); + this.effectiveConfigReporter = Objects.requireNonNull(effectiveConfigReporter); } public void applyConfig(AgentRemoteConfig remoteConfig, OpampClient opampClient) { @@ -59,34 +68,47 @@ public void applyConfig(AgentRemoteConfig remoteConfig, OpampClient opampClient) return; } - DeclarativeConfigProperties remoteConfigProperties = toDeclarativeConfigProperties(configFile); - DeclarativeConfigProperties splunkDistributionConfigProperties = - remoteConfigProperties - .getStructured("distribution", empty()) - .getStructured("splunk", empty()); - - // Update profiler configuration only when profiling node exists - if (splunkDistributionConfigProperties.getPropertyKeys().contains(PROFILING_NODE_NAME)) { - DeclarativeConfigProperties profilingConfigProperties = - splunkDistributionConfigProperties.getStructured(PROFILING_NODE_NAME, empty()); - ProfilerDeclarativeConfiguration profilingConfig = - new ProfilerDeclarativeConfiguration(profilingConfigProperties); - // TODO: should be merged with current profiling config. Probably we will need profiler - // configuration refactoring and some listeners implemented for profiler configuration - // changes. For POC use this temporary solution - if (profilingConfig.isEnabled()) { - profilingSupervisor.requestStartProfiling(); - } else { - profilingSupervisor.requestStopProfiling(); + try { + DeclarativeConfigProperties remoteConfigProperties = + toDeclarativeConfigProperties(configFile); + DeclarativeConfigProperties distributionRemoteConfigProperties = + remoteConfigProperties + .getStructured("distribution", empty()) + .getStructured("splunk", empty()); + + // Update profiler configuration only when profiling node exists + if (distributionRemoteConfigProperties.getPropertyKeys().contains(PROFILING_NODE_NAME)) { + ProfilerDeclarativeConfiguration receivedProfilerConfig = + new ProfilerDeclarativeConfiguration( + distributionRemoteConfigProperties.getStructured(PROFILING_NODE_NAME, empty())); + + profilerRemoteConfiguration.setEnabled(receivedProfilerConfig.isEnabled()); + + if (profilerRemoteConfiguration.isEnabled()) { + profilingSupervisor.requestStartProfiling(); + } else { + profilingSupervisor.requestStopProfiling(); + } } + + // Confirm to the OpAMP Server that remote config has been applied. + reportRemoteConfigStatus( + remoteConfig.config_hash, + RemoteConfigStatuses.RemoteConfigStatuses_APPLIED, + "", + opampClient); + + } catch (Exception e) { + reportRemoteConfigStatus( + remoteConfig.config_hash, + RemoteConfigStatuses.RemoteConfigStatuses_FAILED, + "Exception occurred: " + e.getMessage(), + opampClient); + throw e; } - // Confirm to the OpAMP Server that remote config has been applied. - opampClient.setRemoteConfigStatus( - new RemoteConfigStatus.Builder() - .last_remote_config_hash(remoteConfig.config_hash) - .status(RemoteConfigStatuses.RemoteConfigStatuses_APPLIED) - .build()); + // TODO: Maybe should be postponed after profiler is enabled/disabled? + effectiveConfigReporter.reportEffectiveConfigIfChanged(); } @VisibleForTesting @@ -94,4 +116,17 @@ static DeclarativeConfigProperties toDeclarativeConfigProperties(AgentConfigFile return DeclarativeConfiguration.toConfigProperties( new ByteArrayInputStream(configFile.body.toByteArray())); } + + private void reportRemoteConfigStatus( + ByteString configHash, + RemoteConfigStatuses status, + String errorMessage, + OpampClient opampClient) { + opampClient.setRemoteConfigStatus( + new RemoteConfigStatus.Builder() + .last_remote_config_hash(configHash) + .error_message(errorMessage) + .status(status) + .build()); + } } diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/ServerToAgentMessageHandler.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/ServerToAgentMessageHandler.java index f0ab02d36..dd3899d71 100644 --- a/opamp/src/main/java/com/splunk/opentelemetry/opamp/ServerToAgentMessageHandler.java +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/ServerToAgentMessageHandler.java @@ -17,6 +17,7 @@ package com.splunk.opentelemetry.opamp; import com.google.common.annotations.VisibleForTesting; +import com.splunk.opentelemetry.opamp.effectiveconfig.EffectiveConfigReporter; import com.splunk.opentelemetry.profiler.ProfilingSupervisor; import io.opentelemetry.opamp.client.OpampClient; import io.opentelemetry.opamp.client.internal.response.MessageData; @@ -24,8 +25,13 @@ public class ServerToAgentMessageHandler { private final RemoteConfigProcessor remoteConfigProcessor; - public ServerToAgentMessageHandler(ProfilingSupervisor profilingSupervisor) { - this(new RemoteConfigProcessor(profilingSupervisor)); + public ServerToAgentMessageHandler( + ProfilerRemoteConfiguration profilerRemoteConfiguration, + ProfilingSupervisor profilingSupervisor, + EffectiveConfigReporter effectiveConfigReporter) { + this( + new RemoteConfigProcessor( + profilerRemoteConfiguration, profilingSupervisor, effectiveConfigReporter)); } @VisibleForTesting diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/DeclarativeEffectiveConfigFileFactory.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/DeclarativeEffectiveConfigFileFactory.java similarity index 98% rename from opamp/src/main/java/com/splunk/opentelemetry/opamp/DeclarativeEffectiveConfigFileFactory.java rename to opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/DeclarativeEffectiveConfigFileFactory.java index a3410f895..160fbb32e 100644 --- a/opamp/src/main/java/com/splunk/opentelemetry/opamp/DeclarativeEffectiveConfigFileFactory.java +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/DeclarativeEffectiveConfigFileFactory.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.splunk.opentelemetry.opamp; +package com.splunk.opentelemetry.opamp.effectiveconfig; import com.google.common.annotations.VisibleForTesting; +import com.splunk.opentelemetry.opamp.DeclarativeConfigurationInterceptor; import com.splunk.opentelemetry.profiler.ProfilerConfiguration; import com.splunk.opentelemetry.profiler.ProfilerDeclarativeConfiguration; import com.splunk.opentelemetry.profiler.snapshot.SnapshotProfilingConfiguration; diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/EffectiveConfigBuilder.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EffectiveConfigBuilder.java similarity index 95% rename from opamp/src/main/java/com/splunk/opentelemetry/opamp/EffectiveConfigBuilder.java rename to opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EffectiveConfigBuilder.java index 08ab87bbb..8bfa48a54 100644 --- a/opamp/src/main/java/com/splunk/opentelemetry/opamp/EffectiveConfigBuilder.java +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EffectiveConfigBuilder.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.opentelemetry.opamp; +package com.splunk.opentelemetry.opamp.effectiveconfig; import java.time.Duration; diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/EffectiveConfigFactory.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EffectiveConfigFactory.java similarity index 97% rename from opamp/src/main/java/com/splunk/opentelemetry/opamp/EffectiveConfigFactory.java rename to opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EffectiveConfigFactory.java index 13c454783..a68a7466f 100644 --- a/opamp/src/main/java/com/splunk/opentelemetry/opamp/EffectiveConfigFactory.java +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EffectiveConfigFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.opentelemetry.opamp; +package com.splunk.opentelemetry.opamp.effectiveconfig; import static java.nio.charset.StandardCharsets.UTF_8; diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EffectiveConfigReporter.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EffectiveConfigReporter.java new file mode 100644 index 000000000..587021bd9 --- /dev/null +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EffectiveConfigReporter.java @@ -0,0 +1,75 @@ +/* + * Copyright Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.splunk.opentelemetry.opamp.effectiveconfig; + +import static io.opentelemetry.sdk.autoconfigure.AutoConfigureUtil.getConfig; +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.annotations.VisibleForTesting; +import io.opentelemetry.sdk.autoconfigure.AutoConfigureUtil; +import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; +import java.util.HashMap; +import java.util.Map; +import okio.ByteString; +import opamp.proto.AgentConfigFile; +import opamp.proto.AgentConfigMap; + +public class EffectiveConfigReporter { + private final UpdatableEffectiveConfigState effectiveConfigState; + private final EffectiveConfigFactory effectiveConfigFactory; + private String lastReportedConfigContent; + + @VisibleForTesting + EffectiveConfigReporter( + EffectiveConfigFactory effectiveConfigFactory, + UpdatableEffectiveConfigState effectiveConfigState) { + this.effectiveConfigFactory = effectiveConfigFactory; + this.effectiveConfigState = effectiveConfigState; + } + + public static EffectiveConfigReporter create( + AutoConfiguredOpenTelemetrySdk sdk, UpdatableEffectiveConfigState effectiveConfigState) { + return new EffectiveConfigReporter(createEffectiveConfigFactory(sdk), effectiveConfigState); + } + + public boolean reportEffectiveConfigIfChanged() { + // Detect if effectiveConfig changed and needs to be reported + String configContent = effectiveConfigFactory.createEffectiveConfigContent(); + if (configContent.equals(lastReportedConfigContent)) { + return false; + } + + Map configMap = new HashMap<>(); + AgentConfigFile configFile = + new AgentConfigFile( + new ByteString(configContent.getBytes(UTF_8)), effectiveConfigFactory.getContentType()); + configMap.put(effectiveConfigFactory.getFileName(), configFile); + + effectiveConfigState.set(new AgentConfigMap(configMap)); + lastReportedConfigContent = configContent; + + return true; + } + + private static EffectiveConfigFactory createEffectiveConfigFactory( + AutoConfiguredOpenTelemetrySdk sdk) { + if (AutoConfigureUtil.isDeclarativeConfig(sdk)) { + return new DeclarativeEffectiveConfigFileFactory(); + } + return new EnvVarsEffectiveConfigFileFactory(getConfig(sdk)); + } +} diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/EnvVarsEffectiveConfigFileFactory.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EnvVarsEffectiveConfigFileFactory.java similarity index 95% rename from opamp/src/main/java/com/splunk/opentelemetry/opamp/EnvVarsEffectiveConfigFileFactory.java rename to opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EnvVarsEffectiveConfigFileFactory.java index 62186f822..687fda85a 100644 --- a/opamp/src/main/java/com/splunk/opentelemetry/opamp/EnvVarsEffectiveConfigFileFactory.java +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/EnvVarsEffectiveConfigFileFactory.java @@ -14,10 +14,9 @@ * limitations under the License. */ -package com.splunk.opentelemetry.opamp; +package com.splunk.opentelemetry.opamp.effectiveconfig; import com.splunk.opentelemetry.profiler.ProfilerConfiguration; -import com.splunk.opentelemetry.profiler.ProfilerEnvVarsConfiguration; import com.splunk.opentelemetry.profiler.snapshot.SnapshotProfilingConfiguration; import com.splunk.opentelemetry.profiler.snapshot.SnapshotProfilingEnvVarsConfiguration; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; @@ -49,7 +48,7 @@ public String createEffectiveConfigContent() { } private void addSplunkEnvVars(EffectiveConfigBuilder builder) { - ProfilerConfiguration profilerConfiguration = new ProfilerEnvVarsConfiguration(config); + ProfilerConfiguration profilerConfiguration = ProfilerConfiguration.SUPPLIER.get(); SnapshotProfilingConfiguration snapshotConfiguration = new SnapshotProfilingEnvVarsConfiguration(config); diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/UpdatableEffectiveConfigState.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/UpdatableEffectiveConfigState.java new file mode 100644 index 000000000..242109ab5 --- /dev/null +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/UpdatableEffectiveConfigState.java @@ -0,0 +1,34 @@ +/* + * Copyright Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.splunk.opentelemetry.opamp.effectiveconfig; + +import io.opentelemetry.opamp.client.internal.state.State; +import opamp.proto.AgentConfigMap; + +public class UpdatableEffectiveConfigState extends State.EffectiveConfig { + private AgentConfigMap agentConfigMap; + + public void set(AgentConfigMap configMap) { + agentConfigMap = configMap; + notifyUpdate(); + } + + @Override + public opamp.proto.EffectiveConfig get() { + return new opamp.proto.EffectiveConfig(agentConfigMap); + } +} diff --git a/opamp/src/main/java/com/splunk/opentelemetry/opamp/YamlNodeBuilder.java b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/YamlNodeBuilder.java similarity index 99% rename from opamp/src/main/java/com/splunk/opentelemetry/opamp/YamlNodeBuilder.java rename to opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/YamlNodeBuilder.java index 1bd57418d..e38bfe946 100644 --- a/opamp/src/main/java/com/splunk/opentelemetry/opamp/YamlNodeBuilder.java +++ b/opamp/src/main/java/com/splunk/opentelemetry/opamp/effectiveconfig/YamlNodeBuilder.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.opentelemetry.opamp; +package com.splunk.opentelemetry.opamp.effectiveconfig; import java.util.LinkedHashMap; import java.util.Map; diff --git a/opamp/src/test/java/com/splunk/opentelemetry/opamp/OpampActivatorTest.java b/opamp/src/test/java/com/splunk/opentelemetry/opamp/OpampActivatorTest.java index ca85b97da..689590a19 100644 --- a/opamp/src/test/java/com/splunk/opentelemetry/opamp/OpampActivatorTest.java +++ b/opamp/src/test/java/com/splunk/opentelemetry/opamp/OpampActivatorTest.java @@ -16,7 +16,6 @@ package com.splunk.opentelemetry.opamp; -import static com.splunk.opentelemetry.opamp.OpampActivator.buildEffectiveConfig; import static io.opentelemetry.api.common.AttributeKey.booleanKey; import static io.opentelemetry.api.common.AttributeKey.doubleKey; import static io.opentelemetry.api.common.AttributeKey.longKey; @@ -29,16 +28,15 @@ import static io.opentelemetry.semconv.incubating.OsIncubatingAttributes.OS_TYPE; import static io.opentelemetry.semconv.incubating.OsIncubatingAttributes.OS_VERSION; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import com.splunk.opentelemetry.opamp.effectiveconfig.UpdatableEffectiveConfigState; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.Value; import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension; import io.opentelemetry.opamp.client.OpampClient; import io.opentelemetry.opamp.client.internal.response.MessageData; -import io.opentelemetry.opamp.client.internal.state.State; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.testing.internal.armeria.common.HttpResponse; import io.opentelemetry.testing.internal.armeria.common.HttpStatus; @@ -133,9 +131,7 @@ void testOpamp() throws Exception { .build(); server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.X_PROTOBUF, response.encode())); - ConfigProperties config = DefaultConfigProperties.createFromMap(Map.of()); - State.EffectiveConfig effectiveConfig = - buildEffectiveConfig(new EnvVarsEffectiveConfigFileFactory(config)); + UpdatableEffectiveConfigState effectiveConfig = mock(); CompletableFuture result = new CompletableFuture<>(); OpampClientConfiguration opampClientConfiguration = diff --git a/opamp/src/test/java/com/splunk/opentelemetry/opamp/RemoteConfigProcessorTest.java b/opamp/src/test/java/com/splunk/opentelemetry/opamp/RemoteConfigProcessorTest.java index 5f134fd19..951c1a7bc 100644 --- a/opamp/src/test/java/com/splunk/opentelemetry/opamp/RemoteConfigProcessorTest.java +++ b/opamp/src/test/java/com/splunk/opentelemetry/opamp/RemoteConfigProcessorTest.java @@ -17,10 +17,13 @@ package com.splunk.opentelemetry.opamp; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import com.splunk.opentelemetry.opamp.effectiveconfig.EffectiveConfigReporter; +import com.splunk.opentelemetry.profiler.ProfilerConfiguration; +import com.splunk.opentelemetry.profiler.ProfilingSupervisor; import io.opentelemetry.opamp.client.OpampClient; import java.util.Map; import okio.ByteString; @@ -29,15 +32,32 @@ import opamp.proto.AgentRemoteConfig; import opamp.proto.RemoteConfigStatus; import opamp.proto.RemoteConfigStatuses; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +@ExtendWith(MockitoExtension.class) class RemoteConfigProcessorTest { - private final RemoteConfigProcessor handler = new RemoteConfigProcessor(mock()); - private final OpampClient opampClient = mock(OpampClient.class); + @Mock ProfilerConfiguration profilerConfiguration; + @Mock ProfilingSupervisor profilingSupervisor; + @Mock EffectiveConfigReporter effectiveConfigReporter; + @Mock OpampClient opampClient; + private ProfilerRemoteConfiguration profilerRemoteConfiguration; + private RemoteConfigProcessor handler; + + @BeforeEach + void setUp() { + profilerRemoteConfiguration = new ProfilerRemoteConfiguration(profilerConfiguration); + handler = + new RemoteConfigProcessor( + profilerRemoteConfiguration, profilingSupervisor, effectiveConfigReporter); + } @Test - void shouldMarkRemoteConfigAsApplied() { + void shouldMarkRemoteConfigAsAppliedWhenProfilingConfigIsNotProvided() { // given String remoteConfigYaml = "test-config:"; ByteString configHash = ByteString.encodeUtf8("test-config-hash"); @@ -54,12 +74,67 @@ void shouldMarkRemoteConfigAsApplied() { handler.applyConfig(remoteConfig, opampClient); // then - ArgumentCaptor statusCaptor = - ArgumentCaptor.forClass(RemoteConfigStatus.class); - verify(opampClient).setRemoteConfigStatus(statusCaptor.capture()); - RemoteConfigStatus status = statusCaptor.getValue(); + RemoteConfigStatus status = getReportedRemoteConfigStatus(); + assertThat(status.last_remote_config_hash).isEqualTo(configHash); + assertThat(status.status).isEqualTo(RemoteConfigStatuses.RemoteConfigStatuses_APPLIED); + assertThat(status.error_message).isEmpty(); + assertThat(profilerRemoteConfiguration.isEnabled()).isFalse(); + verify(effectiveConfigReporter).reportEffectiveConfigIfChanged(); + verifyNoInteractions(profilingSupervisor); + } + + @Test + void shouldStartProfilingWhenRemoteConfigEnablesProfiler() { + // given + String remoteConfigYaml = + """ + distribution: + splunk: + profiling: + always_on: + cpu_profiler: + """; + ByteString configHash = ByteString.encodeUtf8("test-config-hash"); + AgentRemoteConfig remoteConfig = createRemoteConfig(configHash, remoteConfigYaml); + + // when + handler.applyConfig(remoteConfig, opampClient); + + // then + RemoteConfigStatus status = getReportedRemoteConfigStatus(); + assertThat(status.last_remote_config_hash).isEqualTo(configHash); + assertThat(status.status).isEqualTo(RemoteConfigStatuses.RemoteConfigStatuses_APPLIED); + assertThat(status.error_message).isEmpty(); + assertThat(profilerRemoteConfiguration.isEnabled()).isTrue(); + verify(profilingSupervisor).requestStartProfiling(); + verify(profilingSupervisor, never()).requestStopProfiling(); + verify(effectiveConfigReporter).reportEffectiveConfigIfChanged(); + } + + @Test + void shouldStopProfilingWhenRemoteConfigDisablesProfiler() { + // given + String remoteConfigYaml = + """ + distribution: + splunk: + profiling: + """; + ByteString configHash = ByteString.encodeUtf8("test-config-hash"); + AgentRemoteConfig remoteConfig = createRemoteConfig(configHash, remoteConfigYaml); + + // when + handler.applyConfig(remoteConfig, opampClient); + + // then + RemoteConfigStatus status = getReportedRemoteConfigStatus(); assertThat(status.last_remote_config_hash).isEqualTo(configHash); assertThat(status.status).isEqualTo(RemoteConfigStatuses.RemoteConfigStatuses_APPLIED); + assertThat(status.error_message).isEmpty(); + assertThat(profilerRemoteConfiguration.isEnabled()).isFalse(); + verify(profilingSupervisor).requestStopProfiling(); + verify(profilingSupervisor, never()).requestStartProfiling(); + verify(effectiveConfigReporter).reportEffectiveConfigIfChanged(); } @Test @@ -76,7 +151,24 @@ void shouldIgnoreRemoteConfigWithoutExpectedConfigFile() { handler.applyConfig(remoteConfig, opampClient); // then - verify(opampClient, never()).setRemoteConfigStatus(org.mockito.ArgumentMatchers.any()); + assertThat(profilerRemoteConfiguration.isEnabled()).isFalse(); + verifyNoInteractions(opampClient, profilingSupervisor); + verify(effectiveConfigReporter, never()).reportEffectiveConfigIfChanged(); + } + + private RemoteConfigStatus getReportedRemoteConfigStatus() { + ArgumentCaptor statusCaptor = + ArgumentCaptor.forClass(RemoteConfigStatus.class); + verify(opampClient).setRemoteConfigStatus(statusCaptor.capture()); + return statusCaptor.getValue(); + } + + private static AgentRemoteConfig createRemoteConfig(ByteString configHash, String config) { + return createRemoteConfig( + configHash, + Map.of( + "splunk.remote.config", + new AgentConfigFile.Builder().body(ByteString.encodeUtf8(config)).build())); } private static AgentRemoteConfig createRemoteConfig( diff --git a/opamp/src/test/java/com/splunk/opentelemetry/opamp/DeclarativeEffectiveConfigFileFactoryTest.java b/opamp/src/test/java/com/splunk/opentelemetry/opamp/effectiveconfig/DeclarativeEffectiveConfigFileFactoryTest.java similarity index 99% rename from opamp/src/test/java/com/splunk/opentelemetry/opamp/DeclarativeEffectiveConfigFileFactoryTest.java rename to opamp/src/test/java/com/splunk/opentelemetry/opamp/effectiveconfig/DeclarativeEffectiveConfigFileFactoryTest.java index 0bbf444ff..3e92535e4 100644 --- a/opamp/src/test/java/com/splunk/opentelemetry/opamp/DeclarativeEffectiveConfigFileFactoryTest.java +++ b/opamp/src/test/java/com/splunk/opentelemetry/opamp/effectiveconfig/DeclarativeEffectiveConfigFileFactoryTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.opentelemetry.opamp; +package com.splunk.opentelemetry.opamp.effectiveconfig; import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; import static io.opentelemetry.sdk.autoconfigure.AutoConfigureUtil.getDistributionConfig; @@ -22,6 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.when; +import com.splunk.opentelemetry.opamp.DeclarativeConfigurationInterceptor; import com.splunk.opentelemetry.profiler.ProfilerConfiguration; import com.splunk.opentelemetry.profiler.ProfilerDeclarativeConfiguration; import com.splunk.opentelemetry.profiler.snapshot.SnapshotProfilingConfiguration; diff --git a/opamp/src/test/java/com/splunk/opentelemetry/opamp/EnvVarsEffectiveConfigFileFactoryTest.java b/opamp/src/test/java/com/splunk/opentelemetry/opamp/effectiveconfig/EnvVarsEffectiveConfigFileFactoryTest.java similarity index 94% rename from opamp/src/test/java/com/splunk/opentelemetry/opamp/EnvVarsEffectiveConfigFileFactoryTest.java rename to opamp/src/test/java/com/splunk/opentelemetry/opamp/effectiveconfig/EnvVarsEffectiveConfigFileFactoryTest.java index f48165485..0940e0a3b 100644 --- a/opamp/src/test/java/com/splunk/opentelemetry/opamp/EnvVarsEffectiveConfigFileFactoryTest.java +++ b/opamp/src/test/java/com/splunk/opentelemetry/opamp/effectiveconfig/EnvVarsEffectiveConfigFileFactoryTest.java @@ -14,19 +14,27 @@ * limitations under the License. */ -package com.splunk.opentelemetry.opamp; +package com.splunk.opentelemetry.opamp.effectiveconfig; import static org.assertj.core.api.Assertions.assertThat; +import com.splunk.opentelemetry.profiler.ProfilerConfiguration; +import com.splunk.opentelemetry.profiler.ProfilerEnvVarsConfiguration; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import java.io.IOException; import java.io.StringReader; import java.util.Map; import java.util.Properties; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; class EnvVarsEffectiveConfigFileFactoryTest { + @AfterEach + void tearDown() { + ProfilerConfiguration.SUPPLIER.reset(); + } + @Test void createFile_reportsCorrectContentType() { DefaultConfigProperties config = DefaultConfigProperties.createFromMap(Map.of()); @@ -154,6 +162,7 @@ void buildFileContent_usesSignalSpecificProtocolWhenResolvingEndpoints() throws private static Properties createFileContent(Map configMap) throws IOException { DefaultConfigProperties config = DefaultConfigProperties.createFromMap(configMap); + ProfilerConfiguration.SUPPLIER.configure(new ProfilerEnvVarsConfiguration(config)); String fileContent = new EnvVarsEffectiveConfigFileFactory(config).createEffectiveConfigContent(); diff --git a/opamp/src/test/java/com/splunk/opentelemetry/opamp/YamlNodeBuilderTest.java b/opamp/src/test/java/com/splunk/opentelemetry/opamp/effectiveconfig/YamlNodeBuilderTest.java similarity index 98% rename from opamp/src/test/java/com/splunk/opentelemetry/opamp/YamlNodeBuilderTest.java rename to opamp/src/test/java/com/splunk/opentelemetry/opamp/effectiveconfig/YamlNodeBuilderTest.java index fd9d7e751..319902ea2 100644 --- a/opamp/src/test/java/com/splunk/opentelemetry/opamp/YamlNodeBuilderTest.java +++ b/opamp/src/test/java/com/splunk/opentelemetry/opamp/effectiveconfig/YamlNodeBuilderTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.splunk.opentelemetry.opamp; +package com.splunk.opentelemetry.opamp.effectiveconfig; import static org.assertj.core.api.Assertions.assertThat; diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/JfrAgentListener.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/JfrAgentListener.java index fc978ef53..cf8ea81e7 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/JfrAgentListener.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/JfrAgentListener.java @@ -19,9 +19,7 @@ import com.google.auto.service.AutoService; import com.google.common.annotations.VisibleForTesting; import io.opentelemetry.javaagent.extension.AgentListener; -import io.opentelemetry.sdk.autoconfigure.AutoConfigureUtil; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import java.util.logging.Logger; @AutoService(AgentListener.class) @@ -40,12 +38,14 @@ public JfrAgentListener() { @Override public void afterAgent(AutoConfiguredOpenTelemetrySdk sdk) { - ProfilingSupervisor.setupJfrContextStorage(); + if (jfr.isAvailable()) { + ProfilingSupervisor.setupJfrContextStorage(); + } - ProfilerConfiguration config = getProfilerConfiguration(sdk); // Always start the supervisor, so it can start profiling later elsewhere. - ProfilingSupervisor supervisor = makeProfilingSupervisor(sdk, config); + ProfilingSupervisor supervisor = makeProfilingSupervisor(sdk); + ProfilerConfiguration config = ProfilerConfiguration.SUPPLIER.get(); if (notClearForTakeoff(config)) { return; } @@ -60,19 +60,8 @@ public int order() { } // Exists for testing - ProfilingSupervisor makeProfilingSupervisor( - AutoConfiguredOpenTelemetrySdk sdk, ProfilerConfiguration config) { - return ProfilingSupervisor.createAndStart(sdk, config); - } - - private static ProfilerConfiguration getProfilerConfiguration( - AutoConfiguredOpenTelemetrySdk sdk) { - if (ProfilerDeclarativeConfiguration.SUPPLIER.isConfigured()) { - return ProfilerDeclarativeConfiguration.SUPPLIER.get(); - } else { - ConfigProperties configProperties = AutoConfigureUtil.getConfig(sdk); - return new ProfilerEnvVarsConfiguration(configProperties); - } + ProfilingSupervisor makeProfilingSupervisor(AutoConfiguredOpenTelemetrySdk sdk) { + return ProfilingSupervisor.createAndStart(sdk); } private boolean notClearForTakeoff(ProfilerConfiguration config) { diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/LogExporterBuilder.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/LogExporterBuilder.java index ea7c781c6..ec4e5f364 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/LogExporterBuilder.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/LogExporterBuilder.java @@ -44,7 +44,8 @@ class LogExporterBuilder { static final String EXTRA_CONTENT_TYPE = "Extra-Content-Type"; static final String STACKTRACES_HEADER_VALUE = "otel-profiling-stacktraces"; - static LogRecordExporter fromConfig(DeclarativeConfigProperties exporterConfigProperties) { + static LogRecordExporter fromDeclarativeConfig( + DeclarativeConfigProperties exporterConfigProperties) { if (exporterConfigProperties != null) { Set propertyKeys = exporterConfigProperties.getPropertyKeys(); @@ -68,11 +69,8 @@ static LogRecordExporter fromConfig(DeclarativeConfigProperties exporterConfigPr throw new ConfigurationException("Profiler exporter configuration is invalid"); } - static LogRecordExporter fromConfig(ConfigProperties config) { - return fromConfig(new ProfilerEnvVarsConfiguration(config)); - } - - static LogRecordExporter fromConfig(ProfilerEnvVarsConfiguration config) { + static LogRecordExporter fromEnvironmentConfig() { + ProfilerConfiguration config = ProfilerConfiguration.SUPPLIER.get(); String protocol = config.getOtlpProtocol(); if ("http/protobuf".equals(protocol)) { return buildHttpExporter(config, OtlpHttpLogRecordExporter::builder); @@ -84,7 +82,7 @@ static LogRecordExporter fromConfig(ProfilerEnvVarsConfiguration config) { @VisibleForTesting static LogRecordExporter buildGrpcExporter( - ProfilerEnvVarsConfiguration config, Supplier makeBuilder) { + ProfilerConfiguration config, Supplier makeBuilder) { OtlpGrpcLogRecordExporterBuilder builder = makeBuilder.get(); String ingestUrl = config.getIngestUrl(); builder.setEndpoint(ingestUrl); @@ -94,13 +92,13 @@ static LogRecordExporter buildGrpcExporter( @VisibleForTesting static LogRecordExporter buildHttpExporter( - ProfilerEnvVarsConfiguration config, Supplier makeBuilder) { + ProfilerConfiguration config, Supplier makeBuilder) { OtlpHttpLogRecordExporterBuilder builder = makeBuilder.get(); String ingestUrl = config.getIngestUrl(); OtlpConfigUtil.configureOtlpExporterBuilder( DATA_TYPE_LOGS, - config.getConfigProperties(), + (ConfigProperties) config.getConfigProperties(), builder::setComponentLoader, builder::setEndpoint, builder::addHeader, diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/OtelLoggerFactory.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/OtelLoggerFactory.java index f164fc902..2bddc274a 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/OtelLoggerFactory.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/OtelLoggerFactory.java @@ -26,26 +26,27 @@ import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor; import io.opentelemetry.sdk.resources.Resource; import java.util.function.Function; +import java.util.function.Supplier; public class OtelLoggerFactory { - private final Function logRecordExporter; + private final Supplier logRecordExporter; private final Function declarativeLogRecordExporter; public OtelLoggerFactory() { - this(LogExporterBuilder::fromConfig, LogExporterBuilder::fromConfig); + this(LogExporterBuilder::fromEnvironmentConfig, LogExporterBuilder::fromDeclarativeConfig); } @VisibleForTesting public OtelLoggerFactory( - Function logRecordExporter, + Supplier logRecordExporter, Function declarativeLogRecordExporter) { this.logRecordExporter = logRecordExporter; this.declarativeLogRecordExporter = declarativeLogRecordExporter; } public Logger build(ConfigProperties properties, Resource resource) { - LogRecordExporter exporter = createLogRecordExporter(properties); + LogRecordExporter exporter = createLogRecordExporter(); LogRecordProcessor processor = SimpleLogRecordProcessor.create(exporter); return buildOtelLogger(processor, resource); } @@ -56,8 +57,8 @@ public Logger build(DeclarativeConfigProperties properties, Resource resource) { return buildOtelLogger(processor, resource); } - private LogRecordExporter createLogRecordExporter(ConfigProperties properties) { - return logRecordExporter.apply(properties); + private LogRecordExporter createLogRecordExporter() { + return logRecordExporter.get(); } private LogRecordExporter createLogRecordExporter(DeclarativeConfigProperties properties) { diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/PeriodicRecordingFlusherBuilder.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/PeriodicRecordingFlusherBuilder.java index 00efd8a62..54297452a 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/PeriodicRecordingFlusherBuilder.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/PeriodicRecordingFlusherBuilder.java @@ -25,7 +25,6 @@ import com.splunk.opentelemetry.profiler.exporter.CpuEventExporter; import com.splunk.opentelemetry.profiler.exporter.PprofCpuEventExporter; import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.logs.LogRecordProcessor; import io.opentelemetry.sdk.logs.SdkLoggerProvider; import io.opentelemetry.sdk.logs.export.LogRecordExporter; @@ -162,13 +161,9 @@ private static LogRecordExporter createLogRecordExporter(Object configProperties if (configProperties instanceof DeclarativeConfigProperties) { DeclarativeConfigProperties exporterConfig = ((DeclarativeConfigProperties) configProperties).getStructured("exporter", empty()); - return LogExporterBuilder.fromConfig(exporterConfig); + return LogExporterBuilder.fromDeclarativeConfig(exporterConfig); } - if (configProperties instanceof ConfigProperties) { - return LogExporterBuilder.fromConfig((ConfigProperties) configProperties); - } - throw new IllegalArgumentException( - "Unsupported config properties type: " + configProperties.getClass().getName()); + return LogExporterBuilder.fromEnvironmentConfig(); } private boolean checkOutputDir(Path outputDir) { diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerConfiguration.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerConfiguration.java index 6e2aaf69f..3f7c600ce 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerConfiguration.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerConfiguration.java @@ -16,9 +16,13 @@ package com.splunk.opentelemetry.profiler; +import com.splunk.opentelemetry.profiler.util.OptionalConfigurableSupplier; import java.time.Duration; public interface ProfilerConfiguration { + OptionalConfigurableSupplier SUPPLIER = + new OptionalConfigurableSupplier<>(); + boolean HAS_OBJECT_ALLOCATION_SAMPLE_EVENT = getJavaVersion() >= 16; boolean isEnabled(); diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerDeclarativeConfigurationInitializer.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerConfigurationInitializer.java similarity index 61% rename from profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerDeclarativeConfigurationInitializer.java rename to profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerConfigurationInitializer.java index 72fba6659..e0041a0d8 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerDeclarativeConfigurationInitializer.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerConfigurationInitializer.java @@ -23,16 +23,25 @@ import io.opentelemetry.sdk.autoconfigure.AutoConfigureUtil; import io.opentelemetry.sdk.autoconfigure.declarativeconfig.DeclarativeConfigurationCustomizer; import io.opentelemetry.sdk.autoconfigure.declarativeconfig.DeclarativeConfigurationCustomizerProvider; +import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; +import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; +import java.util.Collections; /** * Purpose of this class is to configure the supplier of ProfilerDeclarativeConfiguration. * ProfilerDeclarativeConfiguration class object can then be used in code executed after SDK is * created, such as AgentListeners. */ -@AutoService(DeclarativeConfigurationCustomizerProvider.class) -public class ProfilerDeclarativeConfigurationInitializer - implements DeclarativeConfigurationCustomizerProvider { +@AutoService({ + DeclarativeConfigurationCustomizerProvider.class, + AutoConfigurationCustomizerProvider.class +}) +public class ProfilerConfigurationInitializer + implements DeclarativeConfigurationCustomizerProvider, AutoConfigurationCustomizerProvider { + + @Override public void customize(DeclarativeConfigurationCustomizer configurationCustomizer) { + // Initialize profiler configuration from declarative config configurationCustomizer.addModelCustomizer( (model) -> { DeclarativeConfigProperties distributionConfig = @@ -40,10 +49,27 @@ public void customize(DeclarativeConfigurationCustomizer configurationCustomizer DeclarativeConfigProperties profilingConfig = distributionConfig.getStructured("profiling", empty()); - ProfilerDeclarativeConfiguration.SUPPLIER.configure( - new ProfilerDeclarativeConfiguration(profilingConfig)); + ProfilerDeclarativeConfiguration profilerConfiguration = + new ProfilerDeclarativeConfiguration(profilingConfig); + ProfilerConfiguration.SUPPLIER.configure(profilerConfiguration); return model; }); } + + @Override + public void customize(AutoConfigurationCustomizer autoConfiguration) { + // Initialize profiler configuration from environment config + autoConfiguration.addPropertiesCustomizer( + configProperties -> { + ProfilerConfiguration.SUPPLIER.configure( + new ProfilerEnvVarsConfiguration(configProperties)); + return Collections.emptyMap(); + }); + } + + @Override + public int order() { + return Integer.MAX_VALUE; + } } diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerDeclarativeConfiguration.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerDeclarativeConfiguration.java index 1da14893f..029f8d61c 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerDeclarativeConfiguration.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilerDeclarativeConfiguration.java @@ -18,16 +18,12 @@ import static io.opentelemetry.api.incubator.config.DeclarativeConfigProperties.empty; -import com.splunk.opentelemetry.profiler.util.OptionalConfigurableSupplier; import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties; import java.time.Duration; import java.util.logging.Logger; import javax.annotation.Nullable; public class ProfilerDeclarativeConfiguration implements ProfilerConfiguration { - public static final OptionalConfigurableSupplier SUPPLIER = - new OptionalConfigurableSupplier<>(); - private static final Logger logger = Logger.getLogger(ProfilerDeclarativeConfiguration.class.getName()); diff --git a/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilingSupervisor.java b/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilingSupervisor.java index c1575c40c..2b9269ffd 100644 --- a/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilingSupervisor.java +++ b/profiler/src/main/java/com/splunk/opentelemetry/profiler/ProfilingSupervisor.java @@ -41,7 +41,7 @@ public class ProfilingSupervisor { private static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(ProfilingSupervisor.class.getName()); - private final ProfilerConfiguration config; + private final OptionalConfigurableSupplier configSupplier; private final JFR jfr; private final AutoConfiguredOpenTelemetrySdk sdk; private final BlockingQueue commandQueue; @@ -53,24 +53,24 @@ public class ProfilingSupervisor { @VisibleForTesting ProfilingSupervisor( - ProfilerConfiguration config, + OptionalConfigurableSupplier configSupplier, JFR jfr, AutoConfiguredOpenTelemetrySdk sdk, BlockingQueue commandQueue) { - this.config = config; + this.configSupplier = configSupplier; this.jfr = jfr; this.sdk = sdk; this.commandQueue = commandQueue; } - static ProfilingSupervisor createAndStart( - AutoConfiguredOpenTelemetrySdk sdk, ProfilerConfiguration config) { + static ProfilingSupervisor createAndStart(AutoConfiguredOpenTelemetrySdk sdk) { if (SUPPLIER.isConfigured()) { throw new IllegalStateException("Already started"); } ExecutorService executor = HelpfulExecutors.newSingleThreadExecutor("JFR Profiler"); BlockingQueue queue = new LinkedBlockingQueue<>(); - ProfilingSupervisor supervisor = new ProfilingSupervisor(config, JFR.getInstance(), sdk, queue); + ProfilingSupervisor supervisor = + new ProfilingSupervisor(ProfilerConfiguration.SUPPLIER, JFR.getInstance(), sdk, queue); SUPPLIER.configure(supervisor); supervisor.start(executor); @@ -137,10 +137,10 @@ private void tryStart() { "JDK Flight Recorder (JFR) is not available in this JVM. Profiling will not start."); return; } - config.log(); - logger.info("Profiler is active."); + configSupplier.get().log(); setJfrContextStorageEnabled(true); activateJfrRecording(getResource(sdk)); + logger.info("Profiler is active."); } private void tryStop() { @@ -150,6 +150,7 @@ private void tryStop() { } setJfrContextStorageEnabled(false); deactivateJfrRecording(); + logger.info("Profiler is deactivated."); } private boolean isJfrRecordingActive() { @@ -173,7 +174,7 @@ private void deactivateJfrRecording() { // Exists for testing PeriodicRecordingFlusherBuilder makeRecordingFlusherBuilder(Resource resource) { - return PeriodicRecordingFlusher.builder(config, resource); + return PeriodicRecordingFlusher.builder(configSupplier.get(), resource); } static void setupJfrContextStorage() { diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/JfrAgentListenerTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/JfrAgentListenerTest.java index 9f87f91d0..3d7d28fe2 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/JfrAgentListenerTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/JfrAgentListenerTest.java @@ -43,7 +43,7 @@ class JfrAgentListenerTest { @AfterEach void resetDeclarativeConfigSuppliers() { - ProfilerDeclarativeConfiguration.SUPPLIER.reset(); + ProfilerConfiguration.SUPPLIER.reset(); SnapshotProfilingDeclarativeConfiguration.SUPPLIER.reset(); } @@ -68,8 +68,7 @@ void shouldActivateJfrRecording(@TempDir Path tempDir) throws IOException { JfrAgentListener listener = new JfrAgentListener(jfr) { @Override - ProfilingSupervisor makeProfilingSupervisor( - AutoConfiguredOpenTelemetrySdk sdk, ProfilerConfiguration config) { + ProfilingSupervisor makeProfilingSupervisor(AutoConfiguredOpenTelemetrySdk sdk) { return supervisor; } }; @@ -102,8 +101,7 @@ void shouldNotActivateJfrRecording_JfrNotAvailable(@TempDir Path tempDir) throws JfrAgentListener listener = new JfrAgentListener(jfr) { @Override - ProfilingSupervisor makeProfilingSupervisor( - AutoConfiguredOpenTelemetrySdk sdk, ProfilerConfiguration config) { + ProfilingSupervisor makeProfilingSupervisor(AutoConfiguredOpenTelemetrySdk sdk) { return supervisor; } }; @@ -130,8 +128,7 @@ void shouldNotActivateJfrRecording_profilerDisabled(String yaml, @TempDir Path t JfrAgentListener listener = new JfrAgentListener(jfr) { @Override - ProfilingSupervisor makeProfilingSupervisor( - AutoConfiguredOpenTelemetrySdk sdk, ProfilerConfiguration config) { + ProfilingSupervisor makeProfilingSupervisor(AutoConfiguredOpenTelemetrySdk sdk) { return supervisor; } }; diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/LogExporterBuilderTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/LogExporterBuilderTest.java index 973be8856..3b0f5ca0b 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/LogExporterBuilderTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/LogExporterBuilderTest.java @@ -173,7 +173,7 @@ void shouldCreateHttpExporter() { DeclarativeConfigProperties exporterConfig = getExporterConfig(model); // when - LogRecordExporter exporter = LogExporterBuilder.fromConfig(exporterConfig); + LogRecordExporter exporter = LogExporterBuilder.fromDeclarativeConfig(exporterConfig); // then assertThat(exporter).isNotNull(); @@ -197,7 +197,7 @@ void shouldCreateGrpcExporter() { DeclarativeConfigProperties exporterConfig = getExporterConfig(model); // when - LogRecordExporter exporter = LogExporterBuilder.fromConfig(exporterConfig); + LogRecordExporter exporter = LogExporterBuilder.fromDeclarativeConfig(exporterConfig); // then assertThat(exporter).isNotNull(); @@ -220,7 +220,7 @@ void shouldCreateHttpExporter_defaultEndpoint() { DeclarativeConfigProperties exporterConfig = getExporterConfig(model); // when - LogRecordExporter exporter = LogExporterBuilder.fromConfig(exporterConfig); + LogRecordExporter exporter = LogExporterBuilder.fromDeclarativeConfig(exporterConfig); // then assertThat(exporter).isNotNull(); @@ -243,7 +243,7 @@ void shouldCreateGrpcExporter_defaultEndpoint() { DeclarativeConfigProperties exporterConfig = getExporterConfig(model); // when - LogRecordExporter exporter = LogExporterBuilder.fromConfig(exporterConfig); + LogRecordExporter exporter = LogExporterBuilder.fromDeclarativeConfig(exporterConfig); // then assertThat(exporter).isNotNull(); @@ -266,7 +266,7 @@ void shouldThrowExceptionForInvalidProtocol() { DeclarativeConfigProperties exporterConfig = getExporterConfig(model); // when, then - assertThatThrownBy(() -> LogExporterBuilder.fromConfig(exporterConfig)) + assertThatThrownBy(() -> LogExporterBuilder.fromDeclarativeConfig(exporterConfig)) .isInstanceOf(ConfigurationException.class); } diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/OtelLoggerFactoryTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/OtelLoggerFactoryTest.java index 67ceaa988..a75309a9c 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/OtelLoggerFactoryTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/OtelLoggerFactoryTest.java @@ -33,7 +33,7 @@ class OtelLoggerFactoryTest { private final InMemoryLogRecordExporter exporter = InMemoryLogRecordExporter.create(); private final OtelLoggerFactory factory = - new OtelLoggerFactory(properties -> exporter, declarativeConfigProperties -> exporter); + new OtelLoggerFactory(() -> exporter, declarativeConfigProperties -> exporter); @Test void configureLoggerWithProfilingInstrumentationScopeName() { diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/PeriodicRecordingFlusherBuilderTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/PeriodicRecordingFlusherBuilderTest.java index d309ac1da..b491b4c42 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/PeriodicRecordingFlusherBuilderTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/PeriodicRecordingFlusherBuilderTest.java @@ -17,7 +17,6 @@ package com.splunk.opentelemetry.profiler; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockConstruction; import static org.mockito.Mockito.verify; @@ -27,6 +26,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.mockito.MockedConstruction; @@ -35,12 +35,18 @@ class PeriodicRecordingFlusherBuilderTest { @TempDir Path tempDir; + @AfterEach + void tearDown() { + ProfilerConfiguration.SUPPLIER.reset(); + } + @Test void buildConfiguresJfrAndWiresRecorderIntoSequencer() { JFR jfr = mock(JFR.class); TestProfilingConfig config = config(tempDir); config.stackDepth = 73; config.recordingDuration = Duration.ofMillis(100); + ProfilerConfiguration.SUPPLIER.configure(config); try (MockedConstruction recorderConstruction = mockConstruction(JfrRecorder.class)) { @@ -66,6 +72,7 @@ void buildCreatesMissingOutputDirectoryWhenKeepingFiles() { JFR jfr = mock(JFR.class); TestProfilingConfig config = config(outputDir); config.keepFiles = true; + ProfilerConfiguration.SUPPLIER.configure(config); try (MockedConstruction recorderConstruction = mockConstruction(JfrRecorder.class)) { @@ -85,6 +92,7 @@ void buildContinuesWhenKeepFilesPathIsNotADirectory() throws Exception { JFR jfr = mock(JFR.class); TestProfilingConfig config = config(outputFile); config.keepFiles = true; + ProfilerConfiguration.SUPPLIER.configure(config); try (MockedConstruction recorderConstruction = mockConstruction(JfrRecorder.class)) { @@ -96,18 +104,6 @@ void buildContinuesWhenKeepFilesPathIsNotADirectory() throws Exception { } } - @Test - void buildRejectsUnsupportedConfigProperties() { - JFR jfr = mock(JFR.class); - TestProfilingConfig config = config(tempDir); - config.configProperties = new Object(); - - assertThatThrownBy( - () -> PeriodicRecordingFlusher.builder(config, Resource.empty()).jfr(jfr).build()) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageStartingWith("Unsupported config properties type:"); - } - private TestProfilingConfig config(Path outputDir) { TestProfilingConfig config = new TestProfilingConfig(); config.profilerDirectory = outputDir.toString(); diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/ProfilingSupervisorTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/ProfilingSupervisorTest.java index 3d2e133e5..8a338180c 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/ProfilingSupervisorTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/ProfilingSupervisorTest.java @@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.splunk.opentelemetry.profiler.util.OptionalConfigurableSupplier; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import io.opentelemetry.sdk.resources.Resource; import java.nio.file.Path; @@ -156,7 +157,7 @@ private static class TestProfilingSupervisor extends ProfilingSupervisor { JFR jfr, AutoConfiguredOpenTelemetrySdk sdk, PeriodicRecordingFlusherBuilder builder) { - super(config, jfr, sdk, new LinkedBlockingQueue<>()); + super(configSupplier(config), jfr, sdk, new LinkedBlockingQueue<>()); this.builder = builder; } @@ -164,6 +165,14 @@ private static class TestProfilingSupervisor extends ProfilingSupervisor { PeriodicRecordingFlusherBuilder makeRecordingFlusherBuilder(Resource resource) { return builder; } + + private static OptionalConfigurableSupplier configSupplier( + ProfilerConfiguration config) { + OptionalConfigurableSupplier supplier = + new OptionalConfigurableSupplier<>(); + supplier.configure(config); + return supplier; + } } private static class TestPeriodicRecordingFlusherBuilder extends PeriodicRecordingFlusherBuilder { diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/ConcurrentServiceEntrySamplingTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/ConcurrentServiceEntrySamplingTest.java index 327e9bc68..70f6a8934 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/ConcurrentServiceEntrySamplingTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/ConcurrentServiceEntrySamplingTest.java @@ -66,7 +66,7 @@ private StackTraceSampler newSampler(StagingArea staging) { .with( new StackTraceExporterActivator( new OtelLoggerFactory( - properties -> logExporter, declarativeConfigProperties -> logExporter))) + () -> logExporter, declarativeConfigProperties -> logExporter))) .build(); @RegisterExtension diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/GracefulShutdownTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/GracefulShutdownTest.java index c54ad34dc..5b80afa7a 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/GracefulShutdownTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/GracefulShutdownTest.java @@ -43,7 +43,7 @@ class GracefulShutdownTest { .with( new StackTraceExporterActivator( new OtelLoggerFactory( - properties -> logExporter, declarativeConfigProperties -> logExporter))) + () -> logExporter, declarativeConfigProperties -> logExporter))) .build(); @Test diff --git a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingLogExportingTest.java b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingLogExportingTest.java index ee1b18bab..db71b2917 100644 --- a/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingLogExportingTest.java +++ b/profiler/src/test/java/com/splunk/opentelemetry/profiler/snapshot/SnapshotProfilingLogExportingTest.java @@ -63,7 +63,7 @@ class SnapshotProfilingLogExportingTest { .with( new StackTraceExporterActivator( new OtelLoggerFactory( - properties -> logExporter, declarativeConfigProperties -> logExporter))) + () -> logExporter, declarativeConfigProperties -> logExporter))) .build(); @AfterEach