Add Resource configuration factory (#5757)
This commit is contained in:
parent
b78145fa3c
commit
4fdd2ed81e
|
@ -28,6 +28,7 @@ dependencies {
|
|||
implementation("com.fasterxml.jackson.core:jackson-databind")
|
||||
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml")
|
||||
implementation(project(":sdk-extensions:autoconfigure"))
|
||||
implementation(project(":semconv"))
|
||||
|
||||
testImplementation(project(":sdk:testing"))
|
||||
testImplementation(project(":sdk-extensions:autoconfigure"))
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.incubator.fileconfig;
|
||||
|
||||
import io.opentelemetry.api.common.AttributeKey;
|
||||
import io.opentelemetry.api.common.AttributesBuilder;
|
||||
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Attributes;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.io.Closeable;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
final class AttributesFactory
|
||||
implements Factory<Attributes, io.opentelemetry.api.common.Attributes> {
|
||||
|
||||
private static final AttributesFactory INSTANCE = new AttributesFactory();
|
||||
|
||||
private AttributesFactory() {}
|
||||
|
||||
static AttributesFactory getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public io.opentelemetry.api.common.Attributes create(
|
||||
@Nullable Attributes model, SpiHelper spiHelper, List<Closeable> closeables) {
|
||||
if (model == null) {
|
||||
return io.opentelemetry.api.common.Attributes.empty();
|
||||
}
|
||||
|
||||
AttributesBuilder builder = io.opentelemetry.api.common.Attributes.builder();
|
||||
|
||||
String serviceName = model.getServiceName();
|
||||
if (serviceName != null) {
|
||||
builder.put(ResourceAttributes.SERVICE_NAME, serviceName);
|
||||
}
|
||||
|
||||
model
|
||||
.getAdditionalProperties()
|
||||
.forEach(
|
||||
(key, value) -> {
|
||||
if (value == null) {
|
||||
throw new ConfigurationException(
|
||||
"Error processing attribute with key \"" + key + "\": unexpected null value");
|
||||
}
|
||||
if (value instanceof String) {
|
||||
builder.put(key, (String) value);
|
||||
return;
|
||||
}
|
||||
if (value instanceof Integer) {
|
||||
builder.put(key, (int) value);
|
||||
return;
|
||||
}
|
||||
if (value instanceof Long) {
|
||||
builder.put(key, (long) value);
|
||||
return;
|
||||
}
|
||||
if (value instanceof Double) {
|
||||
builder.put(key, (double) value);
|
||||
return;
|
||||
}
|
||||
if (value instanceof Float) {
|
||||
builder.put(key, (float) value);
|
||||
return;
|
||||
}
|
||||
if (value instanceof Boolean) {
|
||||
builder.put(key, (boolean) value);
|
||||
return;
|
||||
}
|
||||
if (value instanceof List) {
|
||||
List<?> values = (List<?>) value;
|
||||
if (values.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Object first = values.get(0);
|
||||
if (first instanceof String) {
|
||||
checkAllEntriesOfType(key, values, String.class);
|
||||
builder.put(
|
||||
AttributeKey.stringArrayKey(key),
|
||||
values.stream().map(obj -> (String) obj).toArray(String[]::new));
|
||||
return;
|
||||
}
|
||||
if (first instanceof Long) {
|
||||
checkAllEntriesOfType(key, values, Long.class);
|
||||
builder.put(
|
||||
AttributeKey.longArrayKey(key),
|
||||
values.stream().map(obj -> (long) obj).toArray(Long[]::new));
|
||||
return;
|
||||
}
|
||||
if (first instanceof Integer) {
|
||||
checkAllEntriesOfType(key, values, Integer.class);
|
||||
builder.put(
|
||||
AttributeKey.longArrayKey(key),
|
||||
values.stream().map(obj -> Long.valueOf((int) obj)).toArray(Long[]::new));
|
||||
return;
|
||||
}
|
||||
if (first instanceof Double) {
|
||||
checkAllEntriesOfType(key, values, Double.class);
|
||||
builder.put(
|
||||
AttributeKey.doubleArrayKey(key),
|
||||
values.stream().map(obj -> (double) obj).toArray(Double[]::new));
|
||||
return;
|
||||
}
|
||||
if (first instanceof Float) {
|
||||
checkAllEntriesOfType(key, values, Float.class);
|
||||
builder.put(
|
||||
AttributeKey.doubleArrayKey(key),
|
||||
values.stream()
|
||||
.map(obj -> Double.valueOf((float) obj))
|
||||
.toArray(Double[]::new));
|
||||
return;
|
||||
}
|
||||
if (first instanceof Boolean) {
|
||||
checkAllEntriesOfType(key, values, Boolean.class);
|
||||
builder.put(
|
||||
AttributeKey.booleanArrayKey(key),
|
||||
values.stream().map(obj -> (Boolean) obj).toArray(Boolean[]::new));
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new ConfigurationException(
|
||||
"Error processing attribute with key \""
|
||||
+ key
|
||||
+ "\": unrecognized value type "
|
||||
+ value.getClass().getName());
|
||||
});
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static void checkAllEntriesOfType(String key, List<?> values, Class<?> expectedType) {
|
||||
values.forEach(
|
||||
value -> {
|
||||
if (value == null) {
|
||||
throw new ConfigurationException(
|
||||
"Error processing attribute with key \""
|
||||
+ key
|
||||
+ "\": unexpected null element in value");
|
||||
}
|
||||
if (!expectedType.isAssignableFrom(value.getClass())) {
|
||||
throw new ConfigurationException(
|
||||
"Error processing attribute with key \""
|
||||
+ key
|
||||
+ "\": expected value entries to be of type "
|
||||
+ expectedType
|
||||
+ " but found entry with type "
|
||||
+ value.getClass());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import io.opentelemetry.sdk.OpenTelemetrySdkBuilder;
|
|||
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfiguration;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import java.io.Closeable;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -42,12 +43,16 @@ final class OpenTelemetryConfigurationFactory
|
|||
builder.setPropagators(
|
||||
PropagatorsFactory.getInstance().create(model.getPropagators(), spiHelper, closeables));
|
||||
|
||||
Resource resource =
|
||||
ResourceFactory.getInstance().create(model.getResource(), spiHelper, closeables);
|
||||
|
||||
if (model.getLoggerProvider() != null) {
|
||||
builder.setLoggerProvider(
|
||||
FileConfigUtil.addAndReturn(
|
||||
closeables,
|
||||
LoggerProviderFactory.getInstance()
|
||||
.create(model.getLoggerProvider(), spiHelper, closeables)
|
||||
.setResource(resource)
|
||||
.build()));
|
||||
}
|
||||
|
||||
|
@ -57,6 +62,7 @@ final class OpenTelemetryConfigurationFactory
|
|||
closeables,
|
||||
TracerProviderFactory.getInstance()
|
||||
.create(model.getTracerProvider(), spiHelper, closeables)
|
||||
.setResource(resource)
|
||||
.build()));
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.incubator.fileconfig;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Attributes;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Resource;
|
||||
import io.opentelemetry.sdk.resources.ResourceBuilder;
|
||||
import java.io.Closeable;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
final class ResourceFactory implements Factory<Resource, io.opentelemetry.sdk.resources.Resource> {
|
||||
|
||||
private static final ResourceFactory INSTANCE = new ResourceFactory();
|
||||
|
||||
private ResourceFactory() {}
|
||||
|
||||
static ResourceFactory getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public io.opentelemetry.sdk.resources.Resource create(
|
||||
@Nullable Resource model, SpiHelper spiHelper, List<Closeable> closeables) {
|
||||
if (model == null) {
|
||||
return io.opentelemetry.sdk.resources.Resource.getDefault();
|
||||
}
|
||||
|
||||
ResourceBuilder builder = io.opentelemetry.sdk.resources.Resource.getDefault().toBuilder();
|
||||
|
||||
Attributes attributesModel = model.getAttributes();
|
||||
if (attributesModel != null) {
|
||||
builder.putAll(
|
||||
AttributesFactory.getInstance().create(attributesModel, spiHelper, closeables));
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.incubator.fileconfig;
|
||||
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Attributes;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
class AttributesFactoryTest {
|
||||
|
||||
@Test
|
||||
void create_Null() {
|
||||
assertThat(
|
||||
AttributesFactory.getInstance()
|
||||
.create(null, mock(SpiHelper.class), Collections.emptyList()))
|
||||
.isEqualTo(io.opentelemetry.api.common.Attributes.empty());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("invalidAttributes")
|
||||
void create_InvalidAttributes(Attributes model, String expectedMessage) {
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
AttributesFactory.getInstance()
|
||||
.create(model, mock(SpiHelper.class), Collections.emptyList()))
|
||||
.isInstanceOf(ConfigurationException.class)
|
||||
.hasMessageContaining(expectedMessage);
|
||||
}
|
||||
|
||||
private static Stream<Arguments> invalidAttributes() {
|
||||
return Stream.of(
|
||||
Arguments.of(
|
||||
new Attributes().withAdditionalProperty("key", null),
|
||||
"Error processing attribute with key \"key\": unexpected null value"),
|
||||
Arguments.of(
|
||||
new Attributes().withAdditionalProperty("key", new Object()),
|
||||
"Error processing attribute with key \"key\": unrecognized value type java.lang.Object"),
|
||||
Arguments.of(
|
||||
new Attributes().withAdditionalProperty("key", Arrays.asList(1L, 1)),
|
||||
"Error processing attribute with key \"key\": expected value entries to be of type class java.lang.Long but found entry with type class java.lang.Integer"),
|
||||
Arguments.of(
|
||||
new Attributes().withAdditionalProperty("key", Arrays.asList(1L, null)),
|
||||
"Error processing attribute with key \"key\": unexpected null element in value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void create() {
|
||||
assertThat(
|
||||
AttributesFactory.getInstance()
|
||||
.create(
|
||||
new Attributes()
|
||||
.withServiceName("my-service")
|
||||
.withAdditionalProperty("strKey", "val")
|
||||
.withAdditionalProperty("longKey", 1L)
|
||||
.withAdditionalProperty("intKey", 2)
|
||||
.withAdditionalProperty("doubleKey", 1.0d)
|
||||
.withAdditionalProperty("floatKey", 2.0f)
|
||||
.withAdditionalProperty("boolKey", true)
|
||||
.withAdditionalProperty("strArrKey", Arrays.asList("val1", "val2"))
|
||||
.withAdditionalProperty("longArrKey", Arrays.asList(1L, 2L))
|
||||
.withAdditionalProperty("intArrKey", Arrays.asList(1, 2))
|
||||
.withAdditionalProperty("doubleArrKey", Arrays.asList(1.0d, 2.0d))
|
||||
.withAdditionalProperty("floatArrKey", Arrays.asList(1.0f, 2.0f))
|
||||
.withAdditionalProperty("boolArrKey", Arrays.asList(true, false))
|
||||
.withAdditionalProperty("emptyArrKey", Collections.emptyList()),
|
||||
mock(SpiHelper.class),
|
||||
Collections.emptyList()))
|
||||
.isEqualTo(
|
||||
io.opentelemetry.api.common.Attributes.builder()
|
||||
.put(ResourceAttributes.SERVICE_NAME, "my-service")
|
||||
.put("strKey", "val")
|
||||
.put("longKey", 1L)
|
||||
.put("intKey", 2)
|
||||
.put("doubleKey", 1.0d)
|
||||
.put("floatKey", 2.0f)
|
||||
.put("boolKey", true)
|
||||
.put("strArrKey", "val1", "val2")
|
||||
.put("longArrKey", 1L, 2L)
|
||||
.put("intArrKey", 1, 2)
|
||||
.put("doubleArrKey", 1.0d, 2.0d)
|
||||
.put("floatArrKey", 1.0f, 2.0f)
|
||||
.put("boolArrKey", true, false)
|
||||
.build());
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import io.opentelemetry.internal.testing.CleanupExtension;
|
|||
import io.opentelemetry.sdk.OpenTelemetrySdk;
|
||||
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Attributes;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchLogRecordProcessor;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.BatchSpanProcessor;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordExporter;
|
||||
|
@ -29,6 +30,7 @@ import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRec
|
|||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LoggerProvider;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfiguration;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Otlp;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Resource;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanExporter;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanProcessor;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProvider;
|
||||
|
@ -36,6 +38,7 @@ import io.opentelemetry.sdk.logs.LogLimits;
|
|||
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
|
||||
import io.opentelemetry.sdk.trace.SdkTracerProvider;
|
||||
import io.opentelemetry.sdk.trace.SpanLimits;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -108,6 +111,11 @@ class OpenTelemetryConfigurationFactoryTest {
|
|||
@Test
|
||||
void create_Configured() {
|
||||
List<Closeable> closeables = new ArrayList<>();
|
||||
io.opentelemetry.sdk.resources.Resource expectedResource =
|
||||
io.opentelemetry.sdk.resources.Resource.getDefault().toBuilder()
|
||||
.put(ResourceAttributes.SERVICE_NAME, "my-service")
|
||||
.put("key", "val")
|
||||
.build();
|
||||
OpenTelemetrySdk expectedSdk =
|
||||
OpenTelemetrySdk.builder()
|
||||
.setPropagators(
|
||||
|
@ -121,6 +129,7 @@ class OpenTelemetryConfigurationFactoryTest {
|
|||
JaegerPropagator.getInstance())))
|
||||
.setLoggerProvider(
|
||||
SdkLoggerProvider.builder()
|
||||
.setResource(expectedResource)
|
||||
.setLogLimits(
|
||||
() ->
|
||||
LogLimits.builder()
|
||||
|
@ -134,6 +143,7 @@ class OpenTelemetryConfigurationFactoryTest {
|
|||
.build())
|
||||
.setTracerProvider(
|
||||
SdkTracerProvider.builder()
|
||||
.setResource(expectedResource)
|
||||
.setSpanLimits(
|
||||
SpanLimits.builder()
|
||||
.setMaxNumberOfAttributes(1)
|
||||
|
@ -159,6 +169,12 @@ class OpenTelemetryConfigurationFactoryTest {
|
|||
.withPropagators(
|
||||
Arrays.asList(
|
||||
"tracecontext", "baggage", "ottrace", "b3multi", "b3", "jaeger"))
|
||||
.withResource(
|
||||
new Resource()
|
||||
.withAttributes(
|
||||
new Attributes()
|
||||
.withServiceName("my-service")
|
||||
.withAdditionalProperty("key", "val")))
|
||||
.withLoggerProvider(
|
||||
new LoggerProvider()
|
||||
.withLimits(
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.sdk.extension.incubator.fileconfig;
|
||||
|
||||
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Attributes;
|
||||
import io.opentelemetry.sdk.resources.Resource;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.util.Collections;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ResourceFactoryTest {
|
||||
|
||||
@Test
|
||||
void create_Null() {
|
||||
assertThat(
|
||||
ResourceFactory.getInstance()
|
||||
.create(null, mock(SpiHelper.class), Collections.emptyList()))
|
||||
.isEqualTo(Resource.getDefault());
|
||||
}
|
||||
|
||||
@Test
|
||||
void create() {
|
||||
assertThat(
|
||||
ResourceFactory.getInstance()
|
||||
.create(
|
||||
new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model
|
||||
.Resource()
|
||||
.withAttributes(
|
||||
new Attributes()
|
||||
.withServiceName("my-service")
|
||||
.withAdditionalProperty("key", "val")),
|
||||
mock(SpiHelper.class),
|
||||
Collections.emptyList()))
|
||||
.isEqualTo(
|
||||
Resource.getDefault().toBuilder()
|
||||
.put(ResourceAttributes.SERVICE_NAME, "my-service")
|
||||
.put("key", "val")
|
||||
.build());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue