diff --git a/sdk-extensions/incubator/README.md b/sdk-extensions/incubator/README.md index fbc181470d4..cf5d34fb5d5 100644 --- a/sdk-extensions/incubator/README.md +++ b/sdk-extensions/incubator/README.md @@ -6,99 +6,3 @@ This artifact contains experimental code related to the trace and metric SDKs. > [!WARNING] > Relocated to [opentelemetry-sdk-extensions-declarative-config](../declarative-config) - -## View File Configuration - -> [!WARNING] -> This mechanism is superseded by declarative config, which is now stable (spec and schema at [opentelemetry-configuration](https://github.com/open-telemetry/opentelemetry-configuration)) and will be removed after the 1.62.0 release. Please use [declarative configuration](#declarative-configuration) instead. - -Adds support for file based YAML configuration of Metric SDK Views. - -For example, suppose `/Users/user123/view.yaml` has the following content: - -```yaml -- selector: - instrument_name: my-instrument - instrument_type: COUNTER - instrument_unit: ms - meter_name: my-meter - meter_version: 1.0.0 - meter_schema_url: http://example.com - view: - name: new-instrument-name - description: new-description - aggregation: explicit_bucket_histogram - aggregation_args: - bucket_boundaries: [1.0, 2.0, 5.0] - attribute_keys: - - foo - - bar -``` - -The equivalent view configuration would be: - -``` -SdkMeterProvider.builder() - .registerView( - InstrumentSelector.builder() - .setName("my-instrument") - .setType(InstrumentType.COUNTER) - .setUnit("ms") - .setMeterName("my-meter") - .setMeterVersion("1.0.0") - .setMeterSchemaUrl("http://example.com") - .build(), - View.builder() - .setName("new-instrument") - .setDescription("new-description") - .setAggregation(Aggregation.explicitBucketHistogram(Arrays.asList(1.0, 2.0, 5.0)) - .setAttributesFilter(key -> new HashSet<>(Arrays.asList("foo", "bar")).contains(key)) - .build()); -``` - -If using [autoconfigure](../autoconfigure) with this artifact on your classpath, it will automatically load a list of view config files specified via environment variable or system property: - -| System property | Environment variable | Purpose | -|---------------------------------------|---------------------------------------|------------------------------------------------------| -| otel.experimental.metrics.view-config | OTEL_EXPERIMENTAL_METRICS_VIEW_CONFIG | List of files containing view configuration YAML [1] | - -**[1]** In addition to absolute paths, resources on the classpath packaged with a jar can be loaded. -For example, `otel.experimental.metrics.view-config=classpath:/my-view.yaml` loads the -resource `/my-view.yaml`. - -If not using autoconfigure, a file can be used to configure views as follows: - -``` -SdkMeterProviderBuilder builder = SdkMeterProvider.builder(); -try (FileInputStream fileInputStream = new FileInputStream("/Users/user123/view.yaml")) { - ViewConfig.registerViews(builder, fileInputStream); -} -``` - -The following table describes the set of recognized aggregations: - -| Aggregation | Arguments | -|----------------------------------|--------------------------------------------------------------------------------------------------------------------------------| -| [`default`] | - | -| [`sum`] | - | -| [`last_value`] | - | -| [`drop`] | - | -| [`explicit_bucket_histogram`] | `bucket_boundaries` (optional): List of inclusive upper boundaries for the histogram buckets, in order from lowest to highest. | -| [`exponential_bucket_histogram`] | `max_buckets` (optional): The maximum number of buckets to use for positive or negative recordings. | - -Additional notes on usage: - -- Many view configurations can live in one file. The YAML is parsed as an array of view - configurations. -- At least one selection field is required, but including all is not necessary. Any omitted fields - will result in the default from `InstrumentSelector` being used. -- At least one view field is required, but including all is not required. Any omitted fields will - result in the default from `View` being used. -- Instrument name selection supports the following wildcard characters: `*` matches 0 or more instances of any character; `?` matches exactly one instance of any character. No other advanced selection criteria is supported. - -[`default`]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#default-aggregation -[`sum`]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#sum-aggregation -[`last_value`]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#last-value-aggregation -[`drop`]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#drop-aggregation -[`explicit_bucket_histogram`]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#explicit-bucket-histogram-aggregation -[`exponential_bucket_histogram`]: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/sdk.md#base2-exponential-bucket-histogram-aggregation diff --git a/sdk-extensions/incubator/build.gradle.kts b/sdk-extensions/incubator/build.gradle.kts index c729f526428..77bd6ef65a3 100644 --- a/sdk-extensions/incubator/build.gradle.kts +++ b/sdk-extensions/incubator/build.gradle.kts @@ -17,9 +17,7 @@ dependencies { compileOnly(project(":api:incubator")) - // io.opentelemetry.sdk.extension.incubator.metric.viewconfig implementation(project(":sdk-extensions:autoconfigure-spi")) - implementation("org.snakeyaml:snakeyaml-engine") testImplementation(project(":sdk:testing")) testImplementation(project(":sdk-extensions:autoconfigure")) diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/SelectorSpecification.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/SelectorSpecification.java deleted file mode 100644 index 70ea3d91642..00000000000 --- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/SelectorSpecification.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.extension.incubator.metric.viewconfig; - -import com.google.auto.value.AutoValue; -import io.opentelemetry.sdk.metrics.InstrumentType; -import javax.annotation.Nullable; - -@AutoValue -abstract class SelectorSpecification { - - static AutoValue_SelectorSpecification.Builder builder() { - return new AutoValue_SelectorSpecification.Builder(); - } - - @Nullable - abstract String getInstrumentName(); - - @Nullable - abstract InstrumentType getInstrumentType(); - - @Nullable - abstract String getInstrumentUnit(); - - @Nullable - abstract String getMeterName(); - - @Nullable - abstract String getMeterVersion(); - - @Nullable - abstract String getMeterSchemaUrl(); - - @AutoValue.Builder - interface Builder { - Builder instrumentName(@Nullable String instrumentName); - - Builder instrumentType(@Nullable InstrumentType instrumentType); - - Builder instrumentUnit(@Nullable String instrumentUnit); - - Builder meterName(@Nullable String meterName); - - Builder meterVersion(@Nullable String meterVersion); - - Builder meterSchemaUrl(@Nullable String meterSchemaUrl); - - SelectorSpecification build(); - } -} diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfig.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfig.java deleted file mode 100644 index ec18190df9d..00000000000 --- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfig.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.extension.incubator.metric.viewconfig; - -import static java.util.Objects.requireNonNull; -import static java.util.stream.Collectors.toList; - -import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; -import io.opentelemetry.sdk.metrics.Aggregation; -import io.opentelemetry.sdk.metrics.Base2ExponentialHistogramOptions; -import io.opentelemetry.sdk.metrics.ExplicitBucketHistogramOptions; -import io.opentelemetry.sdk.metrics.InstrumentSelector; -import io.opentelemetry.sdk.metrics.InstrumentSelectorBuilder; -import io.opentelemetry.sdk.metrics.InstrumentType; -import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; -import io.opentelemetry.sdk.metrics.View; -import io.opentelemetry.sdk.metrics.ViewBuilder; -import io.opentelemetry.sdk.metrics.internal.aggregator.AggregationUtil; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import javax.annotation.Nullable; -import org.snakeyaml.engine.v2.api.Load; -import org.snakeyaml.engine.v2.api.LoadSettings; - -/** - * Enables file based YAML configuration of Metric SDK {@link View}s. - * - *

