Skip to content

Commit de22afe

Browse files
authored
Add declarative support for composable parent threshold sampler (#7941)
1 parent f7324ec commit de22afe

File tree

3 files changed

+81
-28
lines changed

3 files changed

+81
-28
lines changed

sdk-extensions/incubator/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ tasks.getByName("compileJava").dependsOn(deleteJs2pTmp)
199199
tasks.getByName("sourcesJar").dependsOn(deleteJs2pTmp, buildGraalVmReflectionJson)
200200
tasks.getByName("jar").dependsOn(deleteJs2pTmp, buildGraalVmReflectionJson)
201201
tasks.getByName("javadoc").dependsOn(buildGraalVmReflectionJson)
202+
tasks.getByName("compileTestJava").dependsOn(buildGraalVmReflectionJson)
202203

203204
// Exclude jsonschema2pojo generated sources from checkstyle
204205
tasks.named<Checkstyle>("checkstyleMain") {

sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ComposableSamplerFactory.java

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

66
package io.opentelemetry.sdk.extension.incubator.fileconfig;
77

8+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalComposableParentThresholdSamplerModel;
89
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalComposableProbabilitySamplerModel;
910
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalComposableRuleBasedSamplerModel;
1011
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalComposableSamplerModel;
@@ -43,6 +44,13 @@ public ComposableSampler create(
4344
if (ruleBased != null) {
4445
return ComposableRuleBasedSamplerFactory.getInstance().create(ruleBased, context);
4546
}
47+
ExperimentalComposableParentThresholdSamplerModel parentThreshold = model.getParentThreshold();
48+
if (parentThreshold != null) {
49+
ExperimentalComposableSamplerModel rootModel =
50+
FileConfigUtil.requireNonNull(parentThreshold.getRoot(), "parent threshold sampler root");
51+
ComposableSampler rootSampler = INSTANCE.create(rootModel, context);
52+
return ComposableSampler.parentThreshold(rootSampler);
53+
}
4654
Map.Entry<String, ?> keyValue =
4755
FileConfigUtil.getSingletonMapEntry(model.getAdditionalProperties(), "composable sampler");
4856
return context.loadComponent(ComposableSampler.class, keyValue.getKey(), keyValue.getValue());

sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/SamplerFactoryTest.java

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,21 @@
1515
import io.opentelemetry.sdk.extension.incubator.fileconfig.component.SamplerComponentProvider;
1616
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.AlwaysOffSamplerModel;
1717
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.AlwaysOnSamplerModel;
18+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalComposableAlwaysOffSamplerModel;
19+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalComposableAlwaysOnSamplerModel;
20+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalComposableParentThresholdSamplerModel;
21+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalComposableProbabilitySamplerModel;
22+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalComposableRuleBasedSamplerModel;
23+
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalComposableSamplerModel;
1824
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExperimentalJaegerRemoteSamplerModel;
1925
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ParentBasedSamplerModel;
2026
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SamplerModel;
2127
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SamplerPropertyModel;
2228
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TraceIdRatioBasedSamplerModel;
29+
import io.opentelemetry.sdk.extension.incubator.trace.samplers.ComposableSampler;
30+
import io.opentelemetry.sdk.extension.incubator.trace.samplers.CompositeSampler;
2331
import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler;
32+
import io.opentelemetry.sdk.trace.samplers.Sampler;
2433
import java.io.Closeable;
2534
import java.time.Duration;
2635
import java.util.ArrayList;
@@ -45,16 +54,14 @@ class SamplerFactoryTest {
4554

4655
@ParameterizedTest
4756
@MethodSource("createArguments")
48-
void create(
49-
@Nullable SamplerModel model, io.opentelemetry.sdk.trace.samplers.Sampler expectedSampler) {
57+
void create(@Nullable SamplerModel model, Sampler expectedSampler) {
5058
// Some samplers like JaegerRemoteSampler are Closeable - ensure these get cleaned up
5159
if (expectedSampler instanceof Closeable) {
5260
cleanup.addCloseable((Closeable) expectedSampler);
5361
}
5462

5563
List<Closeable> closeables = new ArrayList<>();
56-
io.opentelemetry.sdk.trace.samplers.Sampler sampler =
57-
SamplerFactory.getInstance().create(model, context);
64+
Sampler sampler = SamplerFactory.getInstance().create(model, context);
5865
cleanup.addCloseables(closeables);
5966

6067
assertThat(sampler.toString()).isEqualTo(expectedSampler.toString());
@@ -63,22 +70,19 @@ void create(
6370
private static Stream<Arguments> createArguments() {
6471
return Stream.of(
6572
Arguments.of(
66-
new SamplerModel().withAlwaysOn(new AlwaysOnSamplerModel()),
67-
io.opentelemetry.sdk.trace.samplers.Sampler.alwaysOn()),
73+
new SamplerModel().withAlwaysOn(new AlwaysOnSamplerModel()), Sampler.alwaysOn()),
6874
Arguments.of(
69-
new SamplerModel().withAlwaysOff(new AlwaysOffSamplerModel()),
70-
io.opentelemetry.sdk.trace.samplers.Sampler.alwaysOff()),
75+
new SamplerModel().withAlwaysOff(new AlwaysOffSamplerModel()), Sampler.alwaysOff()),
7176
Arguments.of(
7277
new SamplerModel().withTraceIdRatioBased(new TraceIdRatioBasedSamplerModel()),
73-
io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(1.0d)),
78+
Sampler.traceIdRatioBased(1.0d)),
7479
Arguments.of(
7580
new SamplerModel()
7681
.withTraceIdRatioBased(new TraceIdRatioBasedSamplerModel().withRatio(0.5d)),
77-
io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.5)),
82+
Sampler.traceIdRatioBased(0.5)),
7883
Arguments.of(
7984
new SamplerModel().withParentBased(new ParentBasedSamplerModel()),
80-
io.opentelemetry.sdk.trace.samplers.Sampler.parentBased(
81-
io.opentelemetry.sdk.trace.samplers.Sampler.alwaysOn())),
85+
Sampler.parentBased(Sampler.alwaysOn())),
8286
Arguments.of(
8387
new SamplerModel()
8488
.withParentBased(
@@ -103,16 +107,11 @@ private static Stream<Arguments> createArguments() {
103107
new SamplerModel()
104108
.withTraceIdRatioBased(
105109
new TraceIdRatioBasedSamplerModel().withRatio(0.5d)))),
106-
io.opentelemetry.sdk.trace.samplers.Sampler.parentBasedBuilder(
107-
io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.1d))
108-
.setRemoteParentSampled(
109-
io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.2d))
110-
.setRemoteParentNotSampled(
111-
io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.3d))
112-
.setLocalParentSampled(
113-
io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.4d))
114-
.setLocalParentNotSampled(
115-
io.opentelemetry.sdk.trace.samplers.Sampler.traceIdRatioBased(0.5d))
110+
Sampler.parentBasedBuilder(Sampler.traceIdRatioBased(0.1d))
111+
.setRemoteParentSampled(Sampler.traceIdRatioBased(0.2d))
112+
.setRemoteParentNotSampled(Sampler.traceIdRatioBased(0.3d))
113+
.setLocalParentSampled(Sampler.traceIdRatioBased(0.4d))
114+
.setLocalParentNotSampled(Sampler.traceIdRatioBased(0.5d))
116115
.build()),
117116
Arguments.of(
118117
new SamplerModel()
@@ -125,17 +124,55 @@ private static Stream<Arguments> createArguments() {
125124
JaegerRemoteSampler.builder()
126125
.setEndpoint("http://jaeger-remote-endpoint")
127126
.setPollingInterval(Duration.ofSeconds(10))
128-
.setInitialSampler(io.opentelemetry.sdk.trace.samplers.Sampler.alwaysOff())
129-
.build()));
127+
.setInitialSampler(Sampler.alwaysOff())
128+
.build()),
129+
Arguments.of(
130+
new SamplerModel()
131+
.withCompositeDevelopment(
132+
new ExperimentalComposableSamplerModel()
133+
.withAlwaysOn(new ExperimentalComposableAlwaysOnSamplerModel())),
134+
CompositeSampler.wrap(ComposableSampler.alwaysOn())),
135+
Arguments.of(
136+
new SamplerModel()
137+
.withCompositeDevelopment(
138+
new ExperimentalComposableSamplerModel()
139+
.withAlwaysOff(new ExperimentalComposableAlwaysOffSamplerModel())),
140+
CompositeSampler.wrap(ComposableSampler.alwaysOff())),
141+
Arguments.of(
142+
new SamplerModel()
143+
.withCompositeDevelopment(
144+
new ExperimentalComposableSamplerModel()
145+
.withProbability(
146+
new ExperimentalComposableProbabilitySamplerModel().withRatio(0.5))),
147+
CompositeSampler.wrap(ComposableSampler.probability(0.5))),
148+
Arguments.of(
149+
new SamplerModel()
150+
.withCompositeDevelopment(
151+
new ExperimentalComposableSamplerModel()
152+
.withRuleBased(new ExperimentalComposableRuleBasedSamplerModel())),
153+
CompositeSampler.wrap(ComposableSampler.ruleBasedBuilder().build())),
154+
Arguments.of(
155+
new SamplerModel()
156+
.withCompositeDevelopment(
157+
new ExperimentalComposableSamplerModel()
158+
.withParentThreshold(
159+
new ExperimentalComposableParentThresholdSamplerModel()
160+
.withRoot(
161+
new ExperimentalComposableSamplerModel()
162+
.withAlwaysOn(
163+
new ExperimentalComposableAlwaysOnSamplerModel())))),
164+
CompositeSampler.wrap(
165+
ComposableSampler.parentThreshold(ComposableSampler.alwaysOn()))));
130166
}
131167

