Meter provider configuration factory (#5773)
This commit is contained in:
parent
7229c45513
commit
01503efe97
|
@ -1,2 +1,10 @@
|
||||||
Comparing source compatibility of against
|
Comparing source compatibility of against
|
||||||
No changes.
|
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.logging.LoggingMetricExporter (not serializable)
|
||||||
|
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
|
||||||
|
+++ NEW METHOD: PUBLIC(+) java.lang.String toString()
|
||||||
|
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.logging.LoggingSpanExporter (not serializable)
|
||||||
|
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
|
||||||
|
+++ NEW METHOD: PUBLIC(+) java.lang.String toString()
|
||||||
|
*** MODIFIED CLASS: PUBLIC io.opentelemetry.exporter.logging.SystemOutLogRecordExporter (not serializable)
|
||||||
|
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
|
||||||
|
+++ NEW METHOD: PUBLIC(+) java.lang.String toString()
|
||||||
|
|
|
@ -103,4 +103,9 @@ public final class LoggingMetricExporter implements MetricExporter {
|
||||||
}
|
}
|
||||||
return flush();
|
return flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "LoggingMetricExporter{}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,4 +93,9 @@ public final class LoggingSpanExporter implements SpanExporter {
|
||||||
}
|
}
|
||||||
return flush();
|
return flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "LoggingSpanExporter{}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,4 +95,9 @@ public class SystemOutLogRecordExporter implements LogRecordExporter {
|
||||||
}
|
}
|
||||||
return CompletableResultCode.ofSuccess();
|
return CompletableResultCode.ofSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SystemOutLogRecordExporter{}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,4 +114,9 @@ class LoggingMetricExporterTest {
|
||||||
assertThat(exporter.shutdown().isSuccess()).isTrue();
|
assertThat(exporter.shutdown().isSuccess()).isTrue();
|
||||||
logs.assertContains("Calling shutdown() multiple times.");
|
logs.assertContains("Calling shutdown() multiple times.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void stringRepresentation() {
|
||||||
|
assertThat(LoggingMetricExporter.create().toString()).isEqualTo("LoggingMetricExporter{}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,4 +139,9 @@ class LoggingSpanExporterTest {
|
||||||
assertThat(exporter.shutdown().isSuccess()).isTrue();
|
assertThat(exporter.shutdown().isSuccess()).isTrue();
|
||||||
logs.assertContains("Calling shutdown() multiple times.");
|
logs.assertContains("Calling shutdown() multiple times.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void stringRepresentation() {
|
||||||
|
assertThat(LoggingSpanExporter.create().toString()).isEqualTo("LoggingSpanExporter{}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,12 @@ class SystemOutLogRecordExporterTest {
|
||||||
assertThat(exporter.shutdown().isSuccess()).isTrue();
|
assertThat(exporter.shutdown().isSuccess()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void stringRepresentation() {
|
||||||
|
assertThat(SystemOutLogRecordExporter.create().toString())
|
||||||
|
.isEqualTo("SystemOutLogRecordExporter{}");
|
||||||
|
}
|
||||||
|
|
||||||
private static LogRecordData sampleLog(long timestamp) {
|
private static LogRecordData sampleLog(long timestamp) {
|
||||||
return TestLogRecordData.builder()
|
return TestLogRecordData.builder()
|
||||||
.setResource(Resource.empty())
|
.setResource(Resource.empty())
|
||||||
|
|
|
@ -33,6 +33,8 @@ dependencies {
|
||||||
testImplementation(project(":sdk:testing"))
|
testImplementation(project(":sdk:testing"))
|
||||||
testImplementation(project(":sdk-extensions:autoconfigure"))
|
testImplementation(project(":sdk-extensions:autoconfigure"))
|
||||||
testImplementation(project(":exporters:otlp:all"))
|
testImplementation(project(":exporters:otlp:all"))
|
||||||
|
testImplementation(project(":exporters:prometheus"))
|
||||||
|
testImplementation(project(":exporters:logging"))
|
||||||
testImplementation(project(":sdk-extensions:jaeger-remote-sampler"))
|
testImplementation(project(":sdk-extensions:jaeger-remote-sampler"))
|
||||||
testImplementation(project(":extensions:trace-propagators"))
|
testImplementation(project(":extensions:trace-propagators"))
|
||||||
// As a part of the tests we check that we can parse examples without error. The https://github.com/open-telemetry/opentelemetry-configuration/blob/main/examples/kitchen-sink.yam contains a reference to the xray propagator
|
// As a part of the tests we check that we can parse examples without error. The https://github.com/open-telemetry/opentelemetry-configuration/blob/main/examples/kitchen-sink.yam contains a reference to the xray propagator
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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.autoconfigure.spi.ConfigurationException;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Aggregation;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Base2ExponentialBucketHistogram;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExplicitBucketHistogram;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
final class AggregationFactory
|
||||||
|
implements Factory<Aggregation, io.opentelemetry.sdk.metrics.Aggregation> {
|
||||||
|
|
||||||
|
private static final AggregationFactory INSTANCE = new AggregationFactory();
|
||||||
|
|
||||||
|
private AggregationFactory() {}
|
||||||
|
|
||||||
|
static AggregationFactory getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public io.opentelemetry.sdk.metrics.Aggregation create(
|
||||||
|
@Nullable Aggregation model, SpiHelper spiHelper, List<Closeable> closeables) {
|
||||||
|
if (model == null) {
|
||||||
|
return io.opentelemetry.sdk.metrics.Aggregation.defaultAggregation();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.getDrop() != null) {
|
||||||
|
return io.opentelemetry.sdk.metrics.Aggregation.drop();
|
||||||
|
}
|
||||||
|
if (model.getSum() != null) {
|
||||||
|
return io.opentelemetry.sdk.metrics.Aggregation.sum();
|
||||||
|
}
|
||||||
|
if (model.getLastValue() != null) {
|
||||||
|
return io.opentelemetry.sdk.metrics.Aggregation.lastValue();
|
||||||
|
}
|
||||||
|
Base2ExponentialBucketHistogram exponentialBucketHistogram =
|
||||||
|
model.getBase2ExponentialBucketHistogram();
|
||||||
|
if (exponentialBucketHistogram != null) {
|
||||||
|
Integer maxScale = exponentialBucketHistogram.getMaxScale();
|
||||||
|
if (maxScale == null) {
|
||||||
|
maxScale = 20;
|
||||||
|
}
|
||||||
|
Integer maxSize = exponentialBucketHistogram.getMaxSize();
|
||||||
|
if (maxSize == null) {
|
||||||
|
maxSize = 160;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return io.opentelemetry.sdk.metrics.Aggregation.base2ExponentialBucketHistogram(
|
||||||
|
maxSize, maxScale);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new ConfigurationException("Invalid exponential bucket histogram", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExplicitBucketHistogram explicitBucketHistogram = model.getExplicitBucketHistogram();
|
||||||
|
if (explicitBucketHistogram != null) {
|
||||||
|
List<Double> boundaries = explicitBucketHistogram.getBoundaries();
|
||||||
|
if (boundaries == null) {
|
||||||
|
return io.opentelemetry.sdk.metrics.Aggregation.explicitBucketHistogram();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return io.opentelemetry.sdk.metrics.Aggregation.explicitBucketHistogram(boundaries);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new ConfigurationException("Invalid explicit bucket histogram", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return io.opentelemetry.sdk.metrics.Aggregation.defaultAggregation();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* 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.autoconfigure.spi.ConfigurationException;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Selector;
|
||||||
|
import io.opentelemetry.sdk.metrics.InstrumentSelector;
|
||||||
|
import io.opentelemetry.sdk.metrics.InstrumentSelectorBuilder;
|
||||||
|
import io.opentelemetry.sdk.metrics.InstrumentType;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
final class InstrumentSelectorFactory implements Factory<Selector, InstrumentSelector> {
|
||||||
|
|
||||||
|
private static final InstrumentSelectorFactory INSTANCE = new InstrumentSelectorFactory();
|
||||||
|
|
||||||
|
private InstrumentSelectorFactory() {}
|
||||||
|
|
||||||
|
static InstrumentSelectorFactory getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InstrumentSelector create(
|
||||||
|
@Nullable Selector model, SpiHelper spiHelper, List<Closeable> closeables) {
|
||||||
|
if (model == null) {
|
||||||
|
throw new ConfigurationException("selector must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrumentSelectorBuilder builder = InstrumentSelector.builder();
|
||||||
|
if (model.getInstrumentName() != null) {
|
||||||
|
builder.setName(model.getInstrumentName());
|
||||||
|
}
|
||||||
|
if (model.getInstrumentType() != null) {
|
||||||
|
InstrumentType instrumentType;
|
||||||
|
try {
|
||||||
|
instrumentType = InstrumentType.valueOf(model.getInstrumentType().name());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new ConfigurationException(
|
||||||
|
"Unrecognized instrument type: " + model.getInstrumentType(), e);
|
||||||
|
}
|
||||||
|
builder.setType(instrumentType);
|
||||||
|
}
|
||||||
|
if (model.getMeterName() != null) {
|
||||||
|
builder.setMeterName(model.getMeterName());
|
||||||
|
}
|
||||||
|
if (model.getMeterSchemaUrl() != null) {
|
||||||
|
builder.setMeterSchemaUrl(model.getMeterSchemaUrl());
|
||||||
|
}
|
||||||
|
if (model.getMeterVersion() != null) {
|
||||||
|
builder.setMeterVersion(model.getMeterVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return builder.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new ConfigurationException("Invalid selector", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,9 +45,22 @@ final class LogRecordExporterFactory
|
||||||
return LogRecordExporter.composite();
|
return LogRecordExporter.composite();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model.getOtlp() != null) {
|
Otlp otlpModel = model.getOtlp();
|
||||||
Otlp otlp = model.getOtlp();
|
if (otlpModel != null) {
|
||||||
|
return FileConfigUtil.addAndReturn(closeables, createOtlpExporter(otlpModel, spiHelper));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jack-berg): add support for generic SPI exporters
|
||||||
|
if (!model.getAdditionalProperties().isEmpty()) {
|
||||||
|
throw new ConfigurationException(
|
||||||
|
"Unrecognized log record exporter(s): "
|
||||||
|
+ model.getAdditionalProperties().keySet().stream().collect(joining(",", "[", "]")));
|
||||||
|
}
|
||||||
|
|
||||||
|
return LogRecordExporter.composite();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LogRecordExporter createOtlpExporter(Otlp otlp, SpiHelper spiHelper) {
|
||||||
// Translate from file configuration scheme to environment variable scheme. This is ultimately
|
// Translate from file configuration scheme to environment variable scheme. This is ultimately
|
||||||
// interpreted by Otlp*ExporterProviders, but we want to avoid the dependency on
|
// interpreted by Otlp*ExporterProviders, but we want to avoid the dependency on
|
||||||
// opentelemetry-exporter-otlp
|
// opentelemetry-exporter-otlp
|
||||||
|
@ -87,21 +100,9 @@ final class LogRecordExporterFactory
|
||||||
// TODO(jack-berg): add method for creating from map
|
// TODO(jack-berg): add method for creating from map
|
||||||
ConfigProperties configProperties = DefaultConfigProperties.createForTest(properties);
|
ConfigProperties configProperties = DefaultConfigProperties.createForTest(properties);
|
||||||
|
|
||||||
return FileConfigUtil.addAndReturn(
|
return FileConfigUtil.assertNotNull(
|
||||||
closeables,
|
|
||||||
FileConfigUtil.assertNotNull(
|
|
||||||
logRecordExporterSpiManager(configProperties, spiHelper).getByName("otlp"),
|
logRecordExporterSpiManager(configProperties, spiHelper).getByName("otlp"),
|
||||||
"otlp exporter"));
|
"otlp exporter");
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(jack-berg): add support for generic SPI exporters
|
|
||||||
if (!model.getAdditionalProperties().isEmpty()) {
|
|
||||||
throw new ConfigurationException(
|
|
||||||
"Unrecognized log record exporter(s): "
|
|
||||||
+ model.getAdditionalProperties().keySet().stream().collect(joining(",", "[", "]")));
|
|
||||||
}
|
|
||||||
|
|
||||||
return LogRecordExporter.composite();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NamedSpiManager<LogRecordExporter> logRecordExporterSpiManager(
|
private static NamedSpiManager<LogRecordExporter> logRecordExporterSpiManager(
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* 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.MeterProvider;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricReader;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.View;
|
||||||
|
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
|
||||||
|
import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
final class MeterProviderFactory implements Factory<MeterProvider, SdkMeterProviderBuilder> {
|
||||||
|
|
||||||
|
private static final MeterProviderFactory INSTANCE = new MeterProviderFactory();
|
||||||
|
|
||||||
|
private MeterProviderFactory() {}
|
||||||
|
|
||||||
|
static MeterProviderFactory getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SdkMeterProviderBuilder create(
|
||||||
|
@Nullable MeterProvider model, SpiHelper spiHelper, List<Closeable> closeables) {
|
||||||
|
if (model == null) {
|
||||||
|
return SdkMeterProvider.builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
SdkMeterProviderBuilder builder = SdkMeterProvider.builder();
|
||||||
|
|
||||||
|
List<MetricReader> readerModels = model.getReaders();
|
||||||
|
if (readerModels != null) {
|
||||||
|
readerModels.forEach(
|
||||||
|
readerModel -> {
|
||||||
|
io.opentelemetry.sdk.metrics.export.MetricReader metricReader =
|
||||||
|
MetricReaderFactory.getInstance().create(readerModel, spiHelper, closeables);
|
||||||
|
if (metricReader != null) {
|
||||||
|
builder.registerMetricReader(metricReader);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
List<View> viewModels = model.getViews();
|
||||||
|
if (viewModels != null) {
|
||||||
|
viewModels.forEach(
|
||||||
|
viewModel ->
|
||||||
|
builder.registerView(
|
||||||
|
InstrumentSelectorFactory.getInstance()
|
||||||
|
.create(viewModel.getSelector(), spiHelper, closeables),
|
||||||
|
ViewFactory.getInstance().create(viewModel.getStream(), spiHelper, closeables)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.sdk.extension.incubator.fileconfig;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.joining;
|
||||||
|
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.internal.NamedSpiManager;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpMetric;
|
||||||
|
import io.opentelemetry.sdk.metrics.export.MetricExporter;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
final class MetricExporterFactory
|
||||||
|
implements Factory<
|
||||||
|
io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricExporter,
|
||||||
|
MetricExporter> {
|
||||||
|
|
||||||
|
private static final MetricExporterFactory INSTANCE = new MetricExporterFactory();
|
||||||
|
|
||||||
|
private MetricExporterFactory() {}
|
||||||
|
|
||||||
|
static MetricExporterFactory getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("NullAway") // Override superclass non-null response
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public MetricExporter create(
|
||||||
|
@Nullable
|
||||||
|
io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricExporter model,
|
||||||
|
SpiHelper spiHelper,
|
||||||
|
List<Closeable> closeables) {
|
||||||
|
if (model == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
OtlpMetric otlpModel = model.getOtlp();
|
||||||
|
if (otlpModel != null) {
|
||||||
|
return FileConfigUtil.addAndReturn(closeables, createOtlpExporter(otlpModel, spiHelper));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.getConsole() != null) {
|
||||||
|
return FileConfigUtil.addAndReturn(closeables, createConsoleExporter(spiHelper));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.getPrometheus() != null) {
|
||||||
|
throw new ConfigurationException("prometheus exporter not supported in this context");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jack-berg): add support for generic SPI exporters
|
||||||
|
if (!model.getAdditionalProperties().isEmpty()) {
|
||||||
|
throw new ConfigurationException(
|
||||||
|
"Unrecognized metric exporter(s): "
|
||||||
|
+ model.getAdditionalProperties().keySet().stream().collect(joining(",", "[", "]")));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MetricExporter createOtlpExporter(OtlpMetric model, SpiHelper spiHelper) {
|
||||||
|
// Translate from file configuration scheme to environment variable scheme. This is ultimately
|
||||||
|
// interpreted by Otlp*ExporterProviders, but we want to avoid the dependency on
|
||||||
|
// opentelemetry-exporter-otlp
|
||||||
|
Map<String, String> properties = new HashMap<>();
|
||||||
|
if (model.getProtocol() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.metrics.protocol", model.getProtocol());
|
||||||
|
}
|
||||||
|
if (model.getEndpoint() != null) {
|
||||||
|
// NOTE: Set general otel.exporter.otlp.endpoint instead of signal specific
|
||||||
|
// otel.exporter.otlp.metrics.endpoint to allow signal path (i.e. /v1/metrics) to be added
|
||||||
|
// if not
|
||||||
|
// present
|
||||||
|
properties.put("otel.exporter.otlp.endpoint", model.getEndpoint());
|
||||||
|
}
|
||||||
|
if (model.getHeaders() != null) {
|
||||||
|
properties.put(
|
||||||
|
"otel.exporter.otlp.metrics.headers",
|
||||||
|
model.getHeaders().getAdditionalProperties().entrySet().stream()
|
||||||
|
.map(entry -> entry.getKey() + "=" + entry.getValue())
|
||||||
|
.collect(joining(",")));
|
||||||
|
}
|
||||||
|
if (model.getCompression() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.metrics.compression", model.getCompression());
|
||||||
|
}
|
||||||
|
if (model.getTimeout() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.metrics.timeout", Integer.toString(model.getTimeout()));
|
||||||
|
}
|
||||||
|
if (model.getCertificate() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.metrics.certificate", model.getCertificate());
|
||||||
|
}
|
||||||
|
if (model.getClientKey() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.metrics.client.key", model.getClientKey());
|
||||||
|
}
|
||||||
|
if (model.getClientCertificate() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.metrics.client.certificate", model.getClientCertificate());
|
||||||
|
}
|
||||||
|
if (model.getDefaultHistogramAggregation() != null) {
|
||||||
|
properties.put(
|
||||||
|
"otel.exporter.otlp.metrics.default.histogram.aggregation",
|
||||||
|
model.getDefaultHistogramAggregation().value());
|
||||||
|
}
|
||||||
|
if (model.getTemporalityPreference() != null) {
|
||||||
|
properties.put(
|
||||||
|
"otel.exporter.otlp.metrics.temporality.preference", model.getTemporalityPreference());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jack-berg): add method for creating from map
|
||||||
|
ConfigProperties configProperties = DefaultConfigProperties.createForTest(properties);
|
||||||
|
return FileConfigUtil.assertNotNull(
|
||||||
|
metricExporterSpiManager(configProperties, spiHelper).getByName("otlp"), "otlp exporter");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MetricExporter createConsoleExporter(SpiHelper spiHelper) {
|
||||||
|
return FileConfigUtil.assertNotNull(
|
||||||
|
metricExporterSpiManager(
|
||||||
|
DefaultConfigProperties.createForTest(Collections.emptyMap()), spiHelper)
|
||||||
|
.getByName("logging"),
|
||||||
|
"logging exporter");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NamedSpiManager<MetricExporter> metricExporterSpiManager(
|
||||||
|
ConfigProperties config, SpiHelper spiHelper) {
|
||||||
|
return spiHelper.loadConfigurable(
|
||||||
|
ConfigurableMetricExporterProvider.class,
|
||||||
|
ConfigurableMetricExporterProvider::getName,
|
||||||
|
ConfigurableMetricExporterProvider::createExporter,
|
||||||
|
config);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.sdk.extension.incubator.fileconfig;
|
||||||
|
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.internal.NamedSpiManager;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.internal.ConfigurableMetricReaderProvider;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricExporter;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PeriodicMetricReader;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Prometheus;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PullMetricReader;
|
||||||
|
import io.opentelemetry.sdk.metrics.export.MetricReader;
|
||||||
|
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReaderBuilder;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
final class MetricReaderFactory
|
||||||
|
implements Factory<
|
||||||
|
io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricReader,
|
||||||
|
MetricReader> {
|
||||||
|
|
||||||
|
private static final MetricReaderFactory INSTANCE = new MetricReaderFactory();
|
||||||
|
|
||||||
|
private MetricReaderFactory() {}
|
||||||
|
|
||||||
|
static MetricReaderFactory getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("NullAway") // Override superclass non-null response
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public MetricReader create(
|
||||||
|
@Nullable
|
||||||
|
io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricReader model,
|
||||||
|
SpiHelper spiHelper,
|
||||||
|
List<Closeable> closeables) {
|
||||||
|
if (model == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PeriodicMetricReader periodicModel = model.getPeriodic();
|
||||||
|
if (periodicModel != null) {
|
||||||
|
MetricExporter exporterModel = periodicModel.getExporter();
|
||||||
|
if (exporterModel == null) {
|
||||||
|
throw new ConfigurationException("exporter required for periodic reader");
|
||||||
|
}
|
||||||
|
io.opentelemetry.sdk.metrics.export.MetricExporter metricExporter =
|
||||||
|
MetricExporterFactory.getInstance().create(exporterModel, spiHelper, closeables);
|
||||||
|
if (metricExporter == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
PeriodicMetricReaderBuilder builder =
|
||||||
|
io.opentelemetry.sdk.metrics.export.PeriodicMetricReader.builder(
|
||||||
|
FileConfigUtil.addAndReturn(closeables, metricExporter));
|
||||||
|
if (periodicModel.getInterval() != null) {
|
||||||
|
builder.setInterval(Duration.ofMillis(periodicModel.getInterval()));
|
||||||
|
}
|
||||||
|
return FileConfigUtil.addAndReturn(closeables, builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
PullMetricReader pullModel = model.getPull();
|
||||||
|
if (pullModel != null) {
|
||||||
|
MetricExporter exporterModel = pullModel.getExporter();
|
||||||
|
if (exporterModel == null) {
|
||||||
|
throw new ConfigurationException("exporter required for pull reader");
|
||||||
|
}
|
||||||
|
Prometheus prometheusModel = exporterModel.getPrometheus();
|
||||||
|
if (prometheusModel != null) {
|
||||||
|
// Translate from file configuration scheme to environment variable scheme. This is
|
||||||
|
// ultimately
|
||||||
|
// interpreted by PrometheusMetricReaderProvider, but we want to avoid the dependency on
|
||||||
|
// opentelemetry-exporter-prometheus
|
||||||
|
Map<String, String> properties = new HashMap<>();
|
||||||
|
if (prometheusModel.getHost() != null) {
|
||||||
|
properties.put("otel.exporter.prometheus.host", prometheusModel.getHost());
|
||||||
|
}
|
||||||
|
if (prometheusModel.getPort() != null) {
|
||||||
|
properties.put(
|
||||||
|
"otel.exporter.prometheus.port", String.valueOf(prometheusModel.getPort()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jack-berg): add method for creating from map
|
||||||
|
ConfigProperties configProperties = DefaultConfigProperties.createForTest(properties);
|
||||||
|
|
||||||
|
return FileConfigUtil.addAndReturn(
|
||||||
|
closeables,
|
||||||
|
FileConfigUtil.assertNotNull(
|
||||||
|
metricReaderSpiManager(configProperties, spiHelper).getByName("prometheus"),
|
||||||
|
"prometheus reader"));
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ConfigurationException("prometheus is the only currently supported pull reader");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NamedSpiManager<io.opentelemetry.sdk.metrics.export.MetricReader>
|
||||||
|
metricReaderSpiManager(ConfigProperties config, SpiHelper spiHelper) {
|
||||||
|
return spiHelper.loadConfigurable(
|
||||||
|
ConfigurableMetricReaderProvider.class,
|
||||||
|
ConfigurableMetricReaderProvider::getName,
|
||||||
|
ConfigurableMetricReaderProvider::createMetricReader,
|
||||||
|
config);
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,7 +71,16 @@ final class OpenTelemetryConfigurationFactory
|
||||||
.build()));
|
.build()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jack-berg): add support for meter provider
|
if (model.getMeterProvider() != null) {
|
||||||
|
builder.setMeterProvider(
|
||||||
|
FileConfigUtil.addAndReturn(
|
||||||
|
closeables,
|
||||||
|
MeterProviderFactory.getInstance()
|
||||||
|
.create(model.getMeterProvider(), spiHelper, closeables)
|
||||||
|
.setResource(resource)
|
||||||
|
.build()));
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(jack-berg): add support for general attribute limits
|
// TODO(jack-berg): add support for general attribute limits
|
||||||
|
|
||||||
return FileConfigUtil.addAndReturn(closeables, builder.build());
|
return FileConfigUtil.addAndReturn(closeables, builder.build());
|
||||||
|
|
|
@ -16,6 +16,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterPro
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Otlp;
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Otlp;
|
||||||
import io.opentelemetry.sdk.trace.export.SpanExporter;
|
import io.opentelemetry.sdk.trace.export.SpanExporter;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -44,53 +45,19 @@ final class SpanExporterFactory
|
||||||
return SpanExporter.composite();
|
return SpanExporter.composite();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model.getOtlp() != null) {
|
Otlp otlpModel = model.getOtlp();
|
||||||
Otlp otlp = model.getOtlp();
|
if (otlpModel != null) {
|
||||||
|
return FileConfigUtil.addAndReturn(closeables, createOtlpExporter(otlpModel, spiHelper));
|
||||||
// Translate from file configuration scheme to environment variable scheme. This is ultimately
|
|
||||||
// interpreted by Otlp*ExporterProviders, but we want to avoid the dependency on
|
|
||||||
// opentelemetry-exporter-otlp
|
|
||||||
Map<String, String> properties = new HashMap<>();
|
|
||||||
if (otlp.getProtocol() != null) {
|
|
||||||
properties.put("otel.exporter.otlp.traces.protocol", otlp.getProtocol());
|
|
||||||
}
|
|
||||||
if (otlp.getEndpoint() != null) {
|
|
||||||
// NOTE: Set general otel.exporter.otlp.endpoint instead of signal specific
|
|
||||||
// otel.exporter.otlp.traces.endpoint to allow signal path (i.e. /v1/traces) to be added if
|
|
||||||
// not present
|
|
||||||
properties.put("otel.exporter.otlp.endpoint", otlp.getEndpoint());
|
|
||||||
}
|
|
||||||
if (otlp.getHeaders() != null) {
|
|
||||||
properties.put(
|
|
||||||
"otel.exporter.otlp.traces.headers",
|
|
||||||
otlp.getHeaders().getAdditionalProperties().entrySet().stream()
|
|
||||||
.map(entry -> entry.getKey() + "=" + entry.getValue())
|
|
||||||
.collect(joining(",")));
|
|
||||||
}
|
|
||||||
if (otlp.getCompression() != null) {
|
|
||||||
properties.put("otel.exporter.otlp.traces.compression", otlp.getCompression());
|
|
||||||
}
|
|
||||||
if (otlp.getTimeout() != null) {
|
|
||||||
properties.put("otel.exporter.otlp.traces.timeout", Integer.toString(otlp.getTimeout()));
|
|
||||||
}
|
|
||||||
if (otlp.getCertificate() != null) {
|
|
||||||
properties.put("otel.exporter.otlp.traces.certificate", otlp.getCertificate());
|
|
||||||
}
|
|
||||||
if (otlp.getClientKey() != null) {
|
|
||||||
properties.put("otel.exporter.otlp.traces.client.key", otlp.getClientKey());
|
|
||||||
}
|
|
||||||
if (otlp.getClientCertificate() != null) {
|
|
||||||
properties.put("otel.exporter.otlp.traces.client.certificate", otlp.getClientCertificate());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jack-berg): add method for creating from map
|
if (model.getConsole() != null) {
|
||||||
ConfigProperties configProperties = DefaultConfigProperties.createForTest(properties);
|
|
||||||
|
|
||||||
return FileConfigUtil.addAndReturn(
|
return FileConfigUtil.addAndReturn(
|
||||||
closeables,
|
closeables,
|
||||||
FileConfigUtil.assertNotNull(
|
FileConfigUtil.assertNotNull(
|
||||||
spanExporterSpiManager(configProperties, spiHelper).getByName("otlp"),
|
spanExporterSpiManager(
|
||||||
"otlp exporter"));
|
DefaultConfigProperties.createForTest(Collections.emptyMap()), spiHelper)
|
||||||
|
.getByName("logging"),
|
||||||
|
"logging exporter"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jack-berg): add support for generic SPI exporters
|
// TODO(jack-berg): add support for generic SPI exporters
|
||||||
|
@ -103,6 +70,50 @@ final class SpanExporterFactory
|
||||||
return SpanExporter.composite();
|
return SpanExporter.composite();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static SpanExporter createOtlpExporter(Otlp model, SpiHelper spiHelper) {
|
||||||
|
// Translate from file configuration scheme to environment variable scheme. This is ultimately
|
||||||
|
// interpreted by Otlp*ExporterProviders, but we want to avoid the dependency on
|
||||||
|
// opentelemetry-exporter-otlp
|
||||||
|
Map<String, String> properties = new HashMap<>();
|
||||||
|
if (model.getProtocol() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.traces.protocol", model.getProtocol());
|
||||||
|
}
|
||||||
|
if (model.getEndpoint() != null) {
|
||||||
|
// NOTE: Set general otel.exporter.otlp.endpoint instead of signal specific
|
||||||
|
// otel.exporter.otlp.traces.endpoint to allow signal path (i.e. /v1/traces) to be added if
|
||||||
|
// not present
|
||||||
|
properties.put("otel.exporter.otlp.endpoint", model.getEndpoint());
|
||||||
|
}
|
||||||
|
if (model.getHeaders() != null) {
|
||||||
|
properties.put(
|
||||||
|
"otel.exporter.otlp.traces.headers",
|
||||||
|
model.getHeaders().getAdditionalProperties().entrySet().stream()
|
||||||
|
.map(entry -> entry.getKey() + "=" + entry.getValue())
|
||||||
|
.collect(joining(",")));
|
||||||
|
}
|
||||||
|
if (model.getCompression() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.traces.compression", model.getCompression());
|
||||||
|
}
|
||||||
|
if (model.getTimeout() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.traces.timeout", Integer.toString(model.getTimeout()));
|
||||||
|
}
|
||||||
|
if (model.getCertificate() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.traces.certificate", model.getCertificate());
|
||||||
|
}
|
||||||
|
if (model.getClientKey() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.traces.client.key", model.getClientKey());
|
||||||
|
}
|
||||||
|
if (model.getClientCertificate() != null) {
|
||||||
|
properties.put("otel.exporter.otlp.traces.client.certificate", model.getClientCertificate());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jack-berg): add method for creating from map
|
||||||
|
ConfigProperties configProperties = DefaultConfigProperties.createForTest(properties);
|
||||||
|
|
||||||
|
return FileConfigUtil.assertNotNull(
|
||||||
|
spanExporterSpiManager(configProperties, spiHelper).getByName("otlp"), "otlp exporter");
|
||||||
|
}
|
||||||
|
|
||||||
private static NamedSpiManager<SpanExporter> spanExporterSpiManager(
|
private static NamedSpiManager<SpanExporter> spanExporterSpiManager(
|
||||||
ConfigProperties config, SpiHelper spiHelper) {
|
ConfigProperties config, SpiHelper spiHelper) {
|
||||||
return spiHelper.loadConfigurable(
|
return spiHelper.loadConfigurable(
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.autoconfigure.spi.ConfigurationException;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Stream;
|
||||||
|
import io.opentelemetry.sdk.metrics.View;
|
||||||
|
import io.opentelemetry.sdk.metrics.ViewBuilder;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
final class ViewFactory implements Factory<Stream, View> {
|
||||||
|
|
||||||
|
private static final ViewFactory INSTANCE = new ViewFactory();
|
||||||
|
|
||||||
|
private ViewFactory() {}
|
||||||
|
|
||||||
|
static ViewFactory getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View create(@Nullable Stream model, SpiHelper spiHelper, List<Closeable> closeables) {
|
||||||
|
if (model == null) {
|
||||||
|
throw new ConfigurationException("stream must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewBuilder builder = View.builder();
|
||||||
|
if (model.getName() != null) {
|
||||||
|
builder.setName(model.getName());
|
||||||
|
}
|
||||||
|
if (model.getDescription() != null) {
|
||||||
|
builder.setDescription(model.getDescription());
|
||||||
|
}
|
||||||
|
if (model.getAttributeKeys() != null) {
|
||||||
|
builder.setAttributeFilter(new HashSet<>(model.getAttributeKeys()));
|
||||||
|
}
|
||||||
|
if (model.getAggregation() != null) {
|
||||||
|
builder.setAggregation(
|
||||||
|
AggregationFactory.getInstance().create(model.getAggregation(), spiHelper, closeables));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* 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.Aggregation;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Base2ExponentialBucketHistogram;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExplicitBucketHistogram;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
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 AggregationFactoryTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Null() {
|
||||||
|
assertThat(
|
||||||
|
AggregationFactory.getInstance()
|
||||||
|
.create(null, mock(SpiHelper.class), Collections.emptyList())
|
||||||
|
.toString())
|
||||||
|
.isEqualTo(io.opentelemetry.sdk.metrics.Aggregation.defaultAggregation().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("createTestCases")
|
||||||
|
void create(Aggregation model, io.opentelemetry.sdk.metrics.Aggregation expectedResult) {
|
||||||
|
io.opentelemetry.sdk.metrics.Aggregation aggregation =
|
||||||
|
AggregationFactory.getInstance().create(model, mock(SpiHelper.class), new ArrayList<>());
|
||||||
|
assertThat(aggregation.toString()).isEqualTo(expectedResult.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Stream<Arguments> createTestCases() {
|
||||||
|
return Stream.of(
|
||||||
|
Arguments.of(
|
||||||
|
new Aggregation(), io.opentelemetry.sdk.metrics.Aggregation.defaultAggregation()),
|
||||||
|
Arguments.of(
|
||||||
|
new Aggregation().withDrop(new Object()),
|
||||||
|
io.opentelemetry.sdk.metrics.Aggregation.drop()),
|
||||||
|
Arguments.of(
|
||||||
|
new Aggregation().withSum(new Object()),
|
||||||
|
io.opentelemetry.sdk.metrics.Aggregation.sum()),
|
||||||
|
Arguments.of(
|
||||||
|
new Aggregation().withLastValue(new Object()),
|
||||||
|
io.opentelemetry.sdk.metrics.Aggregation.lastValue()),
|
||||||
|
Arguments.of(
|
||||||
|
new Aggregation()
|
||||||
|
.withBase2ExponentialBucketHistogram(new Base2ExponentialBucketHistogram()),
|
||||||
|
io.opentelemetry.sdk.metrics.Aggregation.base2ExponentialBucketHistogram()),
|
||||||
|
Arguments.of(
|
||||||
|
new Aggregation()
|
||||||
|
.withBase2ExponentialBucketHistogram(
|
||||||
|
new Base2ExponentialBucketHistogram().withMaxSize(1).withMaxScale(2)),
|
||||||
|
io.opentelemetry.sdk.metrics.Aggregation.base2ExponentialBucketHistogram(1, 2)),
|
||||||
|
Arguments.of(
|
||||||
|
new Aggregation()
|
||||||
|
.withExplicitBucketHistogram(new ExplicitBucketHistogram().withBoundaries(null)),
|
||||||
|
io.opentelemetry.sdk.metrics.Aggregation.explicitBucketHistogram()),
|
||||||
|
Arguments.of(
|
||||||
|
new Aggregation()
|
||||||
|
.withExplicitBucketHistogram(
|
||||||
|
new ExplicitBucketHistogram().withBoundaries(Arrays.asList(1.0, 2.0))),
|
||||||
|
io.opentelemetry.sdk.metrics.Aggregation.explicitBucketHistogram(
|
||||||
|
Arrays.asList(1.0, 2.0))));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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.Selector;
|
||||||
|
import io.opentelemetry.sdk.metrics.InstrumentSelector;
|
||||||
|
import io.opentelemetry.sdk.metrics.InstrumentType;
|
||||||
|
import java.util.Collections;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class InstrumentSelectorFactoryTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Null() {
|
||||||
|
assertThatThrownBy(
|
||||||
|
() ->
|
||||||
|
InstrumentSelectorFactory.getInstance()
|
||||||
|
.create(null, mock(SpiHelper.class), Collections.emptyList()))
|
||||||
|
.isInstanceOf(ConfigurationException.class)
|
||||||
|
.hasMessage("selector must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Defaults() {
|
||||||
|
assertThatThrownBy(
|
||||||
|
() ->
|
||||||
|
InstrumentSelectorFactory.getInstance()
|
||||||
|
.create(new Selector(), mock(SpiHelper.class), Collections.emptyList()))
|
||||||
|
.isInstanceOf(ConfigurationException.class)
|
||||||
|
.hasMessage("Invalid selector");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create() {
|
||||||
|
assertThat(
|
||||||
|
InstrumentSelectorFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new Selector()
|
||||||
|
.withInstrumentName("instrument-name")
|
||||||
|
.withInstrumentType(Selector.InstrumentType.COUNTER)
|
||||||
|
.withMeterName("meter-name")
|
||||||
|
.withMeterSchemaUrl("https://opentelemetry.io/schemas/1.16.0")
|
||||||
|
.withMeterVersion("1.0.0"),
|
||||||
|
mock(SpiHelper.class),
|
||||||
|
Collections.emptyList()))
|
||||||
|
.isEqualTo(
|
||||||
|
InstrumentSelector.builder()
|
||||||
|
.setName("instrument-name")
|
||||||
|
.setType(InstrumentType.COUNTER)
|
||||||
|
.setMeterName("meter-name")
|
||||||
|
.setMeterSchemaUrl("https://opentelemetry.io/schemas/1.16.0")
|
||||||
|
.setMeterVersion("1.0.0")
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,6 +56,16 @@ class LogRecordExporterFactoryTest {
|
||||||
private SpiHelper spiHelper =
|
private SpiHelper spiHelper =
|
||||||
SpiHelper.create(LogRecordExporterFactoryTest.class.getClassLoader());
|
SpiHelper.create(LogRecordExporterFactoryTest.class.getClassLoader());
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Null() {
|
||||||
|
LogRecordExporter expectedExporter = LogRecordExporter.composite();
|
||||||
|
|
||||||
|
LogRecordExporter exporter =
|
||||||
|
LogRecordExporterFactory.getInstance().create(null, spiHelper, new ArrayList<>());
|
||||||
|
|
||||||
|
assertThat(exporter.toString()).isEqualTo(expectedExporter.toString());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void create_OtlpDefaults() {
|
void create_OtlpDefaults() {
|
||||||
spiHelper = spy(spiHelper);
|
spiHelper = spy(spiHelper);
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* 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 io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
|
||||||
|
import io.opentelemetry.internal.testing.CleanupExtension;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MeterProvider;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricExporter;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricReader;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpMetric;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PeriodicMetricReader;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Selector;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Stream;
|
||||||
|
import io.opentelemetry.sdk.metrics.InstrumentSelector;
|
||||||
|
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
|
||||||
|
import io.opentelemetry.sdk.metrics.View;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
class MeterProviderFactoryTest {
|
||||||
|
|
||||||
|
@RegisterExtension CleanupExtension cleanup = new CleanupExtension();
|
||||||
|
|
||||||
|
private final SpiHelper spiHelper =
|
||||||
|
SpiHelper.create(MeterProviderFactoryTest.class.getClassLoader());
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Null() {
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
SdkMeterProvider expectedProvider = SdkMeterProvider.builder().build();
|
||||||
|
cleanup.addCloseable(expectedProvider);
|
||||||
|
|
||||||
|
SdkMeterProvider provider =
|
||||||
|
MeterProviderFactory.getInstance().create(null, spiHelper, closeables).build();
|
||||||
|
cleanup.addCloseable(provider);
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
|
||||||
|
assertThat(provider.toString()).isEqualTo(expectedProvider.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Defaults() {
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
SdkMeterProvider expectedProvider = SdkMeterProvider.builder().build();
|
||||||
|
cleanup.addCloseable(expectedProvider);
|
||||||
|
|
||||||
|
SdkMeterProvider provider =
|
||||||
|
MeterProviderFactory.getInstance()
|
||||||
|
.create(new MeterProvider(), spiHelper, closeables)
|
||||||
|
.build();
|
||||||
|
cleanup.addCloseable(provider);
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
|
||||||
|
assertThat(provider.toString()).isEqualTo(expectedProvider.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Configured() {
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
SdkMeterProvider expectedProvider =
|
||||||
|
SdkMeterProvider.builder()
|
||||||
|
.registerMetricReader(
|
||||||
|
io.opentelemetry.sdk.metrics.export.PeriodicMetricReader.builder(
|
||||||
|
OtlpGrpcMetricExporter.getDefault())
|
||||||
|
.build())
|
||||||
|
.registerView(
|
||||||
|
InstrumentSelector.builder().setName("instrument-name").build(),
|
||||||
|
View.builder().setName("stream-name").build())
|
||||||
|
.build();
|
||||||
|
cleanup.addCloseable(expectedProvider);
|
||||||
|
|
||||||
|
SdkMeterProvider provider =
|
||||||
|
MeterProviderFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new MeterProvider()
|
||||||
|
.withReaders(
|
||||||
|
Collections.singletonList(
|
||||||
|
new MetricReader()
|
||||||
|
.withPeriodic(
|
||||||
|
new PeriodicMetricReader()
|
||||||
|
.withExporter(
|
||||||
|
new MetricExporter().withOtlp(new OtlpMetric())))))
|
||||||
|
.withViews(
|
||||||
|
Collections.singletonList(
|
||||||
|
new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model
|
||||||
|
.View()
|
||||||
|
.withSelector(new Selector().withInstrumentName("instrument-name"))
|
||||||
|
.withStream(
|
||||||
|
new Stream().withName("stream-name").withAttributeKeys(null)))),
|
||||||
|
spiHelper,
|
||||||
|
closeables)
|
||||||
|
.build();
|
||||||
|
cleanup.addCloseable(provider);
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
|
||||||
|
assertThat(provider.toString()).isEqualTo(expectedProvider.toString());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,246 @@
|
||||||
|
/*
|
||||||
|
* Copyright The OpenTelemetry Authors
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.opentelemetry.sdk.extension.incubator.fileconfig;
|
||||||
|
|
||||||
|
import static io.opentelemetry.sdk.extension.incubator.fileconfig.FileConfigTestUtil.createTempFileWithContent;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
|
||||||
|
import io.opentelemetry.exporter.logging.LoggingMetricExporter;
|
||||||
|
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter;
|
||||||
|
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
|
||||||
|
import io.opentelemetry.internal.testing.CleanupExtension;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Console;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Headers;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpMetric;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpMetric.DefaultHistogramAggregation;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Prometheus;
|
||||||
|
import io.opentelemetry.sdk.metrics.export.MetricExporter;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.security.cert.CertificateEncodingException;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import org.mockito.junit.jupiter.MockitoSettings;
|
||||||
|
import org.mockito.quality.Strictness;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||||
|
class MetricExporterFactoryTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
static final SelfSignedCertificateExtension serverTls = new SelfSignedCertificateExtension();
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
static final SelfSignedCertificateExtension clientTls = new SelfSignedCertificateExtension();
|
||||||
|
|
||||||
|
@RegisterExtension CleanupExtension cleanup = new CleanupExtension();
|
||||||
|
|
||||||
|
private SpiHelper spiHelper = SpiHelper.create(MetricExporterFactoryTest.class.getClassLoader());
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Null() {
|
||||||
|
assertThat(MetricExporterFactory.getInstance().create(null, spiHelper, new ArrayList<>()))
|
||||||
|
.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_OtlpDefaults() {
|
||||||
|
spiHelper = spy(spiHelper);
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
OtlpGrpcMetricExporter expectedExporter = OtlpGrpcMetricExporter.getDefault();
|
||||||
|
cleanup.addCloseable(expectedExporter);
|
||||||
|
|
||||||
|
MetricExporter exporter =
|
||||||
|
MetricExporterFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model
|
||||||
|
.MetricExporter()
|
||||||
|
.withOtlp(new OtlpMetric()),
|
||||||
|
spiHelper,
|
||||||
|
closeables);
|
||||||
|
cleanup.addCloseable(exporter);
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
|
||||||
|
assertThat(exporter.toString()).isEqualTo(expectedExporter.toString());
|
||||||
|
|
||||||
|
ArgumentCaptor<ConfigProperties> configCaptor = ArgumentCaptor.forClass(ConfigProperties.class);
|
||||||
|
verify(spiHelper)
|
||||||
|
.loadConfigurable(
|
||||||
|
eq(ConfigurableMetricExporterProvider.class), any(), any(), configCaptor.capture());
|
||||||
|
ConfigProperties configProperties = configCaptor.getValue();
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.protocol")).isNull();
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.endpoint")).isNull();
|
||||||
|
assertThat(configProperties.getMap("otel.exporter.otlp.metrics.headers")).isEmpty();
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.compression")).isNull();
|
||||||
|
assertThat(configProperties.getDuration("otel.exporter.otlp.metrics.timeout")).isNull();
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.certificate")).isNull();
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.client.key")).isNull();
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.client.certificate"))
|
||||||
|
.isNull();
|
||||||
|
assertThat(
|
||||||
|
configProperties.getString("otel.exporter.otlp.metrics.default.histogram.aggregation"))
|
||||||
|
.isNull();
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.temporality.preference"))
|
||||||
|
.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_OtlpConfigured(@TempDir Path tempDir)
|
||||||
|
throws CertificateEncodingException, IOException {
|
||||||
|
spiHelper = spy(spiHelper);
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
OtlpHttpMetricExporter expectedExporter =
|
||||||
|
OtlpHttpMetricExporter.builder()
|
||||||
|
.setEndpoint("http://example:4318/v1/metrics")
|
||||||
|
.addHeader("key1", "value1")
|
||||||
|
.addHeader("key2", "value2")
|
||||||
|
.setTimeout(Duration.ofSeconds(15))
|
||||||
|
.setCompression("gzip")
|
||||||
|
.build();
|
||||||
|
cleanup.addCloseable(expectedExporter);
|
||||||
|
|
||||||
|
// Write certificates to temp files
|
||||||
|
String certificatePath =
|
||||||
|
createTempFileWithContent(
|
||||||
|
tempDir, "certificate.cert", serverTls.certificate().getEncoded());
|
||||||
|
String clientKeyPath =
|
||||||
|
createTempFileWithContent(tempDir, "clientKey.key", clientTls.privateKey().getEncoded());
|
||||||
|
String clientCertificatePath =
|
||||||
|
createTempFileWithContent(
|
||||||
|
tempDir, "clientCertificate.cert", clientTls.certificate().getEncoded());
|
||||||
|
|
||||||
|
MetricExporter exporter =
|
||||||
|
MetricExporterFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model
|
||||||
|
.MetricExporter()
|
||||||
|
.withOtlp(
|
||||||
|
new OtlpMetric()
|
||||||
|
.withProtocol("http/protobuf")
|
||||||
|
.withEndpoint("http://example:4318")
|
||||||
|
.withHeaders(
|
||||||
|
new Headers()
|
||||||
|
.withAdditionalProperty("key1", "value1")
|
||||||
|
.withAdditionalProperty("key2", "value2"))
|
||||||
|
.withCompression("gzip")
|
||||||
|
.withTimeout(15_000)
|
||||||
|
.withCertificate(certificatePath)
|
||||||
|
.withClientKey(clientKeyPath)
|
||||||
|
.withClientCertificate(clientCertificatePath)
|
||||||
|
.withTemporalityPreference("delta")
|
||||||
|
.withDefaultHistogramAggregation(
|
||||||
|
DefaultHistogramAggregation.BASE_2_EXPONENTIAL_BUCKET_HISTOGRAM)),
|
||||||
|
spiHelper,
|
||||||
|
closeables);
|
||||||
|
cleanup.addCloseable(exporter);
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
|
||||||
|
assertThat(exporter.toString()).isEqualTo(expectedExporter.toString());
|
||||||
|
|
||||||
|
ArgumentCaptor<ConfigProperties> configCaptor = ArgumentCaptor.forClass(ConfigProperties.class);
|
||||||
|
verify(spiHelper)
|
||||||
|
.loadConfigurable(
|
||||||
|
eq(ConfigurableMetricExporterProvider.class), any(), any(), configCaptor.capture());
|
||||||
|
ConfigProperties configProperties = configCaptor.getValue();
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.protocol"))
|
||||||
|
.isEqualTo("http/protobuf");
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.endpoint"))
|
||||||
|
.isEqualTo("http://example:4318");
|
||||||
|
assertThat(configProperties.getMap("otel.exporter.otlp.metrics.headers"))
|
||||||
|
.isEqualTo(ImmutableMap.of("key1", "value1", "key2", "value2"));
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.compression"))
|
||||||
|
.isEqualTo("gzip");
|
||||||
|
assertThat(configProperties.getDuration("otel.exporter.otlp.metrics.timeout"))
|
||||||
|
.isEqualTo(Duration.ofSeconds(15));
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.certificate"))
|
||||||
|
.isEqualTo(certificatePath);
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.client.key"))
|
||||||
|
.isEqualTo(clientKeyPath);
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.client.certificate"))
|
||||||
|
.isEqualTo(clientCertificatePath);
|
||||||
|
assertThat(configProperties.getString("otel.exporter.otlp.metrics.temporality.preference"))
|
||||||
|
.isEqualTo("delta");
|
||||||
|
assertThat(
|
||||||
|
configProperties.getString("otel.exporter.otlp.metrics.default.histogram.aggregation"))
|
||||||
|
.isEqualTo("base2_exponential_bucket_histogram");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Console() {
|
||||||
|
spiHelper = spy(spiHelper);
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
LoggingMetricExporter expectedExporter = LoggingMetricExporter.create();
|
||||||
|
cleanup.addCloseable(expectedExporter);
|
||||||
|
|
||||||
|
io.opentelemetry.sdk.metrics.export.MetricExporter exporter =
|
||||||
|
MetricExporterFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model
|
||||||
|
.MetricExporter()
|
||||||
|
.withConsole(new Console()),
|
||||||
|
spiHelper,
|
||||||
|
closeables);
|
||||||
|
cleanup.addCloseable(exporter);
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
|
||||||
|
assertThat(exporter.toString()).isEqualTo(expectedExporter.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_PrometheusExporter() {
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
|
||||||
|
assertThatThrownBy(
|
||||||
|
() ->
|
||||||
|
MetricExporterFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model
|
||||||
|
.MetricExporter()
|
||||||
|
.withPrometheus(new Prometheus()),
|
||||||
|
spiHelper,
|
||||||
|
new ArrayList<>()))
|
||||||
|
.isInstanceOf(ConfigurationException.class)
|
||||||
|
.hasMessage("prometheus exporter not supported in this context");
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_SpiExporter() {
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
|
||||||
|
assertThatThrownBy(
|
||||||
|
() ->
|
||||||
|
MetricExporterFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model
|
||||||
|
.MetricExporter()
|
||||||
|
.withAdditionalProperty("test", ImmutableMap.of("key1", "value1")),
|
||||||
|
spiHelper,
|
||||||
|
new ArrayList<>()))
|
||||||
|
.isInstanceOf(ConfigurationException.class)
|
||||||
|
.hasMessage("Unrecognized metric exporter(s): [test]");
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,238 @@
|
||||||
|
/*
|
||||||
|
* 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.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import io.github.netmikey.logunit.api.LogCapturer;
|
||||||
|
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
|
||||||
|
import io.opentelemetry.exporter.prometheus.PrometheusHttpServer;
|
||||||
|
import io.opentelemetry.internal.testing.CleanupExtension;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||||
|
import io.opentelemetry.sdk.autoconfigure.spi.internal.ConfigurableMetricReaderProvider;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricExporter;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricReader;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpMetric;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PeriodicMetricReader;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Prometheus;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PullMetricReader;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
|
class MetricReaderFactoryTest {
|
||||||
|
|
||||||
|
@RegisterExtension CleanupExtension cleanup = new CleanupExtension();
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
LogCapturer logCapturer =
|
||||||
|
LogCapturer.create().captureForLogger(ConfigurationFactory.class.getName());
|
||||||
|
|
||||||
|
private SpiHelper spiHelper = SpiHelper.create(MetricReaderFactoryTest.class.getClassLoader());
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Null() {
|
||||||
|
assertThat(MetricReaderFactory.getInstance().create(null, spiHelper, Collections.emptyList()))
|
||||||
|
.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_PeriodicNullExporter() {
|
||||||
|
assertThatThrownBy(
|
||||||
|
() ->
|
||||||
|
MetricReaderFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new MetricReader().withPeriodic(new PeriodicMetricReader()),
|
||||||
|
spiHelper,
|
||||||
|
Collections.emptyList()))
|
||||||
|
.isInstanceOf(ConfigurationException.class)
|
||||||
|
.hasMessage("exporter required for periodic reader");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_PeriodicDefaults() {
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
io.opentelemetry.sdk.metrics.export.PeriodicMetricReader expectedReader =
|
||||||
|
io.opentelemetry.sdk.metrics.export.PeriodicMetricReader.builder(
|
||||||
|
OtlpGrpcMetricExporter.getDefault())
|
||||||
|
.build();
|
||||||
|
cleanup.addCloseable(expectedReader);
|
||||||
|
|
||||||
|
io.opentelemetry.sdk.metrics.export.MetricReader reader =
|
||||||
|
MetricReaderFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new MetricReader()
|
||||||
|
.withPeriodic(
|
||||||
|
new PeriodicMetricReader()
|
||||||
|
.withExporter(new MetricExporter().withOtlp(new OtlpMetric()))),
|
||||||
|
spiHelper,
|
||||||
|
closeables);
|
||||||
|
cleanup.addCloseable(reader);
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
|
||||||
|
assertThat(reader.toString()).isEqualTo(expectedReader.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_PeriodicConfigured() {
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
io.opentelemetry.sdk.metrics.export.MetricReader expectedReader =
|
||||||
|
io.opentelemetry.sdk.metrics.export.PeriodicMetricReader.builder(
|
||||||
|
OtlpGrpcMetricExporter.getDefault())
|
||||||
|
.setInterval(Duration.ofMillis(1))
|
||||||
|
.build();
|
||||||
|
cleanup.addCloseable(expectedReader);
|
||||||
|
|
||||||
|
io.opentelemetry.sdk.metrics.export.MetricReader reader =
|
||||||
|
MetricReaderFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new MetricReader()
|
||||||
|
.withPeriodic(
|
||||||
|
new PeriodicMetricReader()
|
||||||
|
.withExporter(new MetricExporter().withOtlp(new OtlpMetric()))
|
||||||
|
.withInterval(1)),
|
||||||
|
spiHelper,
|
||||||
|
closeables);
|
||||||
|
cleanup.addCloseable(reader);
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
|
||||||
|
assertThat(reader.toString()).isEqualTo(expectedReader.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_PullPrometheusDefault() throws IOException {
|
||||||
|
int port = randomAvailablePort();
|
||||||
|
spiHelper = spy(spiHelper);
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
PrometheusHttpServer expectedReader = PrometheusHttpServer.builder().setPort(port).build();
|
||||||
|
// Close the reader to avoid port conflict with the new instance created by MetricReaderFactory
|
||||||
|
expectedReader.close();
|
||||||
|
|
||||||
|
io.opentelemetry.sdk.metrics.export.MetricReader reader =
|
||||||
|
MetricReaderFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new MetricReader()
|
||||||
|
.withPull(
|
||||||
|
new PullMetricReader()
|
||||||
|
.withExporter(
|
||||||
|
new MetricExporter()
|
||||||
|
.withPrometheus(new Prometheus().withPort(port)))),
|
||||||
|
spiHelper,
|
||||||
|
closeables);
|
||||||
|
cleanup.addCloseable(reader);
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
|
||||||
|
assertThat(reader.toString()).isEqualTo(expectedReader.toString());
|
||||||
|
|
||||||
|
ArgumentCaptor<ConfigProperties> configCaptor = ArgumentCaptor.forClass(ConfigProperties.class);
|
||||||
|
verify(spiHelper)
|
||||||
|
.loadConfigurable(
|
||||||
|
eq(ConfigurableMetricReaderProvider.class), any(), any(), configCaptor.capture());
|
||||||
|
ConfigProperties configProperties = configCaptor.getValue();
|
||||||
|
assertThat(configProperties.getString("otel.exporter.prometheus.host")).isNull();
|
||||||
|
assertThat(configProperties.getInt("otel.exporter.prometheus.port")).isEqualTo(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_PullPrometheusConfigured() throws IOException {
|
||||||
|
int port = randomAvailablePort();
|
||||||
|
|
||||||
|
spiHelper = spy(spiHelper);
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
PrometheusHttpServer expectedReader =
|
||||||
|
PrometheusHttpServer.builder().setHost("localhost").setPort(port).build();
|
||||||
|
// Close the reader to avoid port conflict with the new instance created by MetricReaderFactory
|
||||||
|
expectedReader.close();
|
||||||
|
|
||||||
|
io.opentelemetry.sdk.metrics.export.MetricReader reader =
|
||||||
|
MetricReaderFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new MetricReader()
|
||||||
|
.withPull(
|
||||||
|
new PullMetricReader()
|
||||||
|
.withExporter(
|
||||||
|
new MetricExporter()
|
||||||
|
.withPrometheus(
|
||||||
|
new Prometheus().withHost("localhost").withPort(port)))),
|
||||||
|
spiHelper,
|
||||||
|
closeables);
|
||||||
|
cleanup.addCloseable(reader);
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
|
||||||
|
assertThat(reader.toString()).isEqualTo(expectedReader.toString());
|
||||||
|
|
||||||
|
ArgumentCaptor<ConfigProperties> configCaptor = ArgumentCaptor.forClass(ConfigProperties.class);
|
||||||
|
verify(spiHelper)
|
||||||
|
.loadConfigurable(
|
||||||
|
eq(ConfigurableMetricReaderProvider.class), any(), any(), configCaptor.capture());
|
||||||
|
ConfigProperties configProperties = configCaptor.getValue();
|
||||||
|
assertThat(configProperties.getString("otel.exporter.prometheus.host")).isEqualTo("localhost");
|
||||||
|
assertThat(configProperties.getInt("otel.exporter.prometheus.port")).isEqualTo(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_InvalidPullReader() {
|
||||||
|
assertThatThrownBy(
|
||||||
|
() ->
|
||||||
|
MetricReaderFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new MetricReader().withPull(new PullMetricReader()),
|
||||||
|
spiHelper,
|
||||||
|
Collections.emptyList()))
|
||||||
|
.isInstanceOf(ConfigurationException.class)
|
||||||
|
.hasMessage("exporter required for pull reader");
|
||||||
|
|
||||||
|
assertThatThrownBy(
|
||||||
|
() ->
|
||||||
|
MetricReaderFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new MetricReader()
|
||||||
|
.withPull(new PullMetricReader().withExporter(new MetricExporter())),
|
||||||
|
spiHelper,
|
||||||
|
Collections.emptyList()))
|
||||||
|
.isInstanceOf(ConfigurationException.class)
|
||||||
|
.hasMessage("prometheus is the only currently supported pull reader");
|
||||||
|
|
||||||
|
assertThatThrownBy(
|
||||||
|
() ->
|
||||||
|
MetricReaderFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new MetricReader()
|
||||||
|
.withPull(
|
||||||
|
new PullMetricReader()
|
||||||
|
.withExporter(new MetricExporter().withOtlp(new OtlpMetric()))),
|
||||||
|
spiHelper,
|
||||||
|
Collections.emptyList()))
|
||||||
|
.isInstanceOf(ConfigurationException.class)
|
||||||
|
.hasMessage("prometheus is the only currently supported pull reader");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a random unused port. There's a small race if another process takes it before we
|
||||||
|
* initialize. Consider adding retries to this test if it flakes, presumably it never will on CI
|
||||||
|
* since there's no prometheus there blocking the well-known port.
|
||||||
|
*/
|
||||||
|
private static int randomAvailablePort() throws IOException {
|
||||||
|
try (ServerSocket socket2 = new ServerSocket(0)) {
|
||||||
|
return socket2.getLocalPort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
|
||||||
import io.opentelemetry.context.propagation.ContextPropagators;
|
import io.opentelemetry.context.propagation.ContextPropagators;
|
||||||
import io.opentelemetry.context.propagation.TextMapPropagator;
|
import io.opentelemetry.context.propagation.TextMapPropagator;
|
||||||
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter;
|
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter;
|
||||||
|
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
|
||||||
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
|
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
|
||||||
import io.opentelemetry.extension.trace.propagation.B3Propagator;
|
import io.opentelemetry.extension.trace.propagation.B3Propagator;
|
||||||
import io.opentelemetry.extension.trace.propagation.JaegerPropagator;
|
import io.opentelemetry.extension.trace.propagation.JaegerPropagator;
|
||||||
|
@ -30,16 +31,26 @@ import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRec
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordLimits;
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordLimits;
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordProcessor;
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LogRecordProcessor;
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LoggerProvider;
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.LoggerProvider;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MeterProvider;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricExporter;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.MetricReader;
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OpenTelemetryConfiguration;
|
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.Otlp;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.OtlpMetric;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.PeriodicMetricReader;
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Resource;
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Resource;
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Sampler;
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Sampler;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Selector;
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleLogRecordProcessor;
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SimpleLogRecordProcessor;
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.SpanExporter;
|
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.SpanProcessor;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Stream;
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProvider;
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.TracerProvider;
|
||||||
import io.opentelemetry.sdk.logs.LogLimits;
|
import io.opentelemetry.sdk.logs.LogLimits;
|
||||||
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
|
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
|
||||||
|
import io.opentelemetry.sdk.metrics.InstrumentSelector;
|
||||||
|
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
|
||||||
|
import io.opentelemetry.sdk.metrics.View;
|
||||||
import io.opentelemetry.sdk.trace.SdkTracerProvider;
|
import io.opentelemetry.sdk.trace.SdkTracerProvider;
|
||||||
import io.opentelemetry.sdk.trace.SpanLimits;
|
import io.opentelemetry.sdk.trace.SpanLimits;
|
||||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||||
|
@ -194,6 +205,17 @@ class OpenTelemetryConfigurationFactoryTest {
|
||||||
OtlpGrpcSpanExporter.getDefault())
|
OtlpGrpcSpanExporter.getDefault())
|
||||||
.build())
|
.build())
|
||||||
.build())
|
.build())
|
||||||
|
.setMeterProvider(
|
||||||
|
SdkMeterProvider.builder()
|
||||||
|
.setResource(expectedResource)
|
||||||
|
.registerMetricReader(
|
||||||
|
io.opentelemetry.sdk.metrics.export.PeriodicMetricReader.builder(
|
||||||
|
OtlpGrpcMetricExporter.getDefault())
|
||||||
|
.build())
|
||||||
|
.registerView(
|
||||||
|
InstrumentSelector.builder().setName("instrument-name").build(),
|
||||||
|
View.builder().setName("stream-name").build())
|
||||||
|
.build())
|
||||||
.build();
|
.build();
|
||||||
cleanup.addCloseable(expectedSdk);
|
cleanup.addCloseable(expectedSdk);
|
||||||
|
|
||||||
|
@ -243,7 +265,27 @@ class OpenTelemetryConfigurationFactoryTest {
|
||||||
.withBatch(
|
.withBatch(
|
||||||
new BatchSpanProcessor()
|
new BatchSpanProcessor()
|
||||||
.withExporter(
|
.withExporter(
|
||||||
new SpanExporter().withOtlp(new Otlp())))))),
|
new SpanExporter().withOtlp(new Otlp()))))))
|
||||||
|
.withMeterProvider(
|
||||||
|
new MeterProvider()
|
||||||
|
.withReaders(
|
||||||
|
Collections.singletonList(
|
||||||
|
new MetricReader()
|
||||||
|
.withPeriodic(
|
||||||
|
new PeriodicMetricReader()
|
||||||
|
.withExporter(
|
||||||
|
new MetricExporter()
|
||||||
|
.withOtlp(new OtlpMetric())))))
|
||||||
|
.withViews(
|
||||||
|
Collections.singletonList(
|
||||||
|
new io.opentelemetry.sdk.extension.incubator.fileconfig.internal
|
||||||
|
.model.View()
|
||||||
|
.withSelector(
|
||||||
|
new Selector().withInstrumentName("instrument-name"))
|
||||||
|
.withStream(
|
||||||
|
new Stream()
|
||||||
|
.withName("stream-name")
|
||||||
|
.withAttributeKeys(null))))),
|
||||||
spiHelper,
|
spiHelper,
|
||||||
closeables);
|
closeables);
|
||||||
cleanup.addCloseable(sdk);
|
cleanup.addCloseable(sdk);
|
||||||
|
|
|
@ -15,6 +15,7 @@ import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
|
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
|
||||||
|
import io.opentelemetry.exporter.logging.LoggingSpanExporter;
|
||||||
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
|
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
|
||||||
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
|
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
|
||||||
import io.opentelemetry.internal.testing.CleanupExtension;
|
import io.opentelemetry.internal.testing.CleanupExtension;
|
||||||
|
@ -22,6 +23,7 @@ import io.opentelemetry.sdk.autoconfigure.internal.SpiHelper;
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||||
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
|
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Console;
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Headers;
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Headers;
|
||||||
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Otlp;
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Otlp;
|
||||||
import io.opentelemetry.sdk.trace.export.SpanExporter;
|
import io.opentelemetry.sdk.trace.export.SpanExporter;
|
||||||
|
@ -163,6 +165,27 @@ class SpanExporterFactoryTest {
|
||||||
.isEqualTo(clientCertificatePath);
|
.isEqualTo(clientCertificatePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Console() {
|
||||||
|
spiHelper = spy(spiHelper);
|
||||||
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
LoggingSpanExporter expectedExporter = LoggingSpanExporter.create();
|
||||||
|
cleanup.addCloseable(expectedExporter);
|
||||||
|
|
||||||
|
SpanExporter exporter =
|
||||||
|
SpanExporterFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model
|
||||||
|
.SpanExporter()
|
||||||
|
.withConsole(new Console()),
|
||||||
|
spiHelper,
|
||||||
|
closeables);
|
||||||
|
cleanup.addCloseable(exporter);
|
||||||
|
cleanup.addCloseables(closeables);
|
||||||
|
|
||||||
|
assertThat(exporter.toString()).isEqualTo(expectedExporter.toString());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void create_SpiExporter() {
|
void create_SpiExporter() {
|
||||||
List<Closeable> closeables = new ArrayList<>();
|
List<Closeable> closeables = new ArrayList<>();
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* 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.Aggregation;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.ExplicitBucketHistogram;
|
||||||
|
import io.opentelemetry.sdk.extension.incubator.fileconfig.internal.model.Stream;
|
||||||
|
import io.opentelemetry.sdk.metrics.View;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class ViewFactoryTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Null() {
|
||||||
|
assertThatThrownBy(
|
||||||
|
() ->
|
||||||
|
ViewFactory.getInstance()
|
||||||
|
.create(null, mock(SpiHelper.class), Collections.emptyList()))
|
||||||
|
.isInstanceOf(ConfigurationException.class)
|
||||||
|
.hasMessage("stream must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create_Defaults() {
|
||||||
|
View expectedView = View.builder().build();
|
||||||
|
|
||||||
|
View view =
|
||||||
|
ViewFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new Stream().withAttributeKeys(null),
|
||||||
|
mock(SpiHelper.class),
|
||||||
|
Collections.emptyList());
|
||||||
|
|
||||||
|
assertThat(view.toString()).isEqualTo(expectedView.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void create() {
|
||||||
|
View expectedView =
|
||||||
|
View.builder()
|
||||||
|
.setName("name")
|
||||||
|
.setDescription("description")
|
||||||
|
.setAttributeFilter(new HashSet<>(Arrays.asList("foo", "bar")))
|
||||||
|
.setAggregation(
|
||||||
|
io.opentelemetry.sdk.metrics.Aggregation.explicitBucketHistogram(
|
||||||
|
Arrays.asList(1.0, 2.0)))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
View view =
|
||||||
|
ViewFactory.getInstance()
|
||||||
|
.create(
|
||||||
|
new Stream()
|
||||||
|
.withName("name")
|
||||||
|
.withDescription("description")
|
||||||
|
.withAttributeKeys(Arrays.asList("foo", "bar"))
|
||||||
|
.withAggregation(
|
||||||
|
new Aggregation()
|
||||||
|
.withExplicitBucketHistogram(
|
||||||
|
new ExplicitBucketHistogram()
|
||||||
|
.withBoundaries(Arrays.asList(1.0, 2.0)))),
|
||||||
|
mock(SpiHelper.class),
|
||||||
|
Collections.emptyList());
|
||||||
|
|
||||||
|
assertThat(view.toString()).isEqualTo(expectedView.toString());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue