Skip to content

Commit

Permalink
Breakout ResourceHolder from AwsXrayRemoteSamplerProvider
Browse files Browse the repository at this point in the history
ResourceHolder provides generic utility for other components in the awsxray package, and could be more broadly used. In this commit, we are breaking out the ResourceHolder inner class to it's own class, and exposing the functionality of getResource, so that other classes can rely on it.

Related issue: #789
  • Loading branch information
thpierce committed Mar 29, 2023
1 parent a8e426c commit 1e7883c
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 26 deletions.
1 change: 1 addition & 0 deletions aws-xray/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies {
implementation("io.opentelemetry:opentelemetry-semconv")

annotationProcessor("com.google.auto.service:auto-service")
testImplementation("com.google.auto.service:auto-service")
compileOnly("com.google.auto.service:auto-service-annotations")

annotationProcessor("com.google.auto.value:auto-value")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,18 @@
package io.opentelemetry.contrib.awsxray;

import com.google.auto.service.AutoService;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSamplerProvider;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.samplers.Sampler;
import java.util.Map;
import javax.annotation.Nullable;

@AutoService(ConfigurableSamplerProvider.class)
public class AwsXrayRemoteSamplerProvider implements ConfigurableSamplerProvider {

@Override
public Sampler createSampler(ConfigProperties config) {
Resource resource = ResourceHolder.resource;
if (resource == null) {
// Should never be the case in practice.
resource = Resource.getDefault();
}
Resource resource = ResourceHolder.getResource();
AwsXrayRemoteSamplerBuilder builder = AwsXrayRemoteSampler.newBuilder(resource);

Map<String, String> params = config.getMap("otel.traces.sampler.arg");
Expand All @@ -41,22 +34,4 @@ public Sampler createSampler(ConfigProperties config) {
public String getName() {
return "xray";
}

// Currently the only way to read the Resource from autoconfiguration. Best would be if the SPI
// could return a Function<SamplerFactoryArgs, Sampler> where SamplerFactoryArgs has
// SDK-constructed components like Resource and Clock.
@AutoService(AutoConfigurationCustomizerProvider.class)
public static final class ResourceHolder implements AutoConfigurationCustomizerProvider {

@Nullable static volatile Resource resource;

@Override
public void customize(AutoConfigurationCustomizer autoConfiguration) {
autoConfiguration.addResourceCustomizer(
(resource, config) -> {
ResourceHolder.resource = resource;
return resource;
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.awsxray;

import com.google.auto.service.AutoService;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
import io.opentelemetry.sdk.resources.Resource;
import javax.annotation.Nullable;

/**
* Currently the only way to read the Resource from autoconfiguration. Best would be if the SPI
* could return a {@code Function<SamplerFactoryArgs, Sampler>} where SamplerFactoryArgs has
* SDK-constructed components like Resource and Clock.
*/
@AutoService(AutoConfigurationCustomizerProvider.class)
public final class ResourceHolder implements AutoConfigurationCustomizerProvider {

@Nullable static volatile Resource resource;

@Override
public void customize(AutoConfigurationCustomizer autoConfiguration) {
autoConfiguration.addResourceCustomizer(
(resource, config) -> {
ResourceHolder.resource = resource;
return resource;
});
}

/**
* Returns held resource, unless resource is null, in which case {@link Resource#getDefault()} is
* returned. This should not happen in practice, as {@link #customize} should be automatically
* run, populating {@link #resource}.
*/
public static Resource getResource() {
Resource resourceReference = resource;
if (resourceReference == null) {
// Should never be the case in practice.
resourceReference = Resource.getDefault();
}
return resourceReference;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.contrib.awsxray;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.resources.Resource;
import java.util.function.BiFunction;
import org.junit.jupiter.api.Test;

/**
* Unit tests for {@link ResourceHolder}. Note that there isn't a great way to test the "default"
* fallback logic, as when the test suite is run, the customize logic appears to be invoked.
*/
public class ResourceHolderTest {

@Test
@SuppressWarnings("unchecked")
public void testCustomized() {
Resource customizedResource = Resource.create(Attributes.empty());
AutoConfigurationCustomizer mockCustomizer = mock(AutoConfigurationCustomizer.class);
ResourceHolder resourceHolder = new ResourceHolder();
when(mockCustomizer.addResourceCustomizer(any()))
.thenAnswer(
invocation -> {
BiFunction<Resource, ConfigProperties, Resource> biFunction =
(BiFunction<Resource, ConfigProperties, Resource>) invocation.getArguments()[0];
assertThat(biFunction.apply(customizedResource, null)).isEqualTo(customizedResource);
return mockCustomizer;
});
resourceHolder.customize(mockCustomizer);
assertThat(ResourceHolder.getResource()).isEqualTo(customizedResource);
}
}

0 comments on commit 1e7883c

Please sign in to comment.