132168
@ParameterizedTest
133169
@MethodSource("createInvalidArguments")
134170
void createInvalid(SamplerModel model, String expectedMessage) {
135171
assertThatThrownBy(() -> SamplerFactory.getInstance().create(model, context))
136172
.isInstanceOf(DeclarativeConfigException.class)
137-
.cause()
138-
.hasMessage(expectedMessage);
173+
.extracting(throwable -> throwable.getCause() == null ? throwable : throwable.getCause())
174+
.extracting(Throwable::getMessage)
175+
.isEqualTo(expectedMessage);
139176
}
140177

141178
private static Stream<Arguments> createInvalidArguments() {
@@ -149,7 +186,14 @@ private static Stream<Arguments> createInvalidArguments() {
149186
.withJaegerRemoteDevelopment(
150187
new ExperimentalJaegerRemoteSamplerModel()
151188
.withEndpoint("http://jaeger-remote-endpoint")),
152-
"jaeger remote sampler initial_sampler is required"));
189+
"jaeger remote sampler initial_sampler is required"),
190+
Arguments.of(
191+
new SamplerModel()
192+
.withCompositeDevelopment(
193+
new ExperimentalComposableSamplerModel()
194+
.withParentThreshold(
195+
new ExperimentalComposableParentThresholdSamplerModel())),
196+
"parent threshold sampler root is required but is null"));
153197
}
154198

155199
@Test
@@ -174,7 +218,7 @@ void create_SpiExporter_Unknown() {
174218

175219
@Test
176220
void create_SpiExporter_Valid() {
177-
io.opentelemetry.sdk.trace.samplers.Sampler sampler =
221+
Sampler sampler =
178222
SamplerFactory.getInstance()
179223
.create(
180224
new SamplerModel()

0 commit comments

Comments
 (0)