Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Meter provider configuration factory #5773

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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()
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,9 @@ public CompletableResultCode shutdown() {
}
return flush();
}

@Override
public String toString() {
return "LoggingMetricExporter{}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,9 @@ public CompletableResultCode shutdown() {
}
return flush();
}

@Override
public String toString() {
return "LoggingSpanExporter{}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,9 @@ public CompletableResultCode shutdown() {
}
return CompletableResultCode.ofSuccess();
}

@Override
public String toString() {
return "SystemOutLogRecordExporter{}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,9 @@ void shutdown() {
assertThat(exporter.shutdown().isSuccess()).isTrue();
logs.assertContains("Calling shutdown() multiple times.");
}

@Test
void stringRepresentation() {
assertThat(LoggingMetricExporter.create().toString()).isEqualTo("LoggingMetricExporter{}");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,9 @@ void shutdown() {
assertThat(exporter.shutdown().isSuccess()).isTrue();
logs.assertContains("Calling shutdown() multiple times.");
}

@Test
void stringRepresentation() {
assertThat(LoggingSpanExporter.create().toString()).isEqualTo("LoggingSpanExporter{}");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ void shutdown() {
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())
Expand Down
2 changes: 2 additions & 0 deletions sdk-extensions/incubator/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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);

Check warning on line 59 in sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/AggregationFactory.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/AggregationFactory.java#L58-L59

Added lines #L58 - L59 were not covered by tests
}
}
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);

Check warning on line 71 in sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/AggregationFactory.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/AggregationFactory.java#L70-L71

Added lines #L70 - L71 were not covered by tests
}
}

return io.opentelemetry.sdk.metrics.Aggregation.defaultAggregation();
}
}
Original file line number Diff line number Diff line change
@@ -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);

Check warning on line 45 in sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/InstrumentSelectorFactory.java

View check run for this annotation

Codecov / codecov/patch

sdk-extensions/incubator/src/main/java/io/opentelemetry/sdk/extension/incubator/fileconfig/InstrumentSelectorFactory.java#L43-L45

Added lines #L43 - L45 were not covered by tests
}
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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,53 +45,9 @@ public LogRecordExporter create(
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
Expand All @@ -104,6 +60,51 @@ public LogRecordExporter create(
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(
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}