-
Notifications
You must be signed in to change notification settings - Fork 848
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add new ResourceDetector #6250
Closed
Closed
add new ResourceDetector #6250
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
51 changes: 51 additions & 0 deletions
51
...e-spi/src/main/java/io/opentelemetry/sdk/autoconfigure/spi/internal/ResourceDetector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* 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 | ||
default int order() { | ||
return 0; | ||
} | ||
|
||
/** 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; | ||
} | ||
|
||
/** 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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
...ure/src/main/java/io/opentelemetry/sdk/autoconfigure/internal/ResourceDetectorReader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() {} | ||
|
||
@Override | ||
public <T> AttributeBuilder add(AttributeKey<T> key, Function<D, Optional<T>> getter) { | ||
attributeGetters.put((AttributeKey) key, Objects.requireNonNull((Function) getter)); | ||
return this; | ||
} | ||
} | ||
|
||
private final Map<AttributeKey<Object>, Function<D, Optional<?>>> attributeGetters = | ||
new HashMap<>(); | ||
|
||
public ResourceDetectorReader(ResourceDetector<D> resourceDetector) { | ||
this.resourceDetector = resourceDetector; | ||
resourceDetector.registerAttributes(new AttributeBuilder()); | ||
} | ||
|
||
public boolean shouldApply(ConfigProperties config, Resource existing) { | ||
Map<String, String> resourceAttributes = getResourceAttributes(config); | ||
return attributeGetters.keySet().stream() | ||
.allMatch(key -> shouldUpdate(config, existing, key, resourceAttributes)); | ||
} | ||
|
||
public Resource createResource(ConfigProperties config, Resource existing) { | ||
return resourceDetector | ||
.readData(config) | ||
.map( | ||
data -> { | ||
Map<String, String> resourceAttributes = getResourceAttributes(config); | ||
AttributesBuilder builder = Attributes.builder(); | ||
attributeGetters.entrySet().stream() | ||
.filter(e -> shouldUpdate(config, existing, e.getKey(), resourceAttributes)) | ||
.forEach( | ||
e -> | ||
e.getValue() | ||
.apply(data) | ||
.ifPresent(value -> putAttribute(builder, e.getKey(), value))); | ||
return Resource.create(builder.build()); | ||
}) | ||
.orElse(Resource.empty()); | ||
} | ||
|
||
private static <T> void putAttribute(AttributesBuilder builder, AttributeKey<T> key, T value) { | ||
builder.put(key, value); | ||
} | ||
|
||
private static Map<String, String> getResourceAttributes(ConfigProperties config) { | ||
return config.getMap("otel.resource.attributes"); | ||
} | ||
|
||
private static boolean shouldUpdate( | ||
ConfigProperties config, | ||
Resource existing, | ||
AttributeKey<?> key, | ||
Map<String, String> resourceAttributes) { | ||
if (resourceAttributes.containsKey(key.getKey())) { | ||
return false; | ||
} | ||
|
||
Object value = existing.getAttribute(key); | ||
|
||
if (key.getKey().equals("service.name")) { | ||
return config.getString("otel.service.name") == null && "unknown_service:java".equals(value); | ||
} | ||
|
||
return value == null; | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't see the current ResourceProvider design as broken, and can't tell how this would alleviate confusion.
Here's a summary of the toolkit for managing resources today:
OTEL_SERVICE_NAME
andOTEL_RESOURCE_ATTRIBUTES
contribute to the environment resource provider, which runs last. These environment variables can be customized byAutoConfigurationCustomizer#addPropertiesSupplier
,AutoConfigurationCustomizer#addPropertiesCustomizer
.otel.java.disabled.resource.providers
otel.java.enabled.resource.providers
otel.experimental.resource.disabled.keys
AutoConfigurationCustomizer#addResourceCustomizer
Sdk{Signal}ProviderBuilder
, you can further customize it withAutoConfigurationCustomizer#add{Signal}ProviderCustomizer
viaSdk{Signal}ProviderBuilder
'ssetResource
andaddResource
methods.That's quite a long and comprehensive list, with interactions which are hard to reason through for a casual user. I'm very reluctant to add additional complexity unless there is a very strong reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I've learned, there's one idiomatic way how to write resource providers, which is easy to get wrong.
Do the idea is to take complexity away, not to add it.
At the same time, this is not a topic that is blocking any of my current tasks.