Skip to content
Merged
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ Extensions to the OpenTelemetry SDK.
| [SDK Autoconfigure](./sdk-extensions/autoconfigure) | Autoconfigure OpenTelemetry SDK from env vars, system properties, and SPI | `opentelemetry-sdk-extension-autoconfigure` | <!--VERSION_STABLE-->1.68.0<!--/VERSION_STABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure) |
| [SDK Autoconfigure SPI](./sdk-extensions/autoconfigure-spi) | Service Provider Interface (SPI) definitions for autoconfigure | `opentelemetry-sdk-extension-autoconfigure-spi` | <!--VERSION_STABLE-->1.68.0<!--/VERSION_STABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure-spi) |
| [SDK Declarative Config](./sdk-extensions/declarative-config) | Declarative config implementation for YAML-based SDK configuration | `opentelemetry-sdk-extension-declarative-config` | <!--VERSION_UNSTABLE-->1.68.0-alpha<!--/VERSION_UNSTABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-sdk-extension-declarative-config.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-declarative-config) |
| [SDK Declarative Config Jackson 2 Mapper](./sdk-extensions/declarative-config-jackson2) | Jackson 2 model mapper for declarative config | `opentelemetry-sdk-extension-declarative-config-jackson2` | TODO | TODO |
| [SDK Declarative Config SnakeYAML Engine 2 Parser](./sdk-extensions/declarative-config-snakeyaml-engine2) | SnakeYAML Engine 2 YAML parser for declarative config | `opentelemetry-sdk-extension-declarative-config-snakeyaml-engine2` | TODO | TODO |
| [SDK Jaeger Remote Sampler Extension](./sdk-extensions/jaeger-remote-sampler) | Sampler which obtains sampling configuration from remote Jaeger server | `opentelemetry-sdk-extension-jaeger-remote-sampler` | <!--VERSION_STABLE-->1.68.0<!--/VERSION_STABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-sdk-extension-jaeger-remote-sampler.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-jaeger-remote-sampler) |
| [SDK Incubator](./sdk-extensions/incubator) | SDK incubator, including YAML based view configuration, LeakDetectingSpanProcessor | `opentelemetry-sdk-extension-incubator` | <!--VERSION_UNSTABLE-->1.68.0-alpha<!--/VERSION_UNSTABLE--> | [![Javadocs](https://www.javadoc.io/badge/io.opentelemetry/opentelemetry-sdk-extension-incubator.svg)](https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-sdk-extension-incubator) |
</details>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class NoSharedInternalCodeTest {
"opentelemetry-sdk-trace",
"opentelemetry-sdk-extension-autoconfigure",
"opentelemetry-sdk-extension-declarative-config",
"opentelemetry-sdk-extension-declarative-config-jackson2",
"opentelemetry-sdk-extension-declarative-config-snakeyaml-engine2",
"opentelemetry-sdk-extension-incubator",
"opentelemetry-sdk-extension-jaeger-remote-sampler",
"opentelemetry-exporter-otlp",
Expand Down
4 changes: 3 additions & 1 deletion integration-tests/osgi/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -285,14 +285,16 @@ val autoconfigureSuiteTask = registerOsgiSuite(
}

// Suite: autoconfigure + declarative-config. Same as above but with declarative-config on the
// classpath, additionally exercising declarative-config bundle OSGi metadata.
// classpath, additionally exercising its SnakeYAML parser and Jackson mapper OSGi metadata.
val autoconfigureDeclarativeConfigSuiteTask = registerOsgiSuite(
"autoconfigureDeclarativeConfig",
extraRunrequires = listOf(
"opentelemetry-exporter-sender-jdk",
"opentelemetry-exporter-otlp",
"opentelemetry-extension-trace-propagators",
"opentelemetry-sdk-extension-declarative-config",
"opentelemetry-sdk-extension-declarative-config-jackson2",
"opentelemetry-sdk-extension-declarative-config-snakeyaml-engine2",
),
serviceLoaderProvides = listOf(
"io.opentelemetry.sdk.autoconfigure.declarativeconfig.DeclarativeConfigurationCustomizerProvider",
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.autoconfigure.spi.internal;

import io.opentelemetry.api.config.DeclarativeConfigException;
import java.util.Map;
import javax.annotation.Nullable;

/**
* Converts parsed configuration values to declarative configuration models and generic maps.
*
* <p>Implementations must preserve the models' mapping semantics, including extension properties
* and null values.
*
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
public interface DeclarativeConfigurationMapper {

/**
* Convert a value to an instance of {@code targetType}.
*
* @param value the value to convert
* @param targetType the target type
* @param <T> the target type
* @return the converted value
* @throws DeclarativeConfigException if the value cannot be converted to {@code targetType}
*/
<T> T convert(Object value, Class<T> targetType);
Comment thread
jack-berg marked this conversation as resolved.
Resolved

/**
* Convert a model or parsed configuration value to a map with string keys.
*
* @param value the value to convert
* @return the converted map, or null if the input value is null
* @throws DeclarativeConfigException if the value cannot be converted to a map
*/
@Nullable
Map<String, Object> toMap(Object value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure.spi.internal;

import io.opentelemetry.api.config.DeclarativeConfigException;
import java.io.InputStream;
import java.util.Map;

/**
* Parses a declarative configuration YAML stream into generic Java objects.
*
* <p>Implementations must apply environment variable and system property substitution according to
* the OpenTelemetry Configuration Data Model specification. Substitution is performed on scalar
* values, not mapping keys. For unquoted scalar values, substituted text must be parsed using the
* same YAML scalar rules as the original text.
*
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
* at any time.
*/
public interface DeclarativeConfigurationYamlParser {

/**
* Parse a YAML stream.
*
* @param configuration the YAML input stream
* @param environmentVariables environment variables used for substitution
* @param systemProperties system properties used for substitution
* @return the parsed configuration
* @throws DeclarativeConfigException if the YAML cannot be parsed
*/
Object parse(
InputStream configuration,
Map<String, String> environmentVariables,
Map<Object, Object> systemProperties);
}
9 changes: 9 additions & 0 deletions sdk-extensions/declarative-config-jackson2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Declarative Configuration Jackson 2 Mapper

This extension provides a Jackson 2 implementation of the `DeclarativeConfigurationMapper` SPI.
It is included as a runtime dependency by `opentelemetry-sdk-extension-declarative-config` from
the `opentelemetry-sdk-extension-declarative-config-jackson2` artifact.

Projects using another mapper can exclude this artifact from the declarative-config dependency and
register their own `DeclarativeConfigurationMapper` provider. For example, a project using Jackson 3
can implement the SPI with its Jackson 3 `ObjectMapper`.
17 changes: 17 additions & 0 deletions sdk-extensions/declarative-config-jackson2/build.gradle.kts
Comment thread
jack-berg marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
plugins {
id("otel.java-conventions")
id("otel.publish-conventions")
Comment thread
jack-berg marked this conversation as resolved.
Resolved
id("otel.animalsniffer-conventions")
}

description = "OpenTelemetry SDK Declarative Config Jackson 2 Mapper"
otelJava.moduleName.set("io.opentelemetry.sdk.autoconfigure.declarativeconfig.jackson2")
otelJava.requireSuppressWarningsExplanation.set(false)
otelJava.osgiServiceLoaderProvides.set(listOf(
"io.opentelemetry.sdk.autoconfigure.spi.internal.DeclarativeConfigurationMapper",
))

dependencies {
api(project(":sdk-extensions:autoconfigure-spi"))
implementation("com.fasterxml.jackson.core:jackson-databind")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
otel.release=alpha
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure.declarativeconfig.jackson2.internal;

import com.fasterxml.jackson.core.type.TypeReference;
import io.opentelemetry.api.config.DeclarativeConfigException;
import io.opentelemetry.sdk.autoconfigure.spi.internal.DeclarativeConfigurationMapper;
import java.util.Map;
import javax.annotation.Nullable;

/**
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public final class JacksonDeclarativeConfigurationMapper implements DeclarativeConfigurationMapper {

@Override
public <T> T convert(Object value, Class<T> targetType) {
try {
return JacksonModelMapper.MAPPER.convertValue(value, targetType);
} catch (IllegalArgumentException e) {
throw new DeclarativeConfigException("Unable to convert value to " + targetType, e);
}
}

@Nullable
@Override
public Map<String, Object> toMap(Object value) {
try {
return JacksonModelMapper.MAPPER.convertValue(
value, new TypeReference<Map<String, Object>>() {});
} catch (IllegalArgumentException e) {
throw new DeclarativeConfigException("Unable to convert value to a map", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,32 @@
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure.declarativeconfig.model.internal;
package io.opentelemetry.sdk.autoconfigure.declarativeconfig.jackson2.internal;

import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.Nulls;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
* Canonical {@link ObjectMapper} configuration for parsing declarative configuration YAML. {@link
* io.opentelemetry.sdk.autoconfigure.declarativeconfig.DeclarativeConfiguration#MAPPER} delegates
* to this instance.
*
* <p>This class is internal and experimental. Its APIs are unstable and can change at any time. Its
* APIs (or a version of them) may be promoted to the public stable API in the future, but no
* guarantees are made.
* This class is internal and is hence not for public use. Its APIs are unstable and can change at
* any time.
*/
public final class ModelMapper {
public final class JacksonModelMapper {

public static final ObjectMapper MAPPER;

static {
MAPPER =
new ObjectMapper()
// Create empty object instances for keys which are present but have null values
// Create empty object instances for keys which are present but have null values.
.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
// Boxed primitives which are present but have null values should be set to null, rather than
// empty instances
// empty instances.
MAPPER.configOverride(String.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SET));
MAPPER.configOverride(Integer.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SET));
MAPPER.configOverride(Double.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SET));
MAPPER.configOverride(Boolean.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SET));
}

private ModelMapper() {}
private JacksonModelMapper() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.opentelemetry.sdk.autoconfigure.declarativeconfig.jackson2.internal.JacksonDeclarativeConfigurationMapper
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.sdk.autoconfigure.declarativeconfig.jackson2.internal;

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

import io.opentelemetry.api.config.DeclarativeConfigException;
import org.junit.jupiter.api.Test;

class JacksonDeclarativeConfigurationMapperTest {

private final JacksonDeclarativeConfigurationMapper mapper =
new JacksonDeclarativeConfigurationMapper();

@Test
void convertWrapsJacksonException() {
assertThatThrownBy(() -> mapper.convert("not-an-integer", Integer.class))
.isInstanceOf(DeclarativeConfigException.class)
.hasCauseInstanceOf(IllegalArgumentException.class);
}

@Test
void toMapWrapsJacksonException() {
assertThatThrownBy(() -> mapper.toMap(42))
.isInstanceOf(DeclarativeConfigException.class)
.hasCauseInstanceOf(IllegalArgumentException.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SnakeYAML Engine 2 Declarative Configuration Parser

This module provides the default `DeclarativeConfigurationYamlParser` implementation using
SnakeYAML Engine 2. It is included as a runtime dependency by
`opentelemetry-sdk-extension-declarative-config`.

Applications that provide a custom YAML parser can exclude this module from the declarative config
dependency and register their parser with `ServiceLoader`. If neither this adapter nor another
parser provider is present, YAML parsing fails with a `DeclarativeConfigException`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
plugins {
id("otel.java-conventions")
id("otel.publish-conventions")
id("otel.animalsniffer-conventions")
}

description = "OpenTelemetry SDK Declarative Config SnakeYAML Engine 2 Parser"
otelJava.moduleName.set("io.opentelemetry.sdk.autoconfigure.declarativeconfig.snakeyamlengine2")
otelJava.requireSuppressWarningsExplanation.set(false)
otelJava.osgiServiceLoaderProvides.set(listOf(
"io.opentelemetry.sdk.autoconfigure.spi.internal.DeclarativeConfigurationYamlParser",
))

dependencies {
api(project(":sdk-extensions:autoconfigure-spi"))
implementation("org.snakeyaml:snakeyaml-engine")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
otel.release=alpha
Loading
Loading