Skip to content

Commit d60b1d9

Browse files
authored
Configure jsonSchema2Pojo to not initialize collections (#8356)
1 parent 0aa7828 commit d60b1d9

4 files changed

Lines changed: 87 additions & 47 deletions

File tree

sdk-extensions/declarative-config/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ jsonSchema2Pojo {
107107

108108
// Append Model as suffix to the generated classes.
109109
classNameSuffix = "Model"
110+
111+
// Initialize collection fields to null rather than empty collections so that absent YAML
112+
// properties deserialize as null (not present) rather than [] (explicitly empty). This lets
113+
// factories distinguish between "user omitted the field" and "user provided an empty list",
114+
// which is important for validations like IncludeExcludeFactory.
115+
initializeCollections = false
110116
}
111117

112118
val generateJsonSchema2Pojo = tasks.getByName("generateJsonSchema2Pojo")

sdk-extensions/declarative-config/src/main/java/io/opentelemetry/sdk/autoconfigure/declarativeconfig/ComposableRuleBasedSamplerFactory.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,10 @@ public ComposableSampler create(
5454
rule -> {
5555
AttributeMatcher valueMatcher = attributeValuesMatcher(rule.getAttributeValues());
5656
AttributeMatcher patternMatcher = attributePatternsMatcher(rule.getAttributePatterns());
57-
// TODO: should be null when omitted but is empty
5857
Set<ExperimentalSpanParent> matchingParents =
5958
rule.getParent() != null && !rule.getParent().isEmpty()
6059
? new HashSet<>(rule.getParent())
6160
: null;
62-
// TODO: should be null when omitted but is empty
6361
Set<SpanKind> matchingSpanKinds =
6462
rule.getSpanKinds() != null && !rule.getSpanKinds().isEmpty()
6563
? rule.getSpanKinds().stream()

sdk-extensions/declarative-config/src/test/java/io/opentelemetry/sdk/autoconfigure/declarativeconfig/ComposableRuleBasedSamplerFactoryTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,33 @@ private static Stream<Arguments> createTestCases() {
135135
Arguments.of(
136136
new ExperimentalComposableRuleBasedSamplerModel(),
137137
ComposableSampler.ruleBasedBuilder().build()),
138+
// attributePatterns with only included (no excluded) - analogous to
139+
// https://github.com/open-telemetry/opentelemetry-java/issues/8337
140+
Arguments.of(
141+
new ExperimentalComposableRuleBasedSamplerModel()
142+
.withRules(
143+
Collections.singletonList(
144+
new ExperimentalComposableRuleBasedSamplerRuleModel()
145+
.withAttributePatterns(
146+
new ExperimentalComposableRuleBasedSamplerRuleAttributePatternsModel()
147+
.withKey("http.path")
148+
.withIncluded(Collections.singletonList("/internal/*")))
149+
.withSampler(
150+
new ExperimentalComposableSamplerModel()
151+
.withAlwaysOn(
152+
new ExperimentalComposableAlwaysOnSamplerModel())))),
153+
ComposableSampler.ruleBasedBuilder()
154+
.add(
155+
new DeclarativeConfigSamplingPredicate(
156+
null,
157+
new AttributeMatcher(
158+
"http.path",
159+
IncludeExcludePredicate.createPatternMatching(
160+
Collections.singletonList("/internal/*"), null)),
161+
null,
162+
null),
163+
ComposableSampler.alwaysOn())
164+
.build()),
138165
// Recreate example
139166
Arguments.of(
140167
new ExperimentalComposableRuleBasedSamplerModel()

sdk-extensions/declarative-config/src/test/java/io/opentelemetry/sdk/autoconfigure/declarativeconfig/ViewFactoryTest.java

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -18,56 +18,65 @@
1818
import io.opentelemetry.sdk.metrics.View;
1919
import java.util.Arrays;
2020
import java.util.Collections;
21-
import org.junit.jupiter.api.Test;
21+
import java.util.stream.Stream;
22+
import org.junit.jupiter.params.ParameterizedTest;
23+
import org.junit.jupiter.params.provider.Arguments;
24+
import org.junit.jupiter.params.provider.MethodSource;
2225

2326
class ViewFactoryTest {
2427

25-
@Test
26-
void create_Defaults() {
27-
View expectedView = View.builder().build();
28-
29-
View view =
30-
ViewFactory.getInstance()
31-
.create(
32-
new ViewStreamModel().withAttributeKeys(null),
33-
mock(DeclarativeConfigContext.class));
34-
28+
@ParameterizedTest
29+
@MethodSource("createArguments")
30+
void create(ViewStreamModel model, View expectedView) {
31+
View view = ViewFactory.getInstance().create(model, mock(DeclarativeConfigContext.class));
3532
assertThat(view.toString()).isEqualTo(expectedView.toString());
3633
}
3734

38-
@Test
39-
void create() {
40-
View expectedView =
41-
View.builder()
42-
.setName("name")
43-
.setDescription("description")
44-
.setAttributeFilter(
45-
IncludeExcludePredicate.createPatternMatching(
46-
Arrays.asList("foo", "bar"), Collections.singletonList("baz")))
47-
.setAggregation(
48-
Aggregation.explicitBucketHistogram(
49-
ExplicitBucketHistogramOptions.builder()
50-
.setBucketBoundaries(Arrays.asList(1.0, 2.0))
51-
.build()))
52-
.build();
53-
54-
View view =
55-
ViewFactory.getInstance()
56-
.create(
57-
new ViewStreamModel()
58-
.withName("name")
59-
.withDescription("description")
60-
.withAttributeKeys(
61-
new IncludeExcludeModel()
62-
.withIncluded(Arrays.asList("foo", "bar"))
63-
.withExcluded(Collections.singletonList("baz")))
64-
.withAggregation(
65-
new AggregationModel()
66-
.withExplicitBucketHistogram(
67-
new ExplicitBucketHistogramAggregationModel()
68-
.withBoundaries(Arrays.asList(1.0, 2.0)))),
69-
mock(DeclarativeConfigContext.class));
70-
71-
assertThat(view.toString()).isEqualTo(expectedView.toString());
35+
private static Stream<Arguments> createArguments() {
36+
return Stream.of(
37+
// defaults
38+
Arguments.of(new ViewStreamModel().withAttributeKeys(null), View.builder().build()),
39+
// attribute_keys with only included (no excluded) - reproduces
40+
// https://github.com/open-telemetry/opentelemetry-java/issues/8337
41+
Arguments.of(
42+
new ViewStreamModel()
43+
.withAttributeKeys(
44+
new IncludeExcludeModel()
45+
.withIncluded(
46+
Arrays.asList(
47+
"url.full", "http.request.method", "http.response.status_code"))),
48+
View.builder()
49+
.setAttributeFilter(
50+
IncludeExcludePredicate.createPatternMatching(
51+
Arrays.asList(
52+
"url.full", "http.request.method", "http.response.status_code"),
53+
null))
54+
.build()),
55+
// full configuration
56+
Arguments.of(
57+
new ViewStreamModel()
58+
.withName("name")
59+
.withDescription("description")
60+
.withAttributeKeys(
61+
new IncludeExcludeModel()
62+
.withIncluded(Arrays.asList("foo", "bar"))
63+
.withExcluded(Collections.singletonList("baz")))
64+
.withAggregation(
65+
new AggregationModel()
66+
.withExplicitBucketHistogram(
67+
new ExplicitBucketHistogramAggregationModel()
68+
.withBoundaries(Arrays.asList(1.0, 2.0)))),
69+
View.builder()
70+
.setName("name")
71+
.setDescription("description")
72+
.setAttributeFilter(
73+
IncludeExcludePredicate.createPatternMatching(
74+
Arrays.asList("foo", "bar"), Collections.singletonList("baz")))
75+
.setAggregation(
76+
Aggregation.explicitBucketHistogram(
77+
ExplicitBucketHistogramOptions.builder()
78+
.setBucketBoundaries(Arrays.asList(1.0, 2.0))
79+
.build()))
80+
.build()));
7281
}
7382
}

0 commit comments

Comments
 (0)