Skip to content

Commit c1d6671

Browse files
authored
Remove reliance on setting global system env vars in tests (Azure#36253)
* Test improvements * fix * Fix sporadically failing test * Fix sporadically failing test
1 parent 6546507 commit c1d6671

File tree

13 files changed

+211
-271
lines changed

13 files changed

+211
-271
lines changed

sdk/monitor/azure-monitor-opentelemetry-exporter/pom.xml

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@
7676
<artifactId>opentelemetry-sdk-extension-autoconfigure-spi</artifactId>
7777
<version>1.28.0</version> <!-- {x-version-update;io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi;external_dependency} -->
7878
</dependency>
79+
<dependency>
80+
<groupId>io.opentelemetry</groupId>
81+
<artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
82+
<version>1.28.0</version> <!-- {x-version-update;io.opentelemetry:opentelemetry-sdk-extension-autoconfigure;external_dependency} -->
83+
</dependency>
7984
<dependency>
8085
<groupId>com.github.spotbugs</groupId>
8186
<artifactId>spotbugs-annotations</artifactId>
@@ -172,12 +177,6 @@
172177
<version>2.9.0</version> <!-- {x-version-update;io.github.hakky54:logcaptor;external_dependency} -->
173178
<scope>test</scope>
174179
</dependency>
175-
<dependency>
176-
<groupId>uk.org.webcompere</groupId>
177-
<artifactId>system-stubs-jupiter</artifactId>
178-
<version>2.0.2</version> <!-- {x-version-update;uk.org.webcompere:system-stubs-jupiter;external_dependency} -->
179-
<scope>test</scope>
180-
</dependency>
181180
<dependency>
182181
<groupId>com.squareup.okio</groupId>
183182
<artifactId>okio</artifactId>
@@ -201,10 +200,10 @@
201200
<include>io.opentelemetry:opentelemetry-sdk-metrics:[1.28.0]</include> <!-- {x-include-update;io.opentelemetry:opentelemetry-sdk-metrics;external_dependency} -->
202201
<include>io.opentelemetry:opentelemetry-sdk-logs:[1.28.0]</include> <!-- {x-include-update;io.opentelemetry:opentelemetry-sdk-logs;external_dependency} -->
203202
<include>io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:[1.28.0]</include> <!-- {x-include-update;io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi;external_dependency} -->
203+
<include>io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:[1.28.0]</include> <!-- {x-include-update;io.opentelemetry:opentelemetry-sdk-extension-autoconfigure;external_dependency} -->
204204
<include>com.github.spotbugs:spotbugs-annotations:[4.2.2]</include> <!-- {x-include-update;com.github.spotbugs:spotbugs-annotations;external_dependency} -->
205205
<include>org.awaitility:awaitility:[4.2.0]</include> <!-- {x-include-update;org.awaitility:awaitility;external_dependency} -->
206206
<include>io.github.hakky54:logcaptor:[2.9.0]</include> <!-- {x-include-update;io.github.hakky54:logcaptor;external_dependency} -->
207-
<include>uk.org.webcompere:system-stubs-jupiter:[2.0.2]</include> <!-- {x-include-update;uk.org.webcompere:system-stubs-jupiter;external_dependency} -->
208207
<include>com.squareup.okio:okio:[3.3.0]</include> <!-- {x-include-update;com.squareup.okio:okio;external_dependency} -->
209208
</includes>
210209
</bannedDependencies>
@@ -216,12 +215,6 @@
216215
<groupId>org.apache.maven.plugins</groupId>
217216
<artifactId>maven-surefire-plugin</artifactId>
218217
<version>3.1.0</version> <!-- {x-version-update;org.apache.maven.plugins:maven-surefire-plugin;external_dependency} -->
219-
<configuration>
220-
<systemPropertyVariables>
221-
<!-- Parallel runs disabled due to concurrency issues with GlobalOpenTelemetry. -->
222-
<junit.jupiter.execution.parallel.enabled>false</junit.jupiter.execution.parallel.enabled>
223-
</systemPropertyVariables>
224-
</configuration>
225218
</plugin>
226219
</plugins>
227220
</build>

sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/AzureMonitorExporterBuilder.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.azure.monitor.opentelemetry.exporter.implementation.utils.ResourceParser;
3535
import com.azure.monitor.opentelemetry.exporter.implementation.utils.TempDirs;
3636
import com.azure.monitor.opentelemetry.exporter.implementation.utils.VersionGenerator;
37+
import io.opentelemetry.sdk.autoconfigure.ResourceConfiguration;
3738
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
3839
import io.opentelemetry.sdk.metrics.export.MetricExporter;
3940
import io.opentelemetry.sdk.resources.Resource;
@@ -302,9 +303,13 @@ private TelemetryItemExporter initExporterBuilder() {
302303
TempDirs.getSubDir(tempDir, "telemetry"),
303304
pipeline,
304305
LocalStorageStats.noop(),
305-
false));
306+
false),
307+
// TODO (trask) pass in autoconfigure's ConfigProperties after converting this to autoconfigure
308+
ResourceConfiguration.createEnvironmentResource());
306309
} else {
307-
telemetryItemExporter = new TelemetryItemExporter(pipeline, TelemetryPipelineListener.noop());
310+
telemetryItemExporter = new TelemetryItemExporter(
311+
// TODO (trask) pass in autoconfigure's ConfigProperties after converting this to autoconfigure
312+
pipeline, TelemetryPipelineListener.noop(), ResourceConfiguration.createEnvironmentResource());
308313
}
309314
return telemetryItemExporter;
310315
}

sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/pipeline/TelemetryItemExporter.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
import com.azure.monitor.opentelemetry.exporter.implementation.logging.OperationLogger;
1010
import com.azure.monitor.opentelemetry.exporter.implementation.models.ContextTagKeys;
1111
import com.azure.monitor.opentelemetry.exporter.implementation.models.TelemetryItem;
12-
import com.azure.monitor.opentelemetry.exporter.implementation.utils.AksResourceAttributes;
1312
import com.fasterxml.jackson.annotation.JsonInclude;
1413
import com.fasterxml.jackson.core.JsonGenerator;
1514
import com.fasterxml.jackson.core.io.SerializedString;
1615
import com.fasterxml.jackson.databind.ObjectMapper;
1716
import com.fasterxml.jackson.databind.SerializationFeature;
1817
import io.opentelemetry.sdk.common.CompletableResultCode;
18+
import io.opentelemetry.sdk.resources.Resource;
1919

2020
import java.io.IOException;
2121
import java.io.StringWriter;
@@ -66,15 +66,18 @@ private static ObjectMapper createObjectMapper() {
6666

6767
private final TelemetryPipeline telemetryPipeline;
6868
private final TelemetryPipelineListener listener;
69+
// TODO (trask) should this be all the resources?
70+
private final Resource environmentResource;
6971

7072
private final Set<CompletableResultCode> activeExportResults =
7173
Collections.newSetFromMap(new ConcurrentHashMap<>());
7274

7375
// e.g. construct with diagnostic listener and local storage listener
7476
public TelemetryItemExporter(
75-
TelemetryPipeline telemetryPipeline, TelemetryPipelineListener listener) {
77+
TelemetryPipeline telemetryPipeline, TelemetryPipelineListener listener, Resource environmentResource) {
7678
this.telemetryPipeline = telemetryPipeline;
7779
this.listener = listener;
80+
this.environmentResource = environmentResource;
7881
}
7982

8083
public CompletableResultCode send(List<TelemetryItem> telemetryItems) {
@@ -151,7 +154,7 @@ CompletableResultCode internalSendByConnectionStringAndRoleName(
151154
// Don't send _OTELRESOURCE_ custom metric when OTEL_RESOURCE_ATTRIBUTES env var is empty
152155
// Don't send _OTELRESOURCE_ custom metric to Statsbeat yet
153156
// insert _OTELRESOURCE_ at the beginning of each batch
154-
if (!AksResourceAttributes.getOtelResourceAttributes().isEmpty()
157+
if (!environmentResource.getAttributes().isEmpty()
155158
&& !"Statsbeat".equals(telemetryItems.get(0).getName())) {
156159
telemetryItems.add(
157160
0, createOtelResourceMetric(telemetryItems.get(0).getTags(), connectionString));
@@ -166,7 +169,7 @@ CompletableResultCode internalSendByConnectionStringAndRoleName(
166169
return telemetryPipeline.send(byteBuffers, connectionString, listener);
167170
}
168171

169-
private static TelemetryItem createOtelResourceMetric(
172+
private TelemetryItem createOtelResourceMetric(
170173
Map<String, String> existingTags, String connectionString) {
171174
MetricTelemetryBuilder builder = MetricTelemetryBuilder.create(_OTELRESOURCE_, 0);
172175
// this is needed in order to stamp iKey onto the telemetry item during serialization
@@ -181,11 +184,8 @@ private static TelemetryItem createOtelResourceMetric(
181184
ContextTagKeys.AI_INTERNAL_SDK_VERSION.toString(),
182185
existingTags.get(ContextTagKeys.AI_INTERNAL_SDK_VERSION.toString()));
183186

184-
// add attributes from OTEL_RESOURCE_ATTRIBUTES
185-
for (Map.Entry<String, String> entry :
186-
AksResourceAttributes.getOtelResourceAttributes().entrySet()) {
187-
builder.addProperty(entry.getKey(), entry.getValue());
188-
}
187+
environmentResource.getAttributes().forEach((k, v) -> builder.addProperty(k.getKey(), v.toString()));
188+
189189
return builder.build();
190190
}
191191

sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/statsbeat/AttachStatsbeat.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import javax.annotation.Nullable;
1010
import java.util.Collections;
11+
import java.util.function.Function;
1112

1213
class AttachStatsbeat extends BaseStatsbeat {
1314

@@ -20,20 +21,23 @@ class AttachStatsbeat extends BaseStatsbeat {
2021
private static final String WEBSITE_HOME_STAMPNAME = "WEBSITE_HOME_STAMPNAME";
2122

2223
private final CustomDimensions customDimensions;
24+
private final Function<String, String> systemGetenvFn;
25+
2326
private volatile String resourceProviderId;
2427
private volatile MetadataInstanceResponse metadataInstanceResponse;
2528

2629
AttachStatsbeat(CustomDimensions customDimensions) {
2730
super(customDimensions);
2831
this.customDimensions = customDimensions;
29-
resourceProviderId = initResourceProviderId(customDimensions.getResourceProvider(), null);
32+
this.systemGetenvFn = System::getenv;
33+
resourceProviderId = initResourceProviderId(customDimensions.getResourceProvider(), null, systemGetenvFn);
3034
}
3135

3236
@Override
3337
protected void send(TelemetryItemExporter exporter) {
3438
// WEBSITE_HOSTNAME is lazily set in Linux Consumption Plan.
3539
if (resourceProviderId == null || resourceProviderId.isEmpty()) {
36-
resourceProviderId = initResourceProviderId(customDimensions.getResourceProvider(), null);
40+
resourceProviderId = initResourceProviderId(customDimensions.getResourceProvider(), null, systemGetenvFn);
3741
}
3842

3943
StatsbeatTelemetryBuilder telemetryBuilder = createStatsbeatTelemetry(ATTACH_METRIC_NAME, 0);
@@ -54,18 +58,18 @@ MetadataInstanceResponse getMetadataInstanceResponse() {
5458

5559
void updateMetadataInstance(MetadataInstanceResponse response) {
5660
metadataInstanceResponse = response;
57-
resourceProviderId = initResourceProviderId(ResourceProvider.RP_VM, response);
61+
resourceProviderId = initResourceProviderId(ResourceProvider.RP_VM, response, systemGetenvFn);
5862
}
5963

6064
// visible for testing
6165
static String initResourceProviderId(
62-
ResourceProvider resourceProvider, @Nullable MetadataInstanceResponse response) {
66+
ResourceProvider resourceProvider, @Nullable MetadataInstanceResponse response, Function<String, String> envVarFn) {
6367
switch (resourceProvider) {
6468
case RP_APPSVC:
6569
// Linux App Services doesn't have WEBSITE_HOME_STAMPNAME yet. An ask has been submitted.
66-
return System.getenv(WEBSITE_SITE_NAME) + "/" + System.getenv(WEBSITE_HOME_STAMPNAME);
70+
return envVarFn.apply(WEBSITE_SITE_NAME) + "/" + envVarFn.apply(WEBSITE_HOME_STAMPNAME);
6771
case RP_FUNCTIONS:
68-
return System.getenv(WEBSITE_HOSTNAME);
72+
return envVarFn.apply(WEBSITE_HOSTNAME);
6973
case RP_VM:
7074
if (response != null) {
7175
return response.getVmId() + "/" + response.getSubscriptionId();

sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/utils/AksResourceAttributes.java

Lines changed: 14 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,105 +3,62 @@
33

44
package com.azure.monitor.opentelemetry.exporter.implementation.utils;
55

6-
import com.azure.core.util.logging.ClientLogger;
7-
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
8-
9-
import java.io.UnsupportedEncodingException;
10-
import java.net.URLDecoder;
11-
import java.nio.charset.StandardCharsets;
12-
import java.util.Collections;
13-
import java.util.HashMap;
14-
import java.util.Map;
6+
import io.opentelemetry.sdk.resources.Resource;
157

168
import static com.azure.monitor.opentelemetry.exporter.implementation.ResourceAttributes.*;
179

1810
public final class AksResourceAttributes {
1911

2012
private static final String AZURE_AKS = "azure_aks";
2113
private static final String UNKNOWN_SERVICE = "unknown_service";
22-
private static final ClientLogger logger = new ClientLogger(AksResourceAttributes.class);
23-
static Map<String, String> otelResourceAttributes = initOtelResourceAttributes();
24-
25-
// visible for tests only
26-
public static void reloadOtelResourceAttributes() {
27-
otelResourceAttributes = initOtelResourceAttributes();
28-
}
29-
30-
public static Map<String, String> getOtelResourceAttributes() {
31-
return otelResourceAttributes;
32-
}
3314

34-
public static boolean isAks() {
35-
return AZURE_AKS.equals(otelResourceAttributes.get(CLOUD_PLATFORM.toString()));
15+
public static boolean isAks(Resource resource) {
16+
return AZURE_AKS.equals(resource.getAttribute(CLOUD_PLATFORM));
3617
}
3718

3819
// https://github.com/aep-health-and-standards/Telemetry-Collection-Spec/blob/main/OpenTelemetry/resource/resourceMapping.md#aicloudrole-1
39-
public static String getAksRoleName() {
40-
String serviceName = otelResourceAttributes.get(SERVICE_NAME.toString());
20+
public static String getAksRoleName(Resource resource) {
21+
String serviceName = resource.getAttribute(SERVICE_NAME);
4122
if (!Strings.isNullOrEmpty(serviceName) && !serviceName.startsWith(UNKNOWN_SERVICE)) {
4223
return serviceName;
4324
}
44-
String k8sDeploymentName = otelResourceAttributes.get(K8S_DEPLOYMENT_NAME.toString());
25+
String k8sDeploymentName = resource.getAttribute(K8S_DEPLOYMENT_NAME);
4526
if (!Strings.isNullOrEmpty(k8sDeploymentName)) {
4627
return k8sDeploymentName;
4728
}
48-
String k8sReplicaSetName = otelResourceAttributes.get(K8S_REPLICASET_NAME.toString());
29+
String k8sReplicaSetName = resource.getAttribute(K8S_REPLICASET_NAME);
4930
if (!Strings.isNullOrEmpty(k8sReplicaSetName)) {
5031
return k8sReplicaSetName;
5132
}
52-
String k8sStatefulSetName = otelResourceAttributes.get(K8S_STATEFULSET_NAME.toString());
33+
String k8sStatefulSetName = resource.getAttribute(K8S_STATEFULSET_NAME);
5334
if (!Strings.isNullOrEmpty(k8sStatefulSetName)) {
5435
return k8sStatefulSetName;
5536
}
56-
String k8sJobName = otelResourceAttributes.get(K8S_JOB_NAME.toString());
37+
String k8sJobName = resource.getAttribute(K8S_JOB_NAME);
5738
if (!Strings.isNullOrEmpty(k8sJobName)) {
5839
return k8sJobName;
5940
}
60-
String k8sCronJobName = otelResourceAttributes.get(K8S_CRONJOB_NAME.toString());
41+
String k8sCronJobName = resource.getAttribute(K8S_CRONJOB_NAME);
6142
if (!Strings.isNullOrEmpty(k8sCronJobName)) {
6243
return k8sCronJobName;
6344
}
64-
String k8sDaemonSetName = otelResourceAttributes.get(K8S_DAEMONSET_NAME.toString());
45+
String k8sDaemonSetName = resource.getAttribute(K8S_DAEMONSET_NAME);
6546
if (!Strings.isNullOrEmpty(k8sDaemonSetName)) {
6647
return k8sDaemonSetName;
6748
}
6849
return serviceName; // default to "unknown_service:java" when no attribute is available
6950
}
7051

7152
// https://github.com/aep-health-and-standards/Telemetry-Collection-Spec/blob/main/OpenTelemetry/resource/resourceMapping.md#aicloudroleinstance-1
72-
public static String getAksRoleInstance() {
73-
String serviceInstanceId = otelResourceAttributes.get(SERVICE_INSTANCE_ID.toString());
53+
public static String getAksRoleInstance(Resource resource) {
54+
String serviceInstanceId = resource.getAttribute(SERVICE_INSTANCE_ID);
7455
if (!Strings.isNullOrEmpty(serviceInstanceId)) {
7556
return serviceInstanceId;
7657
}
77-
String k8sPodName = otelResourceAttributes.get(K8S_POD_NAME.toString());
58+
String k8sPodName = resource.getAttribute(K8S_POD_NAME);
7859
if (!Strings.isNullOrEmpty(k8sPodName)) {
7960
return k8sPodName;
8061
}
8162
return HostName.get(); // default to hostname
8263
}
83-
84-
// TODO remove manual parsing once SDK 1.28.0 is released
85-
// (see https://github.com/open-telemetry/opentelemetry-java/pull/5554)
86-
// visible for testing
87-
private static Map<String, String> initOtelResourceAttributes() {
88-
Map<String, String> originalMap =
89-
DefaultConfigProperties.create(Collections.emptyMap()).getMap("otel.resource.attributes");
90-
Map<String, String> decodedMap = new HashMap<>(originalMap.size());
91-
// Attributes specified via otel.resource.attributes follow the W3C Baggage spec and
92-
// characters outside the baggage-octet range are percent encoded
93-
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable
94-
originalMap.forEach(
95-
(key, value) -> {
96-
try {
97-
decodedMap.put(key, URLDecoder.decode(value, StandardCharsets.UTF_8.displayName()));
98-
} catch (UnsupportedEncodingException e) {
99-
logger.warning("Fail to decode OTEL_RESOURCE_ATTRIBUTES value.", e);
100-
}
101-
});
102-
return decodedMap;
103-
}
104-
105-
private AksResourceAttributes() {
106-
}
10764
}

sdk/monitor/azure-monitor-opentelemetry-exporter/src/main/java/com/azure/monitor/opentelemetry/exporter/implementation/utils/ResourceParser.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33

44
package com.azure.monitor.opentelemetry.exporter.implementation.utils;
55

6-
import static com.azure.monitor.opentelemetry.exporter.implementation.utils.AksResourceAttributes.getAksRoleInstance;
7-
import static com.azure.monitor.opentelemetry.exporter.implementation.utils.AksResourceAttributes.getAksRoleName;
8-
import static com.azure.monitor.opentelemetry.exporter.implementation.utils.AksResourceAttributes.isAks;
9-
106
import com.azure.core.util.Configuration;
117
import com.azure.monitor.opentelemetry.exporter.implementation.ResourceAttributes;
128
import com.azure.monitor.opentelemetry.exporter.implementation.builders.AbstractTelemetryBuilder;
@@ -24,9 +20,9 @@ public static void updateRoleNameAndInstance(
2420
AbstractTelemetryBuilder builder, Resource resource, Configuration configuration) {
2521

2622
// update AKS role name and role instance
27-
if (isAks()) {
28-
builder.addTag(ContextTagKeys.AI_CLOUD_ROLE.toString(), getAksRoleName());
29-
builder.addTag(ContextTagKeys.AI_CLOUD_ROLE_INSTANCE.toString(), getAksRoleInstance());
23+
if (AksResourceAttributes.isAks(resource)) {
24+
builder.addTag(ContextTagKeys.AI_CLOUD_ROLE.toString(), AksResourceAttributes.getAksRoleName(resource));
25+
builder.addTag(ContextTagKeys.AI_CLOUD_ROLE_INSTANCE.toString(), AksResourceAttributes.getAksRoleInstance(resource));
3026
return;
3127
}
3228

0 commit comments

Comments
 (0)