Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

### Extensions

* Stabilize `ServiceInstanceIdResourceProvider` by moving from incubator to autoconfigure module
([#8410](https://github.com/open-telemetry/opentelemetry-java/issues/8410))

## Version 1.65.0 (2026-08-07)

**NOTE:** The `opentelemetry-exporter-zipkin` artifact has stopped being published. It was
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public Resource createResource(ConfigProperties config) {
@Override
public int order() {
// Environment resource takes precedent over all other ResourceProviders except
// ServiceInstanceIdResourceProvider.
// ServiceInstanceIdResourceProvider (which runs at Integer.MAX_VALUE).
return Integer.MAX_VALUE - 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure.resources;

import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
import io.opentelemetry.sdk.autoconfigure.spi.internal.ConditionalResourceProvider;
import io.opentelemetry.sdk.resources.Resource;
import java.util.UUID;

/**
* A {@link ConditionalResourceProvider} for {@code service.instance.id}. It implements {@link
* ConditionalResourceProvider} rather than a plain {@link ResourceProvider} because it depends on
* the attributes discovered by the other providers.
*
* <p>This provider generates a random UUID for {@code service.instance.id} if not already set by
* the user or another resource provider. The value is stable across calls to this provider within
* the same JVM instance.
*
* @since 1.47.0
*/
public final class ServiceInstanceIdResourceProvider implements ConditionalResourceProvider {

public static final AttributeKey<String> SERVICE_INSTANCE_ID =
AttributeKey.stringKey("service.instance.id");

// multiple calls to this resource provider should return the same value
private static final Resource RANDOM =
Resource.create(Attributes.of(SERVICE_INSTANCE_ID, UUID.randomUUID().toString()));

static final int ORDER = Integer.MAX_VALUE;

@Override
public Resource createResource(ConfigProperties config) {
return RANDOM;
}

@Override
public boolean shouldApply(ConfigProperties config, Resource existing) {
return existing.getAttribute(SERVICE_INSTANCE_ID) == null;
}

@Override
public int order() {
// Run after environment resource provider - only set the service instance ID if it
// hasn't been set by any other provider or the user.
return ORDER;
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
io.opentelemetry.sdk.autoconfigure.EnvironmentResourceProvider
io.opentelemetry.sdk.autoconfigure.resources.ServiceInstanceIdResourceProvider
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,23 @@ void customConfigResourceWithDisabledKeys() {
"otel.resource.attributes", "food=cheesecake,drink=juice,animal= ,color=,shape=square");
props.put("otel.resource.disabled-keys", "drink");

assertThat(
ResourceConfiguration.configureResource(
DefaultConfigProperties.create(props, componentLoader),
SpiHelper.create(ResourceConfigurationTest.class.getClassLoader()),
(r, c) -> r))
.isEqualTo(
Resource.getDefault().toBuilder()
.put(stringKey("service.name"), "test-service")
.put("food", "cheesecake")
.put("shape", "square")
.build());
Resource result =
ResourceConfiguration.configureResource(
DefaultConfigProperties.create(props, componentLoader),
SpiHelper.create(ResourceConfigurationTest.class.getClassLoader()),
(r, c) -> r);

// Verify expected attributes are present
assertThat(result.getAttribute(stringKey("service.name"))).isEqualTo("test-service");
assertThat(result.getAttribute(stringKey("food"))).isEqualTo("cheesecake");
assertThat(result.getAttribute(stringKey("shape"))).isEqualTo("square");
// Verify disabled attribute is not present
assertThat(result.getAttribute(stringKey("drink"))).isNull();
// Verify telemetry SDK attributes are present
assertThat(result.getAttribute(stringKey("telemetry.sdk.language"))).isEqualTo("java");
assertThat(result.getAttribute(stringKey("telemetry.sdk.name"))).isEqualTo("opentelemetry");
// Verify service.instance.id is now added by default via ServiceInstanceIdResourceProvider
assertThat(result.getAttribute(stringKey("service.instance.id"))).isNotNull();
}

@ParameterizedTest
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure.resources;

import static org.assertj.core.api.Assertions.assertThat;

import com.google.common.collect.ImmutableMap;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
import io.opentelemetry.sdk.resources.Resource;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

class ServiceInstanceIdResourceProviderTest {

@ParameterizedTest
@MethodSource("createResourceTestCases")
void createResource(String expectedValue, Map<String, String> attributes) {
ServiceInstanceIdResourceProvider provider = new ServiceInstanceIdResourceProvider();
DefaultConfigProperties config = DefaultConfigProperties.createFromMap(Collections.emptyMap());
AttributesBuilder builder = Attributes.builder();
attributes.forEach(builder::put);
Resource existing = Resource.create(builder.build());
Resource resource =
provider.shouldApply(config, existing) ? provider.createResource(config) : Resource.empty();

String actual =
resource.getAttributes().get(ServiceInstanceIdResourceProvider.SERVICE_INSTANCE_ID);
if ("random".equals(expectedValue)) {
assertThat(actual).isNotNull();
} else {
assertThat(actual).isEqualTo(expectedValue);
}
}

static Stream<Arguments> createResourceTestCases() {
return Stream.of(
Arguments.argumentSet(
"user provided service.instance.id",
null,
ImmutableMap.of("service.instance.id", "custom")),
Arguments.argumentSet("random value", "random", Collections.emptyMap()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
* A {@link ConditionalResourceProvider} for {@code service.instance.id}. It implements {@link
* ConditionalResourceProvider} rather than a plain {@link ResourceProvider} because it depends on
* the attributes discovered by the other providers.
*
* @deprecated Use {@link
* io.opentelemetry.sdk.autoconfigure.resources.ServiceInstanceIdResourceProvider} instead. This

Check failure on line 22 in sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/resources/ServiceInstanceIdResourceProvider.java

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, 8)

reference not found

Check failure on line 22 in sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/resources/ServiceInstanceIdResourceProvider.java

View workflow job for this annotation

GitHub Actions / Build (macos-latest, 8)

reference not found

Check failure on line 22 in sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/resources/ServiceInstanceIdResourceProvider.java

View workflow job for this annotation

GitHub Actions / analyze (java)

reference not found
* class will be removed in a future release.
*/
@Deprecated
public final class ServiceInstanceIdResourceProvider implements ConditionalResourceProvider {

public static final AttributeKey<String> SERVICE_INSTANCE_ID =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class ServiceInstanceIdResourceProviderTest {

@ParameterizedTest
@MethodSource("createResourceTestCases")
@SuppressWarnings("OtelDeprecatedApiUsage")
void createResource(String expectedValue, Map<String, String> attributes) {
ServiceInstanceIdResourceProvider provider = new ServiceInstanceIdResourceProvider();
DefaultConfigProperties config = DefaultConfigProperties.createFromMap(Collections.emptyMap());
Expand Down
Loading