Skip to content

Commit 60d53e1

Browse files
authored
package cloud resource in javaagent - but keep them disabled by default (#10754)
1 parent afa3207 commit 60d53e1

File tree

8 files changed

+360
-58
lines changed

8 files changed

+360
-58
lines changed

.github/renovate.json5

+2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
"packageRules": [
1414
{
1515
"matchPackageNames": [
16+
"io.opentelemetry.contrib:opentelemetry-aws-resources",
1617
"io.opentelemetry.contrib:opentelemetry-aws-xray-propagator",
18+
"io.opentelemetry.contrib:opentelemetry-gcp-resources",
1719
"io.opentelemetry.proto:opentelemetry-proto",
1820
"io.opentelemetry.semconv:opentelemetry-semconv"
1921
],

dependencyManagement/build.gradle.kts

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ rootProject.extra["versions"] = dependencyVersions
99

1010
// this line is managed by .github/scripts/update-sdk-version.sh
1111
val otelSdkVersion = "1.36.0"
12+
val otelContribVersion = "1.33.0-alpha"
1213
val otelSdkAlphaVersion = otelSdkVersion.replaceFirst("(-SNAPSHOT)?$".toRegex(), "-alpha$1")
1314

1415
// Need both BOM and groovy jars
@@ -96,7 +97,9 @@ val DEPENDENCIES = listOf(
9697
"commons-logging:commons-logging:1.3.0",
9798
"commons-validator:commons-validator:1.8.0",
9899
"io.netty:netty:3.10.6.Final",
99-
"io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:1.33.0-alpha",
100+
"io.opentelemetry.contrib:opentelemetry-aws-resources:${otelContribVersion}",
101+
"io.opentelemetry.contrib:opentelemetry-aws-xray-propagator:${otelContribVersion}",
102+
"io.opentelemetry.contrib:opentelemetry-gcp-resources:${otelContribVersion}",
100103
"io.opentelemetry.proto:opentelemetry-proto:1.1.0-alpha",
101104
"io.opentelemetry:opentelemetry-extension-annotations:1.18.0", // deprecated, no longer part of bom
102105
"org.assertj:assertj-core:3.25.3",

javaagent-tooling/build.gradle.kts

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ dependencies {
3737

3838
implementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator")
3939

40+
implementation("io.opentelemetry.contrib:opentelemetry-aws-resources")
41+
implementation("io.opentelemetry.contrib:opentelemetry-gcp-resources")
42+
4043
api("net.bytebuddy:byte-buddy-dep")
4144
implementation("org.ow2.asm:asm-tree")
4245
implementation("org.ow2.asm:asm-util")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.tooling.config;
7+
8+
import com.google.auto.service.AutoService;
9+
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
10+
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
11+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
12+
import java.util.ArrayList;
13+
import java.util.Collections;
14+
import java.util.HashMap;
15+
import java.util.HashSet;
16+
import java.util.List;
17+
import java.util.Map;
18+
import java.util.Set;
19+
import javax.annotation.Nullable;
20+
21+
@AutoService(AutoConfigurationCustomizerProvider.class)
22+
public class ResourceProviderPropertiesCustomizer implements AutoConfigurationCustomizerProvider {
23+
24+
private static final Map<String, String> DISABLED_BY_DEFAULT_RESOURCE_PROVIDERS = new HashMap<>();
25+
26+
static {
27+
DISABLED_BY_DEFAULT_RESOURCE_PROVIDERS.put(
28+
"io.opentelemetry.contrib.aws.resource.BeanstalkResourceProvider", "aws");
29+
DISABLED_BY_DEFAULT_RESOURCE_PROVIDERS.put(
30+
"io.opentelemetry.contrib.aws.resource.Ec2ResourceProvider", "aws");
31+
DISABLED_BY_DEFAULT_RESOURCE_PROVIDERS.put(
32+
"io.opentelemetry.contrib.aws.resource.EcsResourceProvider", "aws");
33+
DISABLED_BY_DEFAULT_RESOURCE_PROVIDERS.put(
34+
"io.opentelemetry.contrib.aws.resource.EksResourceProvider", "aws");
35+
DISABLED_BY_DEFAULT_RESOURCE_PROVIDERS.put(
36+
"io.opentelemetry.contrib.aws.resource.LambdaResourceProvider", "aws");
37+
DISABLED_BY_DEFAULT_RESOURCE_PROVIDERS.put(
38+
"io.opentelemetry.contrib.gcp.resource.GCPResourceProvider", "gcp");
39+
// for testing
40+
DISABLED_BY_DEFAULT_RESOURCE_PROVIDERS.put(
41+
"io.opentelemetry.javaagent.tooling.config.ResourceProviderPropertiesCustomizerTest$Provider",
42+
"test");
43+
}
44+
45+
static final String DISABLED_KEY = "otel.java.disabled.resource.providers";
46+
static final String ENABLED_KEY = "otel.java.enabled.resource.providers";
47+
48+
@Override
49+
public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) {
50+
autoConfigurationCustomizer.addPropertiesCustomizer(this::customize);
51+
}
52+
53+
// VisibleForTesting
54+
Map<String, String> customize(ConfigProperties config) {
55+
Set<String> enabledProviders = new HashSet<>(config.getList(ENABLED_KEY));
56+
57+
List<String> enabled = new ArrayList<>();
58+
List<String> disabled = new ArrayList<>();
59+
60+
for (Map.Entry<String, String> providerEntry :
61+
DISABLED_BY_DEFAULT_RESOURCE_PROVIDERS.entrySet()) {
62+
String providerName = providerEntry.getKey();
63+
String providerGroup = providerEntry.getValue();
64+
Boolean explictEnabled =
65+
config.getBoolean(String.format("otel.resource.providers.%s.enabled", providerGroup));
66+
67+
if (isEnabled(providerName, enabledProviders, explictEnabled)) {
68+
enabled.add(providerName);
69+
} else {
70+
disabled.add(providerName);
71+
}
72+
}
73+
74+
if (!enabledProviders.isEmpty()) {
75+
// users has requested specific providers to be enabled only
76+
enabled.addAll(enabledProviders);
77+
return Collections.singletonMap(ENABLED_KEY, String.join(",", enabled));
78+
}
79+
80+
if (disabled.isEmpty()) {
81+
// all providers that are disabled by default are enabled, no need to set any properties
82+
return Collections.emptyMap();
83+
}
84+
85+
disabled.addAll(config.getList(DISABLED_KEY));
86+
return Collections.singletonMap(DISABLED_KEY, String.join(",", disabled));
87+
}
88+
89+
private static boolean isEnabled(
90+
String className, Set<String> enabledProviders, @Nullable Boolean explicitEnabled) {
91+
if (explicitEnabled != null) {
92+
return explicitEnabled;
93+
}
94+
return !enabledProviders.isEmpty() && enabledProviders.contains(className);
95+
}
96+
97+
@Override
98+
public int order() {
99+
// make sure it runs AFTER all the user-provided customizers
100+
return Integer.MAX_VALUE;
101+
}
102+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.tooling.config;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
import io.opentelemetry.api.common.AttributeKey;
11+
import io.opentelemetry.api.common.Attributes;
12+
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
13+
import io.opentelemetry.sdk.autoconfigure.SdkAutoconfigureAccess;
14+
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
15+
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
16+
import io.opentelemetry.sdk.resources.Resource;
17+
import java.util.Collections;
18+
import java.util.HashMap;
19+
import java.util.Map;
20+
import java.util.Set;
21+
import java.util.stream.Stream;
22+
import javax.annotation.Nullable;
23+
import org.assertj.core.util.Strings;
24+
import org.junit.jupiter.api.DynamicTest;
25+
import org.junit.jupiter.api.TestFactory;
26+
27+
public class ResourceProviderPropertiesCustomizerTest {
28+
29+
public static final class Provider implements ResourceProvider {
30+
@Override
31+
public Resource createResource(ConfigProperties config) {
32+
return Resource.create(Attributes.of(AttributeKey.stringKey("key"), "value"));
33+
}
34+
}
35+
36+
private static class EnabledTestCase {
37+
private final String name;
38+
private final boolean result;
39+
private final Set<String> enabledProviders;
40+
private final Set<String> disabledProviders;
41+
private final Boolean explicitEnabled;
42+
43+
private EnabledTestCase(
44+
String name,
45+
boolean result,
46+
Set<String> enabledProviders,
47+
Set<String> disabledProviders,
48+
@Nullable Boolean explicitEnabled) {
49+
this.name = name;
50+
this.result = result;
51+
this.enabledProviders = enabledProviders;
52+
this.disabledProviders = disabledProviders;
53+
this.explicitEnabled = explicitEnabled;
54+
}
55+
}
56+
57+
@SuppressWarnings("BooleanParameter")
58+
@TestFactory
59+
Stream<DynamicTest> enabledTestCases() {
60+
String className =
61+
"io.opentelemetry.javaagent.tooling.config.ResourceProviderPropertiesCustomizerTest$Provider";
62+
return Stream.of(
63+
new EnabledTestCase(
64+
"explicitEnabled", true, Collections.emptySet(), Collections.emptySet(), true),
65+
new EnabledTestCase(
66+
"explicitEnabledFalse",
67+
false,
68+
Collections.emptySet(),
69+
Collections.emptySet(),
70+
false),
71+
new EnabledTestCase(
72+
"enabledProvidersEmpty",
73+
false,
74+
Collections.emptySet(),
75+
Collections.emptySet(),
76+
null),
77+
new EnabledTestCase(
78+
"enabledProvidersContains",
79+
true,
80+
Collections.singleton(className),
81+
Collections.emptySet(),
82+
null),
83+
new EnabledTestCase(
84+
"enabledProvidersNotContains",
85+
false,
86+
Collections.singleton("otherClassName"),
87+
Collections.emptySet(),
88+
null),
89+
new EnabledTestCase(
90+
"disabledProvidersContains",
91+
false,
92+
Collections.emptySet(),
93+
Collections.singleton(className),
94+
null),
95+
new EnabledTestCase(
96+
"disabledProvidersNotContains",
97+
false,
98+
Collections.emptySet(),
99+
Collections.singleton("otherClassName"),
100+
null),
101+
new EnabledTestCase(
102+
"defaultEnabledFalse", false, Collections.emptySet(), Collections.emptySet(), null))
103+
.map(
104+
tc ->
105+
DynamicTest.dynamicTest(
106+
tc.name,
107+
() -> {
108+
Map<String, String> props = new HashMap<>();
109+
props.put(
110+
ResourceProviderPropertiesCustomizer.ENABLED_KEY,
111+
Strings.join(tc.enabledProviders).with(","));
112+
props.put(
113+
ResourceProviderPropertiesCustomizer.DISABLED_KEY,
114+
Strings.join(tc.disabledProviders).with(","));
115+
116+
if (tc.explicitEnabled != null) {
117+
props.put(
118+
"otel.resource.providers.test.enabled",
119+
Boolean.toString(tc.explicitEnabled));
120+
}
121+
122+
Attributes attributes =
123+
SdkAutoconfigureAccess.getResourceAttributes(
124+
AutoConfiguredOpenTelemetrySdk.builder()
125+
.addPropertiesSupplier(() -> props)
126+
.build());
127+
128+
if (tc.result) {
129+
assertThat(attributes.get(AttributeKey.stringKey("key")))
130+
.isEqualTo("value");
131+
} else {
132+
assertThat(attributes.get(AttributeKey.stringKey("key"))).isNull();
133+
}
134+
}));
135+
}
136+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
io.opentelemetry.javaagent.tooling.config.ResourceProviderPropertiesCustomizerTest$Provider
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent;
7+
8+
import static org.junit.jupiter.api.Assertions.assertFalse;
9+
import static org.junit.jupiter.api.Assertions.assertTrue;
10+
11+
import java.util.ServiceLoader;
12+
import org.junit.jupiter.api.Test;
13+
14+
public class ResourceProviderTest {
15+
16+
@Test
17+
void resourceProviderOrder() throws Exception {
18+
boolean containerProviderFound = false;
19+
boolean awsProviderFound = false;
20+
// verify that aws resource provider is found after the regular container provider
21+
// provider that is found later can overrider values from previous providers
22+
Class<?> resourceProviderClass =
23+
Class.forName(
24+
"io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider",
25+
false,
26+
IntegrationTestUtils.getAgentClassLoader());
27+
for (Object resourceProvider :
28+
ServiceLoader.load(resourceProviderClass, IntegrationTestUtils.getAgentClassLoader())) {
29+
Class<?> clazz = resourceProvider.getClass();
30+
if (clazz
31+
.getName()
32+
.equals("io.opentelemetry.instrumentation.resources.ContainerResourceProvider")) {
33+
containerProviderFound = true;
34+
assertFalse(awsProviderFound);
35+
} else if (clazz.getName().startsWith("io.opentelemetry.contrib.aws.resource.")) {
36+
awsProviderFound = true;
37+
assertTrue(containerProviderFound);
38+
}
39+
}
40+
assertTrue(containerProviderFound);
41+
assertTrue(awsProviderFound);
42+
}
43+
}

0 commit comments

Comments
 (0)