Meter provider configuration factory (#5773)
This commit is contained in:
parent
7229c45513
commit
01503efe97
|
@ -1,2 +1,10 @@
|
|||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LoggingMetricExporter{}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,4 +93,9 @@ public final class LoggingSpanExporter implements SpanExporter {
|
|||
}
|
||||
return flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LoggingSpanExporter{}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,4 +95,9 @@ public class SystemOutLogRecordExporter implements LogRecordExporter {
|
|||
}
|
||||
return CompletableResultCode.ofSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SystemOutLogRecordExporter{}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,4 +114,9 @@ class LoggingMetricExporterTest {
|
|||
assertThat(exporter.shutdown().isSuccess()).isTrue();
|
||||
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();
|
||||
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();
|
||||
}
|
||||
|
||||
@Test
|
||||
void stringRepresentation() {
|
||||
assertThat(SystemOutLogRecordExporter.create().toString())
|
||||
.isEqualTo("SystemOutLogRecordExporter{}");
|
||||
}
|
||||
|
||||
private static LogRecordData sampleLog(long timestamp) {
|
||||
return TestLogRecordData.builder()
|
||||
.setResource(Resource.empty())
|
||||
|
|
|
@ -33,6 +33,8 @@ dependencies {
|
|||
testImplementation(project(":sdk:testing"))
|
||||
testImplementation(project(":sdk-extensions:autoconfigure"))
|
||||
testImplementation(project(":exporters:otlp:all"))
|
||||
testImplementation(project(":exporters:prometheus"))
|
||||
testImplementation(project(":exporters:logging"))
|
||||
testImplementation(project(":sdk-extensions:jaeger-remote-sampler"))
|
||||
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
|
||||
|
|
|
@ -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,53 +45,9 @@ final class LogRecordExporterFactory
|
|||
return LogRecordExporter.composite();
|
||||
}
|
||||
|
||||
if (model.getOtlp() != null) {
|
||||
Otlp otlp = model.getOtlp();
|
||||
|
||||
// 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.logs.protocol", otlp.getProtocol());
|
||||
}
|
||||
if (otlp.getEndpoint() != null) {
|
||||
// NOTE: Set general otel.exporter.otlp.endpoint instead of signal specific
|
||||
// otel.exporter.otlp.logs.endpoint to allow signal path (i.e. /v1/logs) to be added if not
|
||||
// present
|
||||
properties.put("otel.exporter.otlp.endpoint", otlp.getEndpoint());
|
||||
}
|
||||
if (otlp.getHeaders() != null) {
|
||||
properties.put(
|
||||
"otel.exporter.otlp.logs.headers",
|
||||
otlp.getHeaders().getAdditionalProperties().entrySet().stream()
|
||||
.map(entry -> entry.getKey() + "=" + entry.getValue())
|
||||
.collect(joining(",")));
|
||||
}
|
||||
if (otlp.getCompression() != null) {
|
||||
properties.put("otel.exporter.otlp.logs.compression", otlp.getCompression());
|
||||
}
|
||||
if (otlp.getTimeout() != null) {
|
||||
properties.put("otel.exporter.otlp.logs.timeout", Integer.toString(otlp.getTimeout()));
|
||||
}
|
||||
if (otlp.getCertificate() != null) {
|
||||
properties.put("otel.exporter.otlp.logs.certificate", otlp.getCertificate());
|
||||
}
|
||||
if (otlp.getClientKey() != null) {
|
||||
properties.put("otel.exporter.otlp.logs.client.key", otlp.getClientKey());
|
||||
}
|
||||
if (otlp.getClientCertificate() != null) {
|
||||
properties.put("otel.exporter.otlp.logs.client.certificate", otlp.getClientCertificate());
|
||||
}
|
||||
|
||||
// TODO(jack-berg): add method for creating from map
|
||||
ConfigProperties configProperties = DefaultConfigProperties.createForTest(properties);
|
||||
|
||||
return FileConfigUtil.addAndReturn(
|
||||
closeables,
|
||||
FileConfigUtil.assertNotNull(
|
||||
logRecordExporterSpiManager(configProperties, spiHelper).getByName("otlp"),
|
||||
"otlp exporter"));
|
||||
Otlp otlpModel = model.getOtlp();
|
||||
if (otlpModel != null) {
|
||||
return FileConfigUtil.addAndReturn(closeables, createOtlpExporter(otlpModel, spiHelper));
|
||||
}
|
||||
|
||||
// TODO(jack-berg): add support for generic SPI exporters
|
||||
|
@ -104,6 +60,51 @@ final class LogRecordExporterFactory
|
|||
return LogRecordExporter.composite();
|
||||
}
|
||||
|
||||
private static LogRecordExporter createOtlpExporter(Otlp otlp, 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 (otlp.getProtocol() != null) {
|
||||
properties.put("otel.exporter.otlp.logs.protocol", otlp.getProtocol());
|
||||
}
|
||||
if (otlp.getEndpoint() != null) {
|
||||
// NOTE: Set general otel.exporter.otlp.endpoint instead of signal specific
|
||||
// otel.exporter.otlp.logs.endpoint to allow signal path (i.e. /v1/logs) to be added if not
|
||||
// present
|
||||
properties.put("otel.exporter.otlp.endpoint", otlp.getEndpoint());
|
||||
}
|
||||
if (otlp.getHeaders() != null) {
|
||||
properties.put(
|
||||
"otel.exporter.otlp.logs.headers",
|
||||
otlp.getHeaders().getAdditionalProperties().entrySet().stream()
|
||||
.map(entry -> entry.getKey() + "=" + entry.getValue())
|
||||
.collect(joining(",")));
|
||||
}
|
||||
if (otlp.getCompression() != null) {
|
||||
properties.put("otel.exporter.otlp.logs.compression", otlp.getCompression());
|
||||
}
|
||||
if (otlp.getTimeout() != null) {
|
||||
properties.put("otel.exporter.otlp.logs.timeout", Integer.toString(otlp.getTimeout()));
|
||||
}
|
||||
if (otlp.getCertificate() != null) {
|
||||
properties.put("otel.exporter.otlp.logs.certificate", otlp.getCertificate());
|
||||
}
|
||||
if (otlp.getClientKey() != null) {
|
||||
properties.put("otel.exporter.otlp.logs.client.key", otlp.getClientKey());
|
||||
}
|
||||
if (otlp.getClientCertificate() != null) {
|
||||
properties.put("otel.exporter.otlp.logs.client.certificate", otlp.getClientCertificate());
|
||||
}
|
||||
|
||||
// TODO(jack-berg): add method for creating from map
|
||||
ConfigProperties configProperties = DefaultConfigProperties.createForTest(properties);
|
||||
|
||||
return FileConfigUtil.assertNotNull(
|
||||
logRecordExporterSpiManager(configProperties, spiHelper).getByName("otlp"),
|
||||
"otlp exporter");
|
||||
}
|
||||
|
||||
private static NamedSpiManager<LogRecordExporter> logRecordExporterSpiManager(
|
||||
ConfigProperties config, SpiHelper spiHelper) {
|
||||
return spiHelper.loadConfigurable(
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
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.trace.export.SpanExporter;
|
||||
import java.io.Closeable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -44,53 +45,19 @@ final class SpanExporterFactory
|
|||
return SpanExporter.composite();
|
||||
}
|
||||
|
||||
if (model.getOtlp() != null) {
|
||||
Otlp otlp = model.getOtlp();
|
||||
|
||||
// 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
|
||||
ConfigProperties configProperties = DefaultConfigProperties.createForTest(properties);
|
||||
Otlp otlpModel = model.getOtlp();
|
||||
if (otlpModel != null) {
|
||||
return FileConfigUtil.addAndReturn(closeables, createOtlpExporter(otlpModel, spiHelper));
|
||||
}
|
||||
|
||||
if (model.getConsole() != null) {
|
||||
return FileConfigUtil.addAndReturn(
|
||||
closeables,
|
||||
FileConfigUtil.assertNotNull(
|
||||
spanExporterSpiManager(configProperties, spiHelper).getByName("otlp"),
|
||||
"otlp exporter"));
|
||||
spanExporterSpiManager(
|
||||
DefaultConfigProperties.createForTest(Collections.emptyMap()), spiHelper)
|
||||
.getByName("logging"),
|
||||
"logging exporter"));
|
||||
}
|
||||
|
||||
// TODO(jack-berg): add support for generic SPI exporters
|
||||
|
@ -103,6 +70,50 @@ final class SpanExporterFactory
|
|||
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(
|
||||
ConfigProperties config, SpiHelper spiHelper) {
|
||||
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 =
|
||||
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
|
||||
void create_OtlpDefaults() {
|
||||
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.TextMapPropagator;
|
||||
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter;
|
||||
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
|
||||
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
|
||||
import io.opentelemetry.extension.trace.propagation.B3Propagator;
|
||||
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.LogRecordProcessor;
|
||||
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.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.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.SpanExporter;
|
||||
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.logs.LogLimits;
|
||||
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.SpanLimits;
|
||||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
|
@ -194,6 +205,17 @@ class OpenTelemetryConfigurationFactoryTest {
|
|||
OtlpGrpcSpanExporter.getDefault())
|
||||
.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();
|
||||
cleanup.addCloseable(expectedSdk);
|
||||
|
||||
|
@ -243,7 +265,27 @@ class OpenTelemetryConfigurationFactoryTest {
|
|||
.withBatch(
|
||||
new BatchSpanProcessor()
|
||||
.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,
|
||||
closeables);
|
||||
cleanup.addCloseable(sdk);
|
||||
|
|
|
@ -15,6 +15,7 @@ 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.LoggingSpanExporter;
|
||||
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
|
||||
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
|
||||
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.ConfigurationException;
|
||||
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.Otlp;
|
||||
import io.opentelemetry.sdk.trace.export.SpanExporter;
|
||||
|
@ -163,6 +165,27 @@ class SpanExporterFactoryTest {
|
|||
.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
|
||||
void create_SpiExporter() {
|
||||
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