io.opentelemetry.sdk.autoconfigure.ResourceConfiguration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of opentelemetry-sdk-extension-autoconfigure Show documentation
Show all versions of opentelemetry-sdk-extension-autoconfigure Show documentation
OpenTelemetry SDK Auto-configuration
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.sdk.autoconfigure;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
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.ResourceProvider;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ConditionalResourceProvider;
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
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.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
/**
* Auto-configuration for the OpenTelemetry {@link Resource}.
*
* @since 1.28.0
*/
public final class ResourceConfiguration {
private static final AttributeKey SERVICE_NAME = AttributeKey.stringKey("service.name");
// Visible for testing
static final String ATTRIBUTE_PROPERTY = "otel.resource.attributes";
static final String SERVICE_NAME_PROPERTY = "otel.service.name";
static final String DISABLED_ATTRIBUTE_KEYS = "otel.experimental.resource.disabled.keys";
/**
* Create a {@link Resource} from the environment. The resource contains attributes parsed from
* environment variables and system property keys {@code otel.resource.attributes} and {@code
* otel.service.name}.
*
* @return the resource.
*/
public static Resource createEnvironmentResource() {
return createEnvironmentResource(DefaultConfigProperties.create(Collections.emptyMap()));
}
/**
* Create a {@link Resource} from the environment. The resource contains attributes parsed from
* environment variables and system property keys {@code otel.resource.attributes} and {@code
* otel.service.name}.
*
* @param config the {@link ConfigProperties} used to obtain resource properties
* @return the resource.
*/
public static Resource createEnvironmentResource(ConfigProperties config) {
AttributesBuilder resourceAttributes = Attributes.builder();
try {
for (Map.Entry entry : config.getMap(ATTRIBUTE_PROPERTY).entrySet()) {
resourceAttributes.put(
entry.getKey(),
// Attributes specified via otel.resource.attributes follow the W3C Baggage spec and
// characters outside the baggage-octet range are percent encoded
// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable
URLDecoder.decode(entry.getValue(), StandardCharsets.UTF_8.displayName()));
}
} catch (UnsupportedEncodingException e) {
// Should not happen since always using standard charset
throw new ConfigurationException("Unable to decode resource attributes.", e);
}
String serviceName = config.getString(SERVICE_NAME_PROPERTY);
if (serviceName != null) {
resourceAttributes.put(SERVICE_NAME, serviceName);
}
return Resource.create(resourceAttributes.build());
}
static Resource configureResource(
ConfigProperties config,
SpiHelper spiHelper,
BiFunction super Resource, ConfigProperties, ? extends Resource> resourceCustomizer) {
Resource result = Resource.getDefault();
Set enabledProviders =
new HashSet<>(config.getList("otel.java.enabled.resource.providers"));
Set 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;
}
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);
return resourceCustomizer.apply(result, config);
}
// visible for testing
static Resource filterAttributes(Resource resource, ConfigProperties configProperties) {
Set disabledKeys = new HashSet<>(configProperties.getList(DISABLED_ATTRIBUTE_KEYS));
ResourceBuilder builder =
resource.toBuilder().removeIf(attributeKey -> disabledKeys.contains(attributeKey.getKey()));
if (resource.getSchemaUrl() != null) {
builder.setSchemaUrl(resource.getSchemaUrl());
}
return builder.build();
}
private ResourceConfiguration() {}
}