Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…y-java into sampler-factory
  • Loading branch information
jack-berg committed Aug 24, 2023
2 parents 458b5e0 + 4fdd2ed commit 886792b
Show file tree
Hide file tree
Showing 8 changed files with 370 additions and 3 deletions.
2 changes: 1 addition & 1 deletion dependencyManagement/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ val DEPENDENCY_BOMS = listOf(
"com.fasterxml.jackson:jackson-bom:2.15.2",
"com.google.guava:guava-bom:32.1.2-jre",
"com.google.protobuf:protobuf-bom:3.24.1",
"com.linecorp.armeria:armeria-bom:1.25.0",
"com.linecorp.armeria:armeria-bom:1.25.1",
"com.squareup.okhttp3:okhttp-bom:4.11.0",
"com.squareup.okio:okio-bom:3.5.0", // applies to transitive dependencies of okhttp
"io.grpc:grpc-bom:1.57.2",
Expand Down
1 change: 1 addition & 0 deletions sdk-extensions/incubator/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down
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());
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
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;
Expand Down Expand Up @@ -42,12 +43,16 @@ public OpenTelemetrySdk create(
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()));
}

Expand All @@ -57,12 +62,11 @@ public OpenTelemetrySdk create(
closeables,
TracerProviderFactory.getInstance()
.create(model.getTracerProvider(), spiHelper, closeables)
.setResource(resource)
.build()));
}

// TODO(jack-berg): add support for meter provider
// TODO(jack-berg): add support for propagators
// TODO(jack-berg): add support for resource
// TODO(jack-berg): add support for general attribute limits

return FileConfigUtil.addAndReturn(closeables, builder.build());
Expand Down
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();
}
}
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());
}
}

0 comments on commit 886792b

Please sign in to comment.