From f07cf9a615128b0dcb62698bda4c67cb5b3c442b Mon Sep 17 00:00:00 2001 From: cleverchuk Date: Mon, 27 Apr 2026 13:13:26 -0400 Subject: [PATCH] allow user provided sampler, add cel-sampler for users to configure w/o extension and removed JDK version check in lambda. --- agent-lambda/build.gradle.kts | 4 ++ agent/build.gradle.kts | 5 ++ .../extensions/SolarwindsAgentListener.java | 17 +----- ...toConfigurationCustomizerProviderImpl.java | 5 -- .../SolarwindsAgentListenerTest.java | 53 ++++++++++--------- ...nfigurationCustomizerProviderImplTest.java | 8 --- dependencyManagement/build.gradle.kts | 1 + ...ltAutoConfigurationCustomizerProvider.java | 18 +------ .../extensions/LambdaAgentListener.java | 17 +----- .../extensions/LambdaAgentListenerTest.java | 35 ++++++------ libs/shared/build.gradle.kts | 5 ++ .../SharedConfigCustomizerProvider.java | 11 ++-- .../SharedConfigCustomizerProviderTest.java | 35 ++++++++++++ testing/agent-for-testing/build.gradle.kts | 4 ++ 14 files changed, 107 insertions(+), 111 deletions(-) diff --git a/agent-lambda/build.gradle.kts b/agent-lambda/build.gradle.kts index be202804..0e6800b6 100644 --- a/agent-lambda/build.gradle.kts +++ b/agent-lambda/build.gradle.kts @@ -82,7 +82,11 @@ tasks { filesMatching("META-INF/services/**") { duplicatesStrategy = DuplicatesStrategy.INCLUDE } + exclude("**/module-info.class") + filesMatching(listOf("META-INF/LICENSE", "META-INF/LICENSE.txt", "META-INF/NOTICE", "META-INF/NOTICE.txt")) { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } // exclude known bootstrap dependencies - they can't appear in the inst/ directory dependencies { diff --git a/agent/build.gradle.kts b/agent/build.gradle.kts index 418d2b1f..1e88df74 100644 --- a/agent/build.gradle.kts +++ b/agent/build.gradle.kts @@ -85,6 +85,11 @@ tasks { filesMatching("META-INF/services/**") { duplicatesStrategy = DuplicatesStrategy.INCLUDE } + + filesMatching(listOf("META-INF/LICENSE", "META-INF/LICENSE.txt", "META-INF/NOTICE", "META-INF/NOTICE.txt")) { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } + exclude("**/module-info.class") // exclude known bootstrap dependencies - they can't appear in the inst/ directory diff --git a/custom/src/main/java/com/solarwinds/opentelemetry/extensions/SolarwindsAgentListener.java b/custom/src/main/java/com/solarwinds/opentelemetry/extensions/SolarwindsAgentListener.java index 0314bbc8..2a6f91a8 100644 --- a/custom/src/main/java/com/solarwinds/opentelemetry/extensions/SolarwindsAgentListener.java +++ b/custom/src/main/java/com/solarwinds/opentelemetry/extensions/SolarwindsAgentListener.java @@ -17,7 +17,6 @@ package com.solarwinds.opentelemetry.extensions; import static com.solarwinds.opentelemetry.extensions.config.provider.AutoConfigurationCustomizerProviderImpl.isAgentEnabled; -import static com.solarwinds.opentelemetry.extensions.config.provider.AutoConfigurationCustomizerProviderImpl.setAgentEnabled; import com.google.auto.service.AutoService; import com.solarwinds.joboe.config.ConfigManager; @@ -39,7 +38,6 @@ import com.solarwinds.opentelemetry.extensions.config.HttpSettingsReaderDelegate; import io.opentelemetry.javaagent.extension.AgentListener; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.sdk.trace.samplers.Sampler; import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -56,7 +54,7 @@ public class SolarwindsAgentListener implements AgentListener { @Override public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { - if (isAgentEnabled() && isUsingSolarwindsSampler(autoConfiguredOpenTelemetrySdk)) { + if (isAgentEnabled()) { executeStartupTasks(); registerShutdownTasks(); logger.info( @@ -66,19 +64,6 @@ public void afterAgent(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetr } } - boolean isUsingSolarwindsSampler(AutoConfiguredOpenTelemetrySdk autoConfiguredOpenTelemetrySdk) { - Sampler sampler = - autoConfiguredOpenTelemetrySdk.getOpenTelemetrySdk().getSdkTracerProvider().getSampler(); - boolean verdict = sampler instanceof SolarwindsSampler; - setAgentEnabled(verdict); - - if (!verdict) { - logger.warn( - "Not using Solarwinds sampler. Configured sampler is: " + sampler.getDescription()); - } - return verdict; - } - private void executeStartupTasks() { ExecutorService service = Executors.newSingleThreadExecutor(DaemonThreadFactory.newInstance("post-startup-tasks")); diff --git a/custom/src/main/java/com/solarwinds/opentelemetry/extensions/config/provider/AutoConfigurationCustomizerProviderImpl.java b/custom/src/main/java/com/solarwinds/opentelemetry/extensions/config/provider/AutoConfigurationCustomizerProviderImpl.java index e598304c..e98dc778 100644 --- a/custom/src/main/java/com/solarwinds/opentelemetry/extensions/config/provider/AutoConfigurationCustomizerProviderImpl.java +++ b/custom/src/main/java/com/solarwinds/opentelemetry/extensions/config/provider/AutoConfigurationCustomizerProviderImpl.java @@ -48,11 +48,6 @@ public static boolean isAgentEnabled() { return agentEnabled; } - public static void setAgentEnabled(boolean agentEnabled) { - AutoConfigurationCustomizerProviderImpl.agentEnabled = - AutoConfigurationCustomizerProviderImpl.agentEnabled && agentEnabled; - } - @Override public void customize(@Nonnull AutoConfigurationCustomizer autoConfiguration) { try { diff --git a/custom/src/test/java/com/solarwinds/opentelemetry/extensions/SolarwindsAgentListenerTest.java b/custom/src/test/java/com/solarwinds/opentelemetry/extensions/SolarwindsAgentListenerTest.java index 64aecf8b..d3e61754 100644 --- a/custom/src/test/java/com/solarwinds/opentelemetry/extensions/SolarwindsAgentListenerTest.java +++ b/custom/src/test/java/com/solarwinds/opentelemetry/extensions/SolarwindsAgentListenerTest.java @@ -16,19 +16,19 @@ package com.solarwinds.opentelemetry.extensions; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.solarwinds.opentelemetry.extensions.config.provider.AutoConfigurationCustomizerProviderImpl; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.sdk.trace.SdkTracerProvider; -import io.opentelemetry.sdk.trace.samplers.Sampler; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) @@ -39,35 +39,36 @@ class SolarwindsAgentListenerTest { @Mock private OpenTelemetrySdk openTelemetrySdkMock; - @Mock private SdkTracerProvider sdkTracerProviderMock; - - @Mock private Sampler samplerMock; - @Test - void returnFalseWhenOurSamplerIsNotAttached() { - when(autoConfiguredOpenTelemetrySdkMock.getOpenTelemetrySdk()) - .thenReturn(OpenTelemetrySdk.builder().build()); - - assertFalse(tested.isUsingSolarwindsSampler(autoConfiguredOpenTelemetrySdkMock)); - } + void verifySDKIsShutdownWhenBranchIsNotTaken() { + try (MockedStatic + autoConfigurationCustomizerProviderMockedStatic = + mockStatic(AutoConfigurationCustomizerProviderImpl.class)) { - @Test - void returnTrueWhenOurSamplerIsAttached() { - when(autoConfiguredOpenTelemetrySdkMock.getOpenTelemetrySdk()).thenReturn(openTelemetrySdkMock); + autoConfigurationCustomizerProviderMockedStatic + .when(AutoConfigurationCustomizerProviderImpl::isAgentEnabled) + .thenReturn(false); - when(openTelemetrySdkMock.getSdkTracerProvider()).thenReturn(sdkTracerProviderMock); - when(sdkTracerProviderMock.getSampler()).thenReturn(new SolarwindsSampler()); + when(autoConfiguredOpenTelemetrySdkMock.getOpenTelemetrySdk()) + .thenReturn(openTelemetrySdkMock); - assertTrue(tested.isUsingSolarwindsSampler(autoConfiguredOpenTelemetrySdkMock)); + tested.afterAgent(autoConfiguredOpenTelemetrySdkMock); + verify(openTelemetrySdkMock).shutdown(); + } } @Test - void verifySDKIsShutdownWhenBranchIsNotTaken() { - when(autoConfiguredOpenTelemetrySdkMock.getOpenTelemetrySdk()).thenReturn(openTelemetrySdkMock); - when(openTelemetrySdkMock.getSdkTracerProvider()).thenReturn(sdkTracerProviderMock); - when(sdkTracerProviderMock.getSampler()).thenReturn(samplerMock); + void verifySDKIsNotShutdownWhenBranchIsTaken() { + try (MockedStatic + autoConfigurationCustomizerProviderMockedStatic = + mockStatic(AutoConfigurationCustomizerProviderImpl.class)) { + + autoConfigurationCustomizerProviderMockedStatic + .when(AutoConfigurationCustomizerProviderImpl::isAgentEnabled) + .thenReturn(true); - tested.afterAgent(autoConfiguredOpenTelemetrySdkMock); - verify(openTelemetrySdkMock).shutdown(); + tested.afterAgent(autoConfiguredOpenTelemetrySdkMock); + verify(openTelemetrySdkMock, never()).shutdown(); + } } } diff --git a/custom/src/test/java/com/solarwinds/opentelemetry/extensions/provider/AutoConfigurationCustomizerProviderImplTest.java b/custom/src/test/java/com/solarwinds/opentelemetry/extensions/provider/AutoConfigurationCustomizerProviderImplTest.java index 5e31b7a5..54c44a4b 100644 --- a/custom/src/test/java/com/solarwinds/opentelemetry/extensions/provider/AutoConfigurationCustomizerProviderImplTest.java +++ b/custom/src/test/java/com/solarwinds/opentelemetry/extensions/provider/AutoConfigurationCustomizerProviderImplTest.java @@ -17,7 +17,6 @@ package com.solarwinds.opentelemetry.extensions.provider; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.atMostOnce; import static org.mockito.Mockito.verify; @@ -60,13 +59,6 @@ void teardown() throws Throwable { AGENT_ENABLED_SETTER.invokeExact(true); } - @Test - void verifyThatWhenDisabledItIsNeverEnabled() { - AutoConfigurationCustomizerProviderImpl.setAgentEnabled(false); - AutoConfigurationCustomizerProviderImpl.setAgentEnabled(true); - assertFalse(AutoConfigurationCustomizerProviderImpl.isAgentEnabled()); - } - @Test void verifyThatOrderReturnsIntMax() { assertEquals(Integer.MAX_VALUE, tested.order()); diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index 59d30dfa..10b06855 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -64,6 +64,7 @@ dependencies { api("com.github.ben-manes.caffeine:caffeine:2.9.3") api("io.opentelemetry.contrib:opentelemetry-span-stacktrace:$otelJavaContribVersion") + api("io.opentelemetry.contrib:opentelemetry-cel-sampler:$otelJavaContribVersion") api("io.opentelemetry.semconv:opentelemetry-semconv-incubating:$opentelemetrySemconvAlpha") api("io.opentelemetry:opentelemetry-api-incubator:$opentelemetryAlpha") diff --git a/libs/lambda/src/main/java/com/solarwinds/opentelemetry/extensions/DefaultAutoConfigurationCustomizerProvider.java b/libs/lambda/src/main/java/com/solarwinds/opentelemetry/extensions/DefaultAutoConfigurationCustomizerProvider.java index a1be6f04..2f3a6d56 100644 --- a/libs/lambda/src/main/java/com/solarwinds/opentelemetry/extensions/DefaultAutoConfigurationCustomizerProvider.java +++ b/libs/lambda/src/main/java/com/solarwinds/opentelemetry/extensions/DefaultAutoConfigurationCustomizerProvider.java @@ -18,7 +18,6 @@ import com.google.auto.service.AutoService; import com.solarwinds.joboe.config.InvalidConfigException; -import com.solarwinds.joboe.config.JavaRuntimeVersionChecker; import com.solarwinds.joboe.logging.Logger; import com.solarwinds.joboe.logging.LoggerFactory; import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; @@ -29,19 +28,11 @@ public class DefaultAutoConfigurationCustomizerProvider implements AutoConfigurationCustomizerProvider { private static final Logger logger = LoggerFactory.getLogger(); - private static boolean agentEnabled; + private static boolean agentEnabled = true; static { try { - agentEnabled = JavaRuntimeVersionChecker.isJdkVersionSupported(); - if (agentEnabled) { - LambdaConfigurationLoader.load(); - } else { - logger.warn( - String.format( - "Unsupported Java runtime version: %s. The lowest Java version supported is %s.", - System.getProperty("java.version"), JavaRuntimeVersionChecker.minVersionSupported)); - } + LambdaConfigurationLoader.load(); } catch (InvalidConfigException invalidConfigException) { logger.warn("Error loading agent config", invalidConfigException); @@ -57,11 +48,6 @@ public static boolean isAgentEnabled() { return agentEnabled; } - public static void setAgentEnabled(boolean agentEnabled) { - DefaultAutoConfigurationCustomizerProvider.agentEnabled = - DefaultAutoConfigurationCustomizerProvider.agentEnabled && agentEnabled; - } - @Override public void customize(AutoConfigurationCustomizer autoConfiguration) { autoConfiguration diff --git a/libs/lambda/src/main/java/com/solarwinds/opentelemetry/extensions/LambdaAgentListener.java b/libs/lambda/src/main/java/com/solarwinds/opentelemetry/extensions/LambdaAgentListener.java index 8d2b3e1a..f7be2998 100644 --- a/libs/lambda/src/main/java/com/solarwinds/opentelemetry/extensions/LambdaAgentListener.java +++ b/libs/lambda/src/main/java/com/solarwinds/opentelemetry/extensions/LambdaAgentListener.java @@ -17,7 +17,6 @@ package com.solarwinds.opentelemetry.extensions; import static com.solarwinds.opentelemetry.extensions.DefaultAutoConfigurationCustomizerProvider.isAgentEnabled; -import static com.solarwinds.opentelemetry.extensions.DefaultAutoConfigurationCustomizerProvider.setAgentEnabled; import com.google.auto.service.AutoService; import com.solarwinds.joboe.logging.Logger; @@ -25,7 +24,6 @@ import com.solarwinds.joboe.sampling.SettingsManager; import io.opentelemetry.javaagent.extension.AgentListener; import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.sdk.trace.samplers.Sampler; /** * Executes startup task after it's safe to do so. See settingsManagerMock = mockStatic(SettingsManager.class); @@ -56,11 +50,6 @@ void verifySettingsManagerIsInitializedWhenConditionsAreMet() { defaultAutoConfigurationCustomizerProviderMock .when(DefaultAutoConfigurationCustomizerProvider::isAgentEnabled) .thenReturn(true); - when(autoConfiguredOpenTelemetrySdkMock.getOpenTelemetrySdk()) - .thenReturn(openTelemetrySdkMock); - when(openTelemetrySdkMock.getSdkTracerProvider()).thenReturn(sdkTracerProviderMock); - - when(sdkTracerProviderMock.getSampler()).thenReturn(new SolarwindsSampler()); tested.afterAgent(autoConfiguredOpenTelemetrySdkMock); settingsManagerMock.verify(() -> SettingsManager.initialize(any(), any())); @@ -76,12 +65,10 @@ void verifySettingsManagerIsNotInitialized() { defaultAutoConfigurationCustomizerProviderMock .when(DefaultAutoConfigurationCustomizerProvider::isAgentEnabled) - .thenReturn(true); + .thenReturn(false); + when(autoConfiguredOpenTelemetrySdkMock.getOpenTelemetrySdk()) .thenReturn(openTelemetrySdkMock); - when(openTelemetrySdkMock.getSdkTracerProvider()).thenReturn(sdkTracerProviderMock); - - when(sdkTracerProviderMock.getSampler()).thenReturn(samplerMock); tested.afterAgent(autoConfiguredOpenTelemetrySdkMock); settingsManagerMock.verify(() -> SettingsManager.initialize(any(), any()), never()); @@ -90,11 +77,19 @@ void verifySettingsManagerIsNotInitialized() { @Test void verifySDKIsShutdownWhenBranchIsNotTaken() { - when(autoConfiguredOpenTelemetrySdkMock.getOpenTelemetrySdk()).thenReturn(openTelemetrySdkMock); - when(openTelemetrySdkMock.getSdkTracerProvider()).thenReturn(sdkTracerProviderMock); - when(sdkTracerProviderMock.getSampler()).thenReturn(samplerMock); + try (MockedStatic + defaultAutoConfigurationCustomizerProviderMock = + mockStatic(DefaultAutoConfigurationCustomizerProvider.class)) { - tested.afterAgent(autoConfiguredOpenTelemetrySdkMock); - verify(openTelemetrySdkMock).shutdown(); + defaultAutoConfigurationCustomizerProviderMock + .when(DefaultAutoConfigurationCustomizerProvider::isAgentEnabled) + .thenReturn(false); + + when(autoConfiguredOpenTelemetrySdkMock.getOpenTelemetrySdk()) + .thenReturn(openTelemetrySdkMock); + + tested.afterAgent(autoConfiguredOpenTelemetrySdkMock); + verify(openTelemetrySdkMock).shutdown(); + } } } diff --git a/libs/shared/build.gradle.kts b/libs/shared/build.gradle.kts index b27581a9..24f4f202 100644 --- a/libs/shared/build.gradle.kts +++ b/libs/shared/build.gradle.kts @@ -42,6 +42,11 @@ dependencies { exclude(module = "opentelemetry-sdk", group = "io.opentelemetry") // the agent includes this } + implementation("io.opentelemetry.contrib:opentelemetry-cel-sampler") { + exclude(module = "opentelemetry-sdk", group = "io.opentelemetry") // the agent includes this + exclude(group = "com.google.code.findbugs", module = "annotations") + } + implementation("org.json:json") implementation("com.google.code.gson:gson") implementation("com.github.ben-manes.caffeine:caffeine") diff --git a/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/config/provider/SharedConfigCustomizerProvider.java b/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/config/provider/SharedConfigCustomizerProvider.java index 91ef3b74..48bb823b 100644 --- a/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/config/provider/SharedConfigCustomizerProvider.java +++ b/libs/shared/src/main/java/com/solarwinds/opentelemetry/extensions/config/provider/SharedConfigCustomizerProvider.java @@ -152,10 +152,13 @@ private void addProcessors(TracerProviderModel model) { } private void addSampler(TracerProviderModel model) { - model.withSampler( - new SamplerModel() - .withAdditionalProperty( - SamplerComponentProvider.COMPONENT_NAME, new SamplerPropertyModel())); + SamplerModel sampler = model.getSampler(); + if (sampler == null) { + model.withSampler( + new SamplerModel() + .withAdditionalProperty( + SamplerComponentProvider.COMPONENT_NAME, new SamplerPropertyModel())); + } } private void addContextPropagators(PropagatorModel model) { diff --git a/libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/config/provider/SharedConfigCustomizerProviderTest.java b/libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/config/provider/SharedConfigCustomizerProviderTest.java index 72c0cdb6..f01a314e 100644 --- a/libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/config/provider/SharedConfigCustomizerProviderTest.java +++ b/libs/shared/src/test/java/com/solarwinds/opentelemetry/extensions/config/provider/SharedConfigCustomizerProviderTest.java @@ -650,6 +650,41 @@ void tracesNotConfiguredWhenTracerProviderAbsent() { assertNotNull(openTelemetryConfigurationModel.getPropagator()); } + @Test + void customizeShouldNotOverrideSamplerWhenOneIsAlreadyConfigured() { + SamplerModel userSampler = new SamplerModel().withAdditionalProperty("cel", null); + + OpenTelemetryConfigurationModel openTelemetryConfigurationModel = + new OpenTelemetryConfigurationModel() + .withTracerProvider(new TracerProviderModel().withSampler(userSampler)) + .withInstrumentationDevelopment( + new ExperimentalInstrumentationModel() + .withJava( + new ExperimentalLanguageSpecificInstrumentationModel() + .withAdditionalProperty( + "solarwinds", + new ExperimentalLanguageSpecificInstrumentationPropertyModel() + .withAdditionalProperty( + ConfigProperty.AGENT_SERVICE_KEY.getConfigFileKey(), + "token:service") + .withAdditionalProperty( + ConfigProperty.AGENT_COLLECTOR.getConfigFileKey(), + "apm.collector.com")))); + + doNothing() + .when(declarativeConfigurationCustomizerMock) + .addModelCustomizer(functionArgumentCaptor.capture()); + + tested.customize(declarativeConfigurationCustomizerMock); + functionArgumentCaptor.getValue().apply(openTelemetryConfigurationModel); + + TracerProviderModel tracerProvider = openTelemetryConfigurationModel.getTracerProvider(); + SamplerModel sampler = tracerProvider.getSampler(); + + assertNull(sampler.getAdditionalProperties().get(SamplerComponentProvider.COMPONENT_NAME)); + assertTrue(sampler.getAdditionalProperties().containsKey("cel")); + } + @Test void logsNotConfiguredWhenLoggerProviderAbsent() { OpenTelemetryConfigurationModel openTelemetryConfigurationModel = diff --git a/testing/agent-for-testing/build.gradle.kts b/testing/agent-for-testing/build.gradle.kts index 289e5631..3ebf0cbc 100644 --- a/testing/agent-for-testing/build.gradle.kts +++ b/testing/agent-for-testing/build.gradle.kts @@ -80,7 +80,11 @@ tasks { filesMatching("META-INF/services/**") { duplicatesStrategy = DuplicatesStrategy.INCLUDE } + exclude("**/module-info.class") + filesMatching(listOf("META-INF/LICENSE", "META-INF/LICENSE.txt", "META-INF/NOTICE", "META-INF/NOTICE.txt")) { + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } // exclude known bootstrap dependencies - they can't appear in the inst/ directory dependencies {