For example, a YAML file with the following content: - * - *

- *   - selector:
- *       instrument_name: my-instrument
- *       instrument_type: COUNTER
- *       instrument_unit: ms
- *       meter_name: my-meter
- *       meter_version: 1.0.0
- *       meter_schema_url: http://example.com
- *     view:
- *       name: new-instrument-name
- *       description: new-description
- *       aggregation: explicit_bucket_histogram
- *       attribute_keys:
- *         - foo
- *         - bar
- * 
- * - *

Is equivalent to the following configuration: - * - *

{@code
- * SdkMeterProvider.builder()
- *     .registerView(
- *         InstrumentSelector.builder()
- *             .setName("my-instrument")
- *             .setType(InstrumentType.COUNTER)
- *             .setUnit("ms")
- *             .setMeterName("my-meter")
- *             .setMeterVersion("1.0.0")
- *             .setMeterSchemaUrl("http://example.com")
- *             .build(),
- *         View.builder()
- *             .setName("new-instrument")
- *             .setDescription("new-description")
- *             .setAggregation(Aggregation.explicitBucketHistogram())
- *             .setAttributesFilter(key -> new HashSet<>(Arrays.asList("foo", "bar")).contains(key))
- *             .build());
- * }
- * - * @deprecated this mechanism is superseded by declarative config, which is now stable (spec and - * schema at opentelemetry-configuration. - * Please uses {@code - * io.opentelemetry.sdk.declarativeconfig.DeclarativeConfiguration#parseAndCreate(InputStream)} - * instead. - */ -@Deprecated -public final class ViewConfig { - - private ViewConfig() {} - - /** - * Load the view configuration YAML from the {@code inputStream} and apply it to the {@link - * SdkMeterProviderBuilder}. - * - * @throws ConfigurationException if unable to interpret {@code inputStream} contents - */ - public static void registerViews( - SdkMeterProviderBuilder meterProviderBuilder, InputStream inputStream) { - List viewConfigSpecs = loadViewConfig(inputStream); - - for (ViewConfigSpecification viewConfigSpec : viewConfigSpecs) { - meterProviderBuilder.registerView( - toInstrumentSelector(viewConfigSpec.getSelectorSpecification()), - toView(viewConfigSpec.getViewSpecification())); - } - } - - // Visible for testing - @SuppressWarnings("unchecked") - static List loadViewConfig(InputStream inputStream) { - LoadSettings settings = LoadSettings.builder().build(); - Load yaml = new Load(settings); - try { - List result = new ArrayList<>(); - - List> viewConfigs = - (List>) yaml.loadFromInputStream(inputStream); - - for (Map viewConfigSpecMap : viewConfigs) { - Map selectorSpecMap = - requireNonNull( - getAsType(viewConfigSpecMap, "selector", Map.class), "selector is required"); - Map viewSpecMap = - requireNonNull(getAsType(viewConfigSpecMap, "view", Map.class), "view is required"); - - InstrumentType instrumentType = - Optional.ofNullable(getAsType(selectorSpecMap, "instrument_type", String.class)) - .map(InstrumentType::valueOf) - .orElse(null); - List attributeKeys = - Optional.ofNullable( - ((List) getAsType(viewSpecMap, "attribute_keys", List.class))) - .map(objects -> objects.stream().map(String::valueOf).collect(toList())) - .orElse(null); - - result.add( - ViewConfigSpecification.builder() - .selectorSpecification( - SelectorSpecification.builder() - .instrumentName(getAsType(selectorSpecMap, "instrument_name", String.class)) - .instrumentType(instrumentType) - .instrumentUnit(getAsType(selectorSpecMap, "instrument_unit", String.class)) - .meterName(getAsType(selectorSpecMap, "meter_name", String.class)) - .meterVersion(getAsType(selectorSpecMap, "meter_version", String.class)) - .meterSchemaUrl( - getAsType(selectorSpecMap, "meter_schema_url", String.class)) - .build()) - .viewSpecification( - ViewSpecification.builder() - .name(getAsType(viewSpecMap, "name", String.class)) - .description(getAsType(viewSpecMap, "description", String.class)) - .aggregation(getAsType(viewSpecMap, "aggregation", String.class)) - .aggregationArgs(getAsType(viewSpecMap, "aggregation_args", Map.class)) - .attributeKeys(attributeKeys) - .build()) - .build()); - } - return result; - } catch (RuntimeException e) { - throw new ConfigurationException("Failed to parse view config", e); - } - } - - @Nullable - @SuppressWarnings("unchecked") - private static T getAsType(Map map, String key, Class type) { - Object value = map.get(key); - if (value != null && !type.isInstance(value)) { - throw new IllegalStateException( - "Expected " - + key - + " to be type " - + type.getName() - + " but was " - + value.getClass().getName()); - } - return (T) value; - } - - // Visible for testing - static View toView(ViewSpecification viewSpec) { - ViewBuilder builder = View.builder(); - String name = viewSpec.getName(); - if (name != null) { - builder.setName(name); - } - String description = viewSpec.getDescription(); - if (description != null) { - builder.setDescription(description); - } - String aggregation = viewSpec.getAggregation(); - if (aggregation != null) { - Map aggregationArgs = - viewSpec.getAggregationArgs() == null - ? Collections.emptyMap() - : viewSpec.getAggregationArgs(); - builder.setAggregation(toAggregation(aggregation, aggregationArgs)); - } - List attributeKeys = viewSpec.getAttributeKeys(); - if (attributeKeys != null) { - Set keySet = new HashSet<>(attributeKeys); - builder.setAttributeFilter(keySet::contains); - } - return builder.build(); - } - - // Visible for testing - static Aggregation toAggregation(String aggregationName, Map aggregationArgs) { - Aggregation aggregation; - try { - aggregation = AggregationUtil.forName(aggregationName); - } catch (IllegalArgumentException e) { - throw new ConfigurationException("Error creating aggregation", e); - } - if (Aggregation.explicitBucketHistogram().equals(aggregation)) { - List bucketBoundaries = getBucketBoundaries(aggregationArgs); - if (bucketBoundaries != null) { - return Aggregation.explicitBucketHistogram( - ExplicitBucketHistogramOptions.builder().setBucketBoundaries(bucketBoundaries).build()); - } - } - if (Aggregation.base2ExponentialBucketHistogram().equals(aggregation)) { - Integer maxBuckets; - try { - maxBuckets = getAsType(aggregationArgs, "max_buckets", Integer.class); - } catch (IllegalStateException e) { - throw new ConfigurationException("max_buckets must be an integer", e); - } - // TODO: support configuring max_scale - if (maxBuckets != null) { - return Aggregation.base2ExponentialBucketHistogram( - Base2ExponentialHistogramOptions.builder().setMaxBuckets(maxBuckets).build()); - } - } - return aggregation; - } - - @Nullable - @SuppressWarnings("unchecked") - private static List getBucketBoundaries(Map aggregationArgs) { - List boundaryObjects = - ((List) getAsType(aggregationArgs, "bucket_boundaries", List.class)); - if (boundaryObjects == null) { - return null; - } - return boundaryObjects.stream() - .map( - o -> { - if (!(o instanceof Number)) { - throw new ConfigurationException("bucket_boundaries must be an array of numbers"); - } - return ((Number) o).doubleValue(); - }) - .collect(toList()); - } - - // Visible for testing - static InstrumentSelector toInstrumentSelector(SelectorSpecification selectorSpec) { - InstrumentSelectorBuilder builder = InstrumentSelector.builder(); - String instrumentName = selectorSpec.getInstrumentName(); - if (instrumentName != null) { - builder.setName(instrumentName); - } - InstrumentType instrumentType = selectorSpec.getInstrumentType(); - if (instrumentType != null) { - builder.setType(instrumentType); - } - String instrumentUnit = selectorSpec.getInstrumentUnit(); - if (instrumentUnit != null) { - builder.setUnit(instrumentUnit); - } - - String meterName = selectorSpec.getMeterName(); - if (meterName != null) { - builder.setMeterName(meterName); - } - String meterVersion = selectorSpec.getMeterVersion(); - if (meterVersion != null) { - builder.setMeterVersion(meterVersion); - } - String meterSchemaUrl = selectorSpec.getMeterSchemaUrl(); - if (meterSchemaUrl != null) { - builder.setMeterSchemaUrl(meterSchemaUrl); - } - - return builder.build(); - } -} diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigCustomizer.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigCustomizer.java deleted file mode 100644 index 13f5fbda742..00000000000 --- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigCustomizer.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.extension.incubator.metric.viewconfig; - -import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer; -import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; -import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.logging.Logger; - -/** - * SPI implementation for loading view configuration YAML. - * - * @deprecated this mechanism is superseded by declarative config, which is now stable (spec and - * schema at opentelemetry-configuration) - * and will be removed after the 1.62.0 release. Please uses {@code - * io.opentelemetry.sdk.declarativeconfig.DeclarativeConfiguration#parseAndCreate(InputStream)} - * instead. - */ -@Deprecated -public final class ViewConfigCustomizer implements AutoConfigurationCustomizerProvider { - private static final Logger LOGGER = Logger.getLogger(ViewConfigCustomizer.class.getName()); - - @Override - public void customize(AutoConfigurationCustomizer autoConfiguration) { - autoConfiguration.addMeterProviderCustomizer(ViewConfigCustomizer::customizeMeterProvider); - } - - // Visible for testing - static SdkMeterProviderBuilder customizeMeterProvider( - SdkMeterProviderBuilder meterProviderBuilder, ConfigProperties configProperties) { - List configFileLocations = - configProperties.getList("otel.experimental.metrics.view.config"); - if (!configFileLocations.isEmpty()) { - LOGGER.warning( - "otel.experimental.metrics.view.config is deprecated and will be removed after 1.62 release. Please use declarative config instead."); - } - for (String configFileLocation : configFileLocations) { - if (configFileLocation.startsWith("classpath:")) { - String classpathLocation = configFileLocation.substring("classpath:".length()); - try (InputStream inputStream = - ViewConfigCustomizer.class.getResourceAsStream(classpathLocation)) { - if (inputStream == null) { - throw new ConfigurationException( - "Resource " - + classpathLocation - + " not found on classpath of classloader " - + ViewConfigCustomizer.class.getClassLoader().getClass().getName()); - } - ViewConfig.registerViews(meterProviderBuilder, inputStream); - } catch (IOException e) { - throw new ConfigurationException( - "An error occurred reading view config resource on classpath: " + classpathLocation, - e); - } - } else { - try (FileInputStream fileInputStream = new FileInputStream(configFileLocation)) { - ViewConfig.registerViews(meterProviderBuilder, fileInputStream); - } catch (FileNotFoundException e) { - throw new ConfigurationException("View config file not found: " + configFileLocation, e); - } catch (IOException e) { - throw new ConfigurationException( - "An error occurred reading view config file: " + configFileLocation, e); - } - } - } - return meterProviderBuilder; - } -} diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigSpecification.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigSpecification.java deleted file mode 100644 index 1e7b54459f2..00000000000 --- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigSpecification.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.extension.incubator.metric.viewconfig; - -import com.google.auto.value.AutoValue; - -@AutoValue -abstract class ViewConfigSpecification { - - static AutoValue_ViewConfigSpecification.Builder builder() { - return new AutoValue_ViewConfigSpecification.Builder(); - } - - abstract SelectorSpecification getSelectorSpecification(); - - abstract ViewSpecification getViewSpecification(); - - @AutoValue.Builder - interface Builder { - Builder selectorSpecification(SelectorSpecification selectorSpecification); - - Builder viewSpecification(ViewSpecification viewSpecification); - - ViewConfigSpecification build(); - } -} diff --git a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewSpecification.java b/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewSpecification.java deleted file mode 100644 index 33229ac91b7..00000000000 --- a/sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewSpecification.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.extension.incubator.metric.viewconfig; - -import com.google.auto.value.AutoValue; -import java.util.List; -import java.util.Map; -import javax.annotation.Nullable; - -@AutoValue -abstract class ViewSpecification { - - static AutoValue_ViewSpecification.Builder builder() { - return new AutoValue_ViewSpecification.Builder(); - } - - @Nullable - abstract String getName(); - - @Nullable - abstract String getDescription(); - - @Nullable - abstract String getAggregation(); - - @Nullable - abstract Map getAggregationArgs(); - - @Nullable - abstract List getAttributeKeys(); - - @AutoValue.Builder - interface Builder { - Builder name(@Nullable String name); - - Builder description(@Nullable String description); - - Builder aggregation(@Nullable String aggregation); - - Builder aggregationArgs(@Nullable Map aggregationArgs); - - Builder attributeKeys(@Nullable List attributeKeys); - - ViewSpecification build(); - } -} diff --git a/sdk-extensions/incubator/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider b/sdk-extensions/incubator/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider deleted file mode 100644 index 547806a7c68..00000000000 --- a/sdk-extensions/incubator/src/main/resources/META-INF/services/io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider +++ /dev/null @@ -1 +0,0 @@ -io.opentelemetry.sdk.extension.incubator.metric.viewconfig.ViewConfigCustomizer \ No newline at end of file diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigCustomizerTest.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigCustomizerTest.java deleted file mode 100644 index 0a742ee96e5..00000000000 --- a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigCustomizerTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.extension.incubator.metric.viewconfig; - -import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; -import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.attributeEntry; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import com.google.common.collect.ImmutableMap; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; -import io.opentelemetry.sdk.metrics.SdkMeterProvider; -import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader; -import java.util.Arrays; -import java.util.UUID; -import org.junit.jupiter.api.Test; - -@SuppressWarnings("deprecation") // Testing deprecated methods -class ViewConfigCustomizerTest { - - @Test - void customizeMeterProvider_Spi() { - InMemoryMetricReader reader = InMemoryMetricReader.create(); - AutoConfiguredOpenTelemetrySdk.builder() - .addPropertiesSupplier( - () -> - ImmutableMap.of( - "otel.traces.exporter", - "none", - "otel.metrics.exporter", - "none", - "otel.logs.exporter", - "none", - "otel.experimental.metrics.view.config", - "classpath:/view-config-customizer-test.yaml")) - .addMeterProviderCustomizer( - (meterProviderBuilder, configProperties) -> - meterProviderBuilder.registerMetricReader(reader)) - .build() - .getOpenTelemetrySdk() - .getSdkMeterProvider() - .get("test-meter") - .counterBuilder("counter") - .buildWithCallback( - callback -> { - // Attributes with keys baz and qux should be filtered out - callback.record( - 1, - Attributes.builder() - .put("foo", "val") - .put("bar", "val") - .put("baz", "val") - .put("qux", "val") - .build()); - }); - - assertThat(reader.collectAllMetrics()) - .satisfiesExactly( - metricData -> - assertThat(metricData) - .hasLongSumSatisfying( - sum -> - sum.hasPointsSatisfying( - point -> - point - .hasValue(1) - .hasAttributes( - attributeEntry("foo", "val"), - attributeEntry("bar", "val"))))); - } - - @Test - void customizeMeterProvider_MultipleFiles() { - ConfigProperties properties = - withConfigFileLocations( - "classpath:/view-config-customizer-test.yaml", "classpath:/full-config.yaml"); - - assertThatCode( - () -> - ViewConfigCustomizer.customizeMeterProvider(SdkMeterProvider.builder(), properties)) - .doesNotThrowAnyException(); - } - - @Test - void customizeMeterProvider_AbsolutePath() { - ConfigProperties properties = - withConfigFileLocations( - ViewConfigTest.class.getResource("/view-config-customizer-test.yaml").getFile()); - - assertThatCode( - () -> - ViewConfigCustomizer.customizeMeterProvider(SdkMeterProvider.builder(), properties)) - .doesNotThrowAnyException(); - } - - @Test - void customizeMeterProvider_Invalid() { - assertThatThrownBy( - () -> - ViewConfigCustomizer.customizeMeterProvider( - SdkMeterProvider.builder(), - withConfigFileLocations("classpath:" + UUID.randomUUID()))) - .hasMessageMatching("Resource .* not found on classpath of classloader .*"); - assertThatThrownBy( - () -> - ViewConfigCustomizer.customizeMeterProvider( - SdkMeterProvider.builder(), withConfigFileLocations("/" + UUID.randomUUID()))) - .hasMessageContaining("View config file not found:"); - assertThatThrownBy( - () -> - ViewConfigCustomizer.customizeMeterProvider( - SdkMeterProvider.builder(), - withConfigFileLocations("classpath:/empty-selector-config.yaml"))) - .hasMessageContaining("Failed to parse view config") - .hasRootCauseMessage("selector is required"); - } - - private static ConfigProperties withConfigFileLocations(String... fileLocations) { - ConfigProperties properties = mock(ConfigProperties.class); - when(properties.getList("otel.experimental.metrics.view.config")) - .thenReturn(Arrays.asList(fileLocations)); - return properties; - } -} diff --git a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigTest.java b/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigTest.java deleted file mode 100644 index 68c7b87d99b..00000000000 --- a/sdk-extensions/incubator/src/test/java/io/opentelemetry/sdk/extension/incubator/metric/viewconfig/ViewConfigTest.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.sdk.extension.incubator.metric.viewconfig; - -import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; -import static org.assertj.core.api.Assertions.as; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import com.google.common.collect.ImmutableMap; -import io.opentelemetry.api.common.AttributeKey; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.context.Context; -import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException; -import io.opentelemetry.sdk.metrics.Aggregation; -import io.opentelemetry.sdk.metrics.InstrumentSelector; -import io.opentelemetry.sdk.metrics.InstrumentType; -import io.opentelemetry.sdk.metrics.SdkMeterProvider; -import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; -import io.opentelemetry.sdk.metrics.View; -import io.opentelemetry.sdk.metrics.internal.view.AttributesProcessor; -import io.opentelemetry.sdk.metrics.internal.view.Base2ExponentialHistogramAggregation; -import io.opentelemetry.sdk.metrics.internal.view.ExplicitBucketHistogramAggregation; -import io.opentelemetry.sdk.metrics.internal.view.RegisteredView; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.net.URL; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; -import org.assertj.core.api.InstanceOfAssertFactories; -import org.junit.jupiter.api.Test; - -@SuppressWarnings("deprecation") // Testing deprecated methods -class ViewConfigTest { - - @Test - void registerViews_FullConfig() { - SdkMeterProviderBuilder builder = SdkMeterProvider.builder(); - - ViewConfig.registerViews(builder, resourceFileInputStream("full-config.yaml")); - - assertThat(builder) - .extracting("registeredViews", as(InstanceOfAssertFactories.list(RegisteredView.class))) - .hasSize(2); - } - - @Test - void loadViewConfig_FullConfig() { - List viewConfigSpecs = - ViewConfig.loadViewConfig(resourceFileInputStream("full-config.yaml")); - - assertThat(viewConfigSpecs) - .satisfiesExactly( - viewConfigSpec -> { - SelectorSpecification selectorSpec = viewConfigSpec.getSelectorSpecification(); - assertThat(selectorSpec.getInstrumentName()).isEqualTo("name1"); - assertThat(selectorSpec.getInstrumentType()).isEqualTo(InstrumentType.COUNTER); - assertThat(selectorSpec.getInstrumentUnit()).isEqualTo("ms"); - assertThat(selectorSpec.getMeterName()).isEqualTo("meterName1"); - assertThat(selectorSpec.getMeterVersion()).isEqualTo("1.0.0"); - assertThat(selectorSpec.getMeterSchemaUrl()).isEqualTo("http://example1.com"); - ViewSpecification viewSpec = viewConfigSpec.getViewSpecification(); - assertThat(viewSpec.getName()).isEqualTo("name1"); - assertThat(viewSpec.getDescription()).isEqualTo("description1"); - assertThat(viewSpec.getAggregation()).isEqualTo("sum"); - assertThat(viewSpec.getAttributeKeys()).containsExactly("foo", "bar"); - }, - viewConfigSpec -> { - SelectorSpecification selectorSpec = viewConfigSpec.getSelectorSpecification(); - assertThat(selectorSpec.getInstrumentName()).isEqualTo("name2"); - assertThat(selectorSpec.getInstrumentType()).isEqualTo(InstrumentType.COUNTER); - assertThat(selectorSpec.getInstrumentUnit()).isEqualTo("s"); - assertThat(selectorSpec.getMeterName()).isEqualTo("meterName2"); - assertThat(selectorSpec.getMeterVersion()).isEqualTo("2.0.0"); - assertThat(selectorSpec.getMeterSchemaUrl()).isEqualTo("http://example2.com"); - ViewSpecification viewSpec = viewConfigSpec.getViewSpecification(); - assertThat(viewSpec.getName()).isEqualTo("name2"); - assertThat(viewSpec.getDescription()).isEqualTo("description2"); - assertThat(viewSpec.getAggregation()).isEqualTo("last_value"); - assertThat(viewSpec.getAttributeKeys()).containsExactly("baz", "qux"); - }); - } - - @Test - void loadViewConfig_Invalid() { - assertThatThrownBy( - () -> ViewConfig.loadViewConfig(resourceFileInputStream("empty-view-config.yaml"))) - .isInstanceOf(ConfigurationException.class) - .hasMessageContaining("Failed to parse view config") - .hasRootCauseMessage("view is required"); - assertThatThrownBy( - () -> ViewConfig.loadViewConfig(resourceFileInputStream("empty-selector-config.yaml"))) - .isInstanceOf(ConfigurationException.class) - .hasMessageContaining("Failed to parse view config") - .hasRootCauseMessage("selector is required"); - } - - @Test - void loadViewConfig_AggregationArgs() { - List viewConfigSpecs = - ViewConfig.loadViewConfig(resourceFileInputStream("aggregation-args.yaml")); - - assertThat(viewConfigSpecs) - .satisfiesExactly( - viewConfigSpec -> { - SelectorSpecification selectorSpec = viewConfigSpec.getSelectorSpecification(); - assertThat(selectorSpec.getInstrumentType()).isEqualTo(InstrumentType.HISTOGRAM); - ViewSpecification viewSpec = viewConfigSpec.getViewSpecification(); - assertThat(viewSpec.getAggregation()).isEqualTo("explicit_bucket_histogram"); - assertThat(viewSpec.getAggregationArgs()) - .isEqualTo(ImmutableMap.of("bucket_boundaries", Arrays.asList(1.0, 2.0, 5.0))); - }, - viewConfigSpec -> { - SelectorSpecification selectorSpec = viewConfigSpec.getSelectorSpecification(); - assertThat(selectorSpec.getInstrumentType()).isEqualTo(InstrumentType.HISTOGRAM); - ViewSpecification viewSpec = viewConfigSpec.getViewSpecification(); - assertThat(viewSpec.getAggregation()).isEqualTo("explicit_bucket_histogram"); - assertThat(viewSpec.getAggregationArgs()) - .isEqualTo(ImmutableMap.of("bucket_boundaries", Arrays.asList(1.0, 2.0, 5.0))); - }, - viewConfigSpec -> { - SelectorSpecification selectorSpec = viewConfigSpec.getSelectorSpecification(); - assertThat(selectorSpec.getInstrumentType()).isEqualTo(InstrumentType.HISTOGRAM); - ViewSpecification viewSpec = viewConfigSpec.getViewSpecification(); - assertThat(viewSpec.getAggregation()).isEqualTo("exponential_bucket_histogram"); - assertThat(viewSpec.getAggregationArgs()) - .isEqualTo(ImmutableMap.of("max_buckets", 20)); - }); - } - - @Test - void toView_Empty() { - View view = ViewConfig.toView(ViewSpecification.builder().build()); - assertThat(view).isEqualTo(View.builder().build()); - } - - @Test - void toView() { - View view = - ViewConfig.toView( - ViewSpecification.builder() - .name("name") - .description("description") - .aggregation("sum") - .attributeKeys(Arrays.asList("foo", "bar")) - .build()); - assertThat(view.getName()).isEqualTo("name"); - assertThat(view.getDescription()).isEqualTo("description"); - assertThat(view.getAggregation()).isEqualTo(Aggregation.sum()); - assertThat(view) - .extracting( - "attributesProcessor", as(InstanceOfAssertFactories.type(AttributesProcessor.class))) - .satisfies( - attributesProcessor -> - assertThat( - attributesProcessor.process( - Attributes.builder() - .put("foo", "val") - .put("bar", "val") - .put("baz", "val") - .build(), - Context.current())) - .containsEntry("foo", "val") - .containsEntry("bar", "val") - .satisfies( - (Consumer) - attributes -> - assertThat(attributes.get(AttributeKey.stringKey("baz"))) - .isBlank())); - } - - @Test - void toAggregation_BadConfig() { - // Unrecognized aggregation - assertThatThrownBy(() -> ViewConfig.toAggregation("foo", Collections.emptyMap())) - .isInstanceOf(ConfigurationException.class) - .hasMessage("Error creating aggregation"); - - // Explicit bucket histogram - assertThatThrownBy( - () -> - ViewConfig.toAggregation( - "explicit_bucket_histogram", - ImmutableMap.of("bucket_boundaries", Arrays.asList("seven", "four")))) - .isInstanceOf(ConfigurationException.class) - .hasMessage("bucket_boundaries must be an array of numbers"); - assertThatThrownBy( - () -> - ViewConfig.toAggregation( - "explicit_bucket_histogram", - ImmutableMap.of("bucket_boundaries", Collections.singletonList("2.0,3.0")))) - .isInstanceOf(ConfigurationException.class) - .hasMessage("bucket_boundaries must be an array of numbers"); - - // Exponential histogram - assertThatThrownBy( - () -> - ViewConfig.toAggregation( - "base2_exponential_bucket_histogram", ImmutableMap.of("max_buckets", "four"))) - .isInstanceOf(ConfigurationException.class) - .hasMessage("max_buckets must be an integer"); - } - - @Test - void toAggregation_GoodConfig() { - // Explicit bucket histogram - assertThat(ViewConfig.toAggregation("explicit_bucket_histogram", Collections.emptyMap())) - .isEqualTo(Aggregation.explicitBucketHistogram()); - assertThat( - ViewConfig.toAggregation( - "explicit_bucket_histogram", - ImmutableMap.of("bucket_boundaries", Arrays.asList(1.0, 2.0)))) - .isInstanceOf(ExplicitBucketHistogramAggregation.class) - .extracting("bucketBoundaries", as(InstanceOfAssertFactories.list(Double.class))) - .isEqualTo(Arrays.asList(1.0, 2.0)); - assertThat( - ViewConfig.toAggregation( - "explicit_bucket_histogram", - ImmutableMap.of("bucket_boundaries", Arrays.asList(1, 2)))) - .isInstanceOf(ExplicitBucketHistogramAggregation.class) - .extracting("bucketBoundaries", as(InstanceOfAssertFactories.list(Double.class))) - .isEqualTo(Arrays.asList(1.0, 2.0)); - - // Exponential histogram - assertThat( - ViewConfig.toAggregation("base2_exponential_bucket_histogram", Collections.emptyMap())) - .isEqualTo(Aggregation.base2ExponentialBucketHistogram()); - assertThat( - ViewConfig.toAggregation( - "base2_exponential_bucket_histogram", ImmutableMap.of("max_buckets", 20))) - .isInstanceOf(Base2ExponentialHistogramAggregation.class) - .extracting("maxBuckets", as(InstanceOfAssertFactories.INTEGER)) - .isEqualTo(20); - } - - @Test - void toInstrumentSelector() { - InstrumentSelector selector = - ViewConfig.toInstrumentSelector( - SelectorSpecification.builder() - .instrumentName("name") - .instrumentType(InstrumentType.COUNTER) - .instrumentUnit("ms") - .meterName("meterName") - .meterVersion("meterVersion") - .meterSchemaUrl("http://example.com") - .build()); - - assertThat(selector.getInstrumentName()).isEqualTo("name"); - assertThat(selector.getInstrumentType()).isEqualTo(InstrumentType.COUNTER); - assertThat(selector.getInstrumentUnit()).isEqualTo("ms"); - assertThat(selector.getMeterName()).isEqualTo("meterName"); - assertThat(selector.getMeterVersion()).isEqualTo("meterVersion"); - assertThat(selector.getMeterSchemaUrl()).isEqualTo("http://example.com"); - } - - private static InputStream resourceFileInputStream(String resourceFileName) { - URL resourceUrl = ViewConfigTest.class.getResource("/" + resourceFileName); - if (resourceUrl == null) { - throw new IllegalStateException("Could not find resource file: " + resourceFileName); - } - String path = resourceUrl.getFile(); - try { - return new FileInputStream(path); - } catch (FileNotFoundException e) { - throw new IllegalStateException("File not found: " + path, e); - } - } -} diff --git a/sdk-extensions/incubator/src/test/resources/aggregation-args.yaml b/sdk-extensions/incubator/src/test/resources/aggregation-args.yaml deleted file mode 100644 index 9ddf21b5c8d..00000000000 --- a/sdk-extensions/incubator/src/test/resources/aggregation-args.yaml +++ /dev/null @@ -1,21 +0,0 @@ -- selector: - instrument_type: HISTOGRAM - view: - aggregation: explicit_bucket_histogram - aggregation_args: - bucket_boundaries: [1.0, 2.0, 5.0] -- selector: - instrument_type: HISTOGRAM - view: - aggregation: explicit_bucket_histogram - aggregation_args: - bucket_boundaries: - - 1.0 - - 2.0 - - 5.0 -- selector: - instrument_type: HISTOGRAM - view: - aggregation: exponential_bucket_histogram - aggregation_args: - max_buckets: 20 diff --git a/sdk-extensions/incubator/src/test/resources/empty-selector-config.yaml b/sdk-extensions/incubator/src/test/resources/empty-selector-config.yaml deleted file mode 100644 index 657a53c0f87..00000000000 --- a/sdk-extensions/incubator/src/test/resources/empty-selector-config.yaml +++ /dev/null @@ -1,5 +0,0 @@ -- selector: - view: - name: name1 - description: description1 - aggregation: sum diff --git a/sdk-extensions/incubator/src/test/resources/empty-view-config.yaml b/sdk-extensions/incubator/src/test/resources/empty-view-config.yaml deleted file mode 100644 index 7b27e1e26a9..00000000000 --- a/sdk-extensions/incubator/src/test/resources/empty-view-config.yaml +++ /dev/null @@ -1,8 +0,0 @@ -- selector: - instrument_name: name1 - instrument_type: COUNTER - instrument_unit: ms - meter_name: meterName1 - meter_version: 1.0.0 - meter_schema_url: http://example1.com - view: diff --git a/sdk-extensions/incubator/src/test/resources/full-config.yaml b/sdk-extensions/incubator/src/test/resources/full-config.yaml deleted file mode 100644 index bf968c7e1d6..00000000000 --- a/sdk-extensions/incubator/src/test/resources/full-config.yaml +++ /dev/null @@ -1,28 +0,0 @@ -- selector: - instrument_name: name1 - instrument_type: COUNTER - instrument_unit: ms - meter_name: meterName1 - meter_version: 1.0.0 - meter_schema_url: http://example1.com - view: - name: name1 - description: description1 - aggregation: sum - attribute_keys: - - foo - - bar -- selector: - instrument_name: name2 - instrument_type: COUNTER - instrument_unit: s - meter_name: meterName2 - meter_version: 2.0.0 - meter_schema_url: http://example2.com - view: - name: name2 - description: description2 - aggregation: last_value - attribute_keys: - - baz - - qux diff --git a/sdk-extensions/incubator/src/test/resources/view-config-customizer-test.yaml b/sdk-extensions/incubator/src/test/resources/view-config-customizer-test.yaml deleted file mode 100644 index afa6514b62b..00000000000 --- a/sdk-extensions/incubator/src/test/resources/view-config-customizer-test.yaml +++ /dev/null @@ -1,6 +0,0 @@ -- selector: - instrument_type: OBSERVABLE_COUNTER - view: - attribute_keys: - - foo - - bar \ No newline at end of file