-
Notifications
You must be signed in to change notification settings - Fork 861
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Resource configuration factory (#5757)
- Loading branch information
Showing
7 changed files
with
369 additions
and
0 deletions.
There are no files selected for viewing
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
156 changes: 156 additions & 0 deletions
156
.../src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/AttributesFactory.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,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()); | ||
} | ||
}); | ||
} | ||
} |
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
43 changes: 43 additions & 0 deletions
43
...or/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/ResourceFactory.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,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(); | ||
} | ||
} |
100 changes: 100 additions & 0 deletions
100
.../test/java/io/opentelemetry/sdk/extension/incubator/fileconfig/AttributesFactoryTest.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,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()); | ||
} | ||
} |
Oops, something went wrong.