Skip to content

Commit

Permalink
add new ResourceDetector
Browse files Browse the repository at this point in the history
  • Loading branch information
zeitlinger committed Feb 26, 2024
1 parent 1d4a2f4 commit 235c03f
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure.spi.internal;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
import java.util.Optional;
import java.util.function.Function;

public interface ResourceDetector<D> extends Ordered {
/** Read the data for the resource attributes. */
Optional<D> readData(ConfigProperties config);

/** Registers the attributes that this resource detector can provide. */
void registerAttributes(Builder<D> builder);

/** Greater order means lower priority. The default order is 0. */
@Override
int order();

/** Returns the name of this resource detector. */
String name();

/**
* Returns whether this resource detector is enabled by default. If not, it will only be used if
* explicitly enabled in the configuration.
*/
default boolean defaultEnabled() {
return true;

Check warning on line 33 in sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ResourceDetector.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ResourceDetector.java#L33

Added line #L33 was not covered by tests
}

/** A builder for registering attributes that a resource detector can provide. */
interface Builder<D> {
/**
* Adds an attribute to the resource.
*
* @param key the attribute key
* @param getter a function that returns the value of the attribute from the data that is read
* by {@link ResourceDetector#readData(ConfigProperties)}
* @return this builder
* @param <T> the type of the attribute
*/
<T> Builder<D> add(AttributeKey<T> key, Function<D, Optional<T>> getter);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,24 @@
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.sdk.autoconfigure.internal.ResourceDetectorReader;
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
import io.opentelemetry.sdk.autoconfigure.spi.Ordered;
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ConditionalResourceProvider;
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ResourceDetector;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.resources.ResourceBuilder;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
Expand Down Expand Up @@ -81,6 +86,7 @@ public static Resource createEnvironmentResource(ConfigProperties config) {
return Resource.create(resourceAttributes.build());
}

@SuppressWarnings({"rawtypes", "unchecked"})
static Resource configureResource(
ConfigProperties config,
SpiHelper spiHelper,
Expand All @@ -91,19 +97,39 @@ static Resource configureResource(
new HashSet<>(config.getList("otel.java.enabled.resource.providers"));
Set<String> disabledProviders =
new HashSet<>(config.getList("otel.java.disabled.resource.providers"));
for (ResourceProvider resourceProvider : spiHelper.loadOrdered(ResourceProvider.class)) {
if (!enabledProviders.isEmpty()
&& !enabledProviders.contains(resourceProvider.getClass().getName())) {
continue;
List<Ordered> providers = (List) spiHelper.load(ResourceProvider.class);
providers.addAll(spiHelper.load(ResourceDetector.class));
providers.sort(Comparator.comparingInt(Ordered::order));
for (Ordered ordered : providers) {
if (ordered instanceof ResourceProvider) {
ResourceProvider provider = (ResourceProvider) ordered;

if (!enabledProviders.isEmpty()
&& !enabledProviders.contains(provider.getClass().getName())) {
continue;
}
if (disabledProviders.contains(provider.getClass().getName())) {
continue;
}
if (provider instanceof ConditionalResourceProvider
&& !((ConditionalResourceProvider) provider).shouldApply(config, result)) {
continue;
}
result = result.merge(provider.createResource(config));
} else {
ResourceDetector<Object> detector = (ResourceDetector<Object>) ordered;

Check warning on line 120 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java#L120

Added line #L120 was not covered by tests

String key = String.format("otel.resource.provider.%s.enabled", detector.name());

Check warning on line 122 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java#L122

Added line #L122 was not covered by tests
if (!config.getBoolean(key, detector.defaultEnabled())) {
continue;

Check warning on line 124 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java#L124

Added line #L124 was not covered by tests
}

ResourceDetectorReader<Object> reader = new ResourceDetectorReader<>(detector);

Check warning on line 127 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java#L127

Added line #L127 was not covered by tests

if (reader.shouldApply(config, result)) {
result = result.merge(reader.createResource(config, result));

Check warning on line 130 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/ResourceConfiguration.java#L130

Added line #L130 was not covered by tests
}
}
if (disabledProviders.contains(resourceProvider.getClass().getName())) {
continue;
}
if (resourceProvider instanceof ConditionalResourceProvider
&& !((ConditionalResourceProvider) resourceProvider).shouldApply(config, result)) {
continue;
}
result = result.merge(resourceProvider.createResource(config));
}

result = filterAttributes(result, config);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure.internal;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ResourceDetector;
import io.opentelemetry.sdk.resources.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;

@SuppressWarnings({"unchecked", "rawtypes"})
public final class ResourceDetectorReader<D> {

private final ResourceDetector<D> resourceDetector;

public class AttributeBuilder implements ResourceDetector.Builder<D> {

private AttributeBuilder() {}

Check warning on line 27 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L27

Added line #L27 was not covered by tests

@Override
public <T> AttributeBuilder add(AttributeKey<T> key, Function<D, Optional<T>> getter) {
attributeGetters.put((AttributeKey) key, Objects.requireNonNull((Function) getter));
return this;

Check warning on line 32 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L31-L32

Added lines #L31 - L32 were not covered by tests
}
}

private final Map<AttributeKey<Object>, Function<D, Optional<?>>> attributeGetters =

Check warning on line 36 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L36

Added line #L36 was not covered by tests
new HashMap<>();

public ResourceDetectorReader(ResourceDetector<D> resourceDetector) {
this.resourceDetector = resourceDetector;
resourceDetector.registerAttributes(new AttributeBuilder());
}

Check warning on line 42 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L39-L42

Added lines #L39 - L42 were not covered by tests

public boolean shouldApply(ConfigProperties config, Resource existing) {
Map<String, String> resourceAttributes = getResourceAttributes(config);
return attributeGetters.keySet().stream()
.allMatch(key -> shouldUpdate(config, existing, key, resourceAttributes));

Check warning on line 47 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L45-L47

Added lines #L45 - L47 were not covered by tests
}

public Resource createResource(ConfigProperties config, Resource existing) {
return resourceDetector
.readData(config)
.map(

Check warning on line 53 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L51-L53

Added lines #L51 - L53 were not covered by tests
data -> {
Map<String, String> resourceAttributes = getResourceAttributes(config);
AttributesBuilder builder = Attributes.builder();
attributeGetters.entrySet().stream()
.filter(e -> shouldUpdate(config, existing, e.getKey(), resourceAttributes))
.forEach(

Check warning on line 59 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L55-L59

Added lines #L55 - L59 were not covered by tests
e ->
e.getValue()
.apply(data)
.ifPresent(value -> putAttribute(builder, e.getKey(), value)));
return Resource.create(builder.build());

Check warning on line 64 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L61-L64

Added lines #L61 - L64 were not covered by tests
})
.orElse(Resource.empty());

Check warning on line 66 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L66

Added line #L66 was not covered by tests
}

private static <T> void putAttribute(AttributesBuilder builder, AttributeKey<T> key, T value) {
builder.put(key, value);
}

Check warning on line 71 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L70-L71

Added lines #L70 - L71 were not covered by tests

private static Map<String, String> getResourceAttributes(ConfigProperties config) {
return config.getMap("otel.resource.attributes");

Check warning on line 74 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L74

Added line #L74 was not covered by tests
}

private static boolean shouldUpdate(
ConfigProperties config,
Resource existing,
AttributeKey<?> key,
Map<String, String> resourceAttributes) {
if (resourceAttributes.containsKey(key.getKey())) {
return false;

Check warning on line 83 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L83

Added line #L83 was not covered by tests
}

Object value = existing.getAttribute(key);

Check warning on line 86 in sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/autoconfigure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java#L86

Added line #L86 was not covered by tests

if (key.getKey().equals("service.name")) {
return config.getString("otel.service.name") == null && "unknown_service:java".equals(value);
}

return value == null;
}
}

0 comments on commit 235c03f

Please sign in to comment.