Skip to content

Commit 2b67f7a

Browse files
authored
[dynamic control] wire up first policy (#2833)
1 parent cb87fe9 commit 2b67f7a

8 files changed

Lines changed: 164 additions & 17 deletions

File tree

dynamic-control/src/main/java/io/opentelemetry/contrib/dynamic/policy/registry/PolicyInit.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import io.opentelemetry.contrib.dynamic.policy.PolicyTypeInitializer;
1414
import io.opentelemetry.contrib.dynamic.policy.PolicyValidator;
1515
import io.opentelemetry.contrib.dynamic.policy.TelemetryPolicy;
16+
import io.opentelemetry.contrib.dynamic.policy.tracesampling.TraceSamplingRatePolicy;
1617
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
1718
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
1819
import java.io.Closeable;
@@ -65,9 +66,8 @@ public final class PolicyInit {
6566
private static final PolicyStore policyStore = new PolicyStore();
6667

6768
static {
68-
// For now, policies will be registered here.
69-
// TODO: register TraceSamplingRatePolicy when registerPolicyType implemented
70-
// TraceSamplingRatePolicy.registerPolicyType();
69+
// For now, policies will be registered here. TODO: move to a more dynamic way.
70+
TraceSamplingRatePolicy.registerPolicyType();
7171
}
7272

7373
/**

dynamic-control/src/main/java/io/opentelemetry/contrib/dynamic/policy/tracesampling/TraceSamplingRatePolicy.java

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

66
package io.opentelemetry.contrib.dynamic.policy.tracesampling;
77

8+
import io.opentelemetry.contrib.dynamic.policy.PolicyImplementer;
89
import io.opentelemetry.contrib.dynamic.policy.TelemetryPolicy;
10+
import io.opentelemetry.contrib.dynamic.policy.registry.PolicyInit;
911
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
1012
import io.opentelemetry.sdk.extension.incubator.trace.samplers.ComposableSampler;
1113
import io.opentelemetry.sdk.extension.incubator.trace.samplers.CompositeSampler;
@@ -35,12 +37,18 @@ public double getProbability() {
3537
* <p>If the extension is configured to use this policy, this installs an opinionated sampler that
3638
* overrides any other sampler
3739
*/
38-
public static void initialize(AutoConfigurationCustomizer autoConfiguration) {
40+
public static PolicyImplementer initialize(AutoConfigurationCustomizer autoConfiguration) {
3941
Objects.requireNonNull(autoConfiguration, "autoConfiguration cannot be null");
4042
Sampler initialDelegate = createSampler(1.0);
4143
DelegatingSampler delegatingSampler = new DelegatingSampler(initialDelegate);
4244
initializedSampler = delegatingSampler;
4345
autoConfiguration.addSamplerCustomizer((sampler, config) -> delegatingSampler);
46+
return new TraceSamplingRatePolicyImplementer(delegatingSampler);
47+
}
48+
49+
public static void registerPolicyType() {
50+
PolicyInit.registerPolicyType(
51+
POLICY_TYPE, TraceSamplingRatePolicy.class, TraceSamplingRatePolicy::initialize);
4452
}
4553

4654
/**
@@ -69,6 +77,10 @@ public static DelegatingSampler getInitializedSampler() {
6977
return initializedSampler;
7078
}
7179

80+
static void resetForTest() {
81+
initializedSampler = null;
82+
}
83+
7284
@Override
7385
public boolean equals(Object obj) {
7486
if (this == obj) {

dynamic-control/src/test/java/io/opentelemetry/contrib/dynamic/policy/registry/PolicyInitConfigTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void readFromConfigPropertiesReadsJsonWhenYamlPathMissing() throws Exception {
8989
assertThat(source.getLocation()).isEqualTo("vendor");
9090
assertThat(source.getMappings()).hasSize(1);
9191
assertThat(source.getMappings().get(0).getSourceKey()).isEqualTo("sampling_rate");
92-
assertThat(source.getMappings().get(0).getPolicyType()).isEqualTo("trace_sampling_rate_policy");
92+
assertThat(source.getMappings().get(0).getPolicyType()).isEqualTo("trace-sampling");
9393
}
9494

9595
@Test
@@ -191,7 +191,7 @@ void readFromDeclarativeConfigPropertiesReadsTelemetryPolicySources() {
191191
assertThat(source.getLocation()).isEqualTo("from-declarative");
192192
assertThat(source.getMappings()).hasSize(1);
193193
assertThat(source.getMappings().get(0).getSourceKey()).isEqualTo("sampling_rate");
194-
assertThat(source.getMappings().get(0).getPolicyType()).isEqualTo("trace_sampling_rate_policy");
194+
assertThat(source.getMappings().get(0).getPolicyType()).isEqualTo("trace-sampling");
195195
}
196196

197197
@Test
@@ -428,7 +428,7 @@ private static DeclarativeConfigProperties mappingConfig() {
428428
when(mapping.getString(PolicyInitConfig.SOURCE_KEY_DECLARATIVE_KEY))
429429
.thenReturn("sampling_rate");
430430
when(mapping.getString(PolicyInitConfig.POLICY_TYPE_DECLARATIVE_KEY))
431-
.thenReturn("trace_sampling_rate_policy");
431+
.thenReturn("trace-sampling");
432432
return mapping;
433433
}
434434

@@ -453,13 +453,13 @@ public DeclarativeConfigProperties getGeneralConfig() {
453453

454454
private static String minimalJsonConfig() {
455455
return "{\"sources\":[{\"kind\":\"opamp\",\"format\":\"jsonkeyvalue\",\"location\":\"vendor\","
456-
+ "\"mappings\":[{\"sourceKey\":\"sampling_rate\",\"policyType\":\"trace_sampling_rate_policy\"}]}]}";
456+
+ "\"mappings\":[{\"sourceKey\":\"sampling_rate\",\"policyType\":\"trace-sampling\"}]}]}";
457457
}
458458

459459
private static String jsonWithLocation(String location) {
460460
return "{\"sources\":[{\"kind\":\"opamp\",\"format\":\"jsonkeyvalue\",\"location\":\""
461461
+ location
462-
+ "\",\"mappings\":[{\"sourceKey\":\"sampling_rate\",\"policyType\":\"trace_sampling_rate_policy\"}]}]}";
462+
+ "\",\"mappings\":[{\"sourceKey\":\"sampling_rate\",\"policyType\":\"trace-sampling\"}]}]}";
463463
}
464464

465465
private static String minimalYamlConfig() {
@@ -469,7 +469,7 @@ private static String minimalYamlConfig() {
469469
+ " location: vendor\n"
470470
+ " mappings:\n"
471471
+ " - sourceKey: sampling_rate\n"
472-
+ " policyType: trace_sampling_rate_policy\n";
472+
+ " policyType: trace-sampling\n";
473473
}
474474

475475
private static String yamlWithLocation(String location) {
@@ -481,6 +481,6 @@ private static String yamlWithLocation(String location) {
481481
+ "\n"
482482
+ " mappings:\n"
483483
+ " - sourceKey: sampling_rate\n"
484-
+ " policyType: trace_sampling_rate_policy\n";
484+
+ " policyType: trace-sampling\n";
485485
}
486486
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.contrib.dynamic.policy.registry;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
10+
import static org.mockito.Mockito.mock;
11+
import static org.mockito.Mockito.verify;
12+
import static org.mockito.Mockito.when;
13+
14+
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
15+
import io.opentelemetry.contrib.dynamic.policy.tracesampling.TraceSamplingRatePolicy;
16+
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
17+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
18+
import java.lang.reflect.Method;
19+
import java.nio.charset.StandardCharsets;
20+
import java.nio.file.Files;
21+
import java.nio.file.Path;
22+
import java.util.Collections;
23+
import java.util.Map;
24+
import java.util.function.Function;
25+
import org.junit.jupiter.api.AfterEach;
26+
import org.junit.jupiter.api.Test;
27+
import org.junit.jupiter.api.io.TempDir;
28+
import org.mockito.ArgumentCaptor;
29+
30+
class PolicyInitTest {
31+
@TempDir Path tempDir;
32+
33+
@AfterEach
34+
void tearDown() throws Exception {
35+
PolicyInit.resetForTest();
36+
invokeStaticNoArg(TraceSamplingRatePolicy.class, "resetForTest");
37+
}
38+
39+
@Test
40+
void doesNotInitializePolicyFromDeclarativeOnlyConfigInAutoConfigurationMode() {
41+
AutoConfigurationCustomizer customizer = mock(AutoConfigurationCustomizer.class);
42+
PolicyInit.init(customizer);
43+
Function<ConfigProperties, Map<String, String>> propertiesCustomizer =
44+
capturePropertiesCustomizer(customizer);
45+
46+
ConfigProperties config = mock(ConfigProperties.class);
47+
when(config.getString(PolicyInitConfig.POLICY_INIT_CONFIG_PROPERTY_YAML)).thenReturn(null);
48+
when(config.getString(PolicyInitConfig.POLICY_INIT_CONFIG_PROPERTY_JSON)).thenReturn(null);
49+
Map<String, String> ignored = propertiesCustomizer.apply(config);
50+
51+
assertThat(TraceSamplingRatePolicy.getInitializedSampler()).isNull();
52+
assertThat(ignored).isNotNull();
53+
}
54+
55+
@Test
56+
void initializesPolicyFromInitConfigInAutoConfigurationMode() throws Exception {
57+
AutoConfigurationCustomizer customizer = mock(AutoConfigurationCustomizer.class);
58+
PolicyInit.init(customizer);
59+
Function<ConfigProperties, Map<String, String>> propertiesCustomizer =
60+
capturePropertiesCustomizer(customizer);
61+
62+
Path configPath = tempDir.resolve("policy-init.json");
63+
Files.write(configPath, minimalJsonInitConfig().getBytes(StandardCharsets.UTF_8));
64+
65+
ConfigProperties config = mock(ConfigProperties.class);
66+
when(config.getString(PolicyInitConfig.POLICY_INIT_CONFIG_PROPERTY_YAML)).thenReturn(null);
67+
when(config.getString(PolicyInitConfig.POLICY_INIT_CONFIG_PROPERTY_JSON))
68+
.thenReturn(configPath.toString());
69+
70+
Map<String, String> ignored = propertiesCustomizer.apply(config);
71+
72+
assertThat(ignored).isNotNull();
73+
assertThat(TraceSamplingRatePolicy.getInitializedSampler()).isNotNull();
74+
}
75+
76+
@Test
77+
void initializesRegisteredPolicyTypeFromDeclarativeConfig() {
78+
ConfigProperties config = mock(ConfigProperties.class);
79+
80+
PolicyInit.initFromDeclarativeConfig(
81+
telemetryPolicyNodeConfig(TraceSamplingRatePolicy.POLICY_TYPE), config);
82+
83+
assertThat(TraceSamplingRatePolicy.getInitializedSampler()).isNotNull();
84+
}
85+
86+
@Test
87+
void throwsWhenDeclarativeConfigUsesUnknownPolicyType() {
88+
ConfigProperties config = mock(ConfigProperties.class);
89+
90+
assertThatThrownBy(
91+
() ->
92+
PolicyInit.initFromDeclarativeConfig(
93+
telemetryPolicyNodeConfig("trace_sampling_rate_policy"), config))
94+
.isInstanceOf(IllegalArgumentException.class)
95+
.hasMessageContaining("Unknown policyType");
96+
}
97+
98+
private static Function<ConfigProperties, Map<String, String>> capturePropertiesCustomizer(
99+
AutoConfigurationCustomizer customizer) {
100+
@SuppressWarnings("unchecked")
101+
ArgumentCaptor<Function<ConfigProperties, Map<String, String>>> captor =
102+
ArgumentCaptor.forClass(Function.class);
103+
verify(customizer).addPropertiesCustomizer(captor.capture());
104+
return captor.getValue();
105+
}
106+
107+
private static void invokeStaticNoArg(Class<?> targetClass, String methodName) throws Exception {
108+
Method method = targetClass.getDeclaredMethod(methodName);
109+
method.setAccessible(true);
110+
method.invoke(null);
111+
}
112+
113+
private static DeclarativeConfigProperties telemetryPolicyNodeConfig(String policyType) {
114+
DeclarativeConfigProperties telemetryPolicy = mock(DeclarativeConfigProperties.class);
115+
DeclarativeConfigProperties source = mock(DeclarativeConfigProperties.class);
116+
DeclarativeConfigProperties mapping = mock(DeclarativeConfigProperties.class);
117+
118+
when(telemetryPolicy.getStructuredList(PolicyInitConfig.SOURCES_DECLARATIVE_KEY))
119+
.thenReturn(Collections.singletonList(source));
120+
when(source.getString(PolicyInitConfig.KIND_DECLARATIVE_KEY)).thenReturn("opamp");
121+
when(source.getString(PolicyInitConfig.FORMAT_DECLARATIVE_KEY)).thenReturn("jsonkeyvalue");
122+
when(source.getString(PolicyInitConfig.LOCATION_DECLARATIVE_KEY)).thenReturn("vendor");
123+
when(source.getStructuredList(PolicyInitConfig.MAPPINGS_DECLARATIVE_KEY))
124+
.thenReturn(Collections.singletonList(mapping));
125+
when(mapping.getString(PolicyInitConfig.SOURCE_KEY_DECLARATIVE_KEY))
126+
.thenReturn("sampling_rate");
127+
when(mapping.getString(PolicyInitConfig.POLICY_TYPE_DECLARATIVE_KEY)).thenReturn(policyType);
128+
return telemetryPolicy;
129+
}
130+
131+
private static String minimalJsonInitConfig() {
132+
return "{\"sources\":[{\"kind\":\"opamp\",\"format\":\"jsonkeyvalue\",\"location\":\"vendor\","
133+
+ "\"mappings\":[{\"sourceKey\":\"sampling_rate\",\"policyType\":\""
134+
+ TraceSamplingRatePolicy.POLICY_TYPE
135+
+ "\"}]}]}";
136+
}
137+
}

dynamic-control/src/test/java/io/opentelemetry/contrib/dynamic/policy/registry/json/JsonPolicyInitConfigReaderTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ void readsSourceCentricFixture() throws Exception {
3434
assertThat(source.getLocation()).isEqualTo("vendor-specific");
3535
assertThat(source.getMappings()).hasSize(4);
3636
assertThat(source.getMappings().get(0).getSourceKey()).isEqualTo("sampling_rate");
37-
assertThat(source.getMappings().get(0).getPolicyType())
38-
.isEqualTo("trace_sampling_rate_policy");
37+
assertThat(source.getMappings().get(0).getPolicyType()).isEqualTo("trace-sampling");
3938
}
4039
}
4140

dynamic-control/src/test/java/io/opentelemetry/contrib/dynamic/policy/registry/yaml/YamlPolicyInitConfigReaderTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ void readsSourceCentricFixture() throws Exception {
3434
assertThat(source.getLocation()).isEqualTo("vendor-specific");
3535
assertThat(source.getMappings()).hasSize(4);
3636
assertThat(source.getMappings().get(0).getSourceKey()).isEqualTo("sampling_rate");
37-
assertThat(source.getMappings().get(0).getPolicyType())
38-
.isEqualTo("trace_sampling_rate_policy");
37+
assertThat(source.getMappings().get(0).getPolicyType()).isEqualTo("trace-sampling");
3938
}
4039
}
4140

dynamic-control/src/test/resources/io/opentelemetry/contrib/dynamic/policy/registry/json/policy-init-example.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"format": "jsonkeyvalue",
66
"location": "vendor-specific",
77
"mappings": [
8-
{ "sourceKey": "sampling_rate", "policyType": "trace_sampling_rate_policy" },
8+
{ "sourceKey": "sampling_rate", "policyType": "trace-sampling" },
99
{ "sourceKey": "send_logs", "policyType": "log_export_enabled_policy" },
1010
{ "sourceKey": "send_traces", "policyType": "trace_export_enabled_policy" },
1111
{ "sourceKey": "send_metrics", "policyType": "metric_export_enabled_policy" }

dynamic-control/src/test/resources/io/opentelemetry/contrib/dynamic/policy/registry/yaml/policy-init-example.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ sources:
44
location: vendor-specific
55
mappings:
66
- sourceKey: sampling_rate
7-
policyType: trace_sampling_rate_policy
7+
policyType: trace-sampling
88
- sourceKey: send_logs
99
policyType: log_export_enabled_policy
1010
- sourceKey: send_traces

0 commit comments

Comments
 (0)