Metric exporter REUSABLE_DATA memory mode configuration options (#6304)
This commit is contained in:
parent
ff0480c354
commit
4d8f4f3111
|
@ -1,2 +1,7 @@
|
|||
Comparing source compatibility of against
|
||||
No changes.
|
||||
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter (not serializable)
|
||||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
|
||||
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.export.MemoryMode getMemoryMode()
|
||||
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter (not serializable)
|
||||
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
|
||||
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.export.MemoryMode getMemoryMode()
|
||||
|
|
|
@ -11,6 +11,7 @@ otelJava.moduleName.set("io.opentelemetry.exporter.internal")
|
|||
val versions: Map<String, String> by project
|
||||
dependencies {
|
||||
api(project(":api:all"))
|
||||
api(project(":sdk-extensions:autoconfigure-spi"))
|
||||
|
||||
compileOnly(project(":sdk:common"))
|
||||
|
||||
|
|
|
@ -5,8 +5,13 @@
|
|||
|
||||
package io.opentelemetry.exporter.internal;
|
||||
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Utilities for exporter builders.
|
||||
|
@ -33,5 +38,21 @@ public final class ExporterBuilderUtil {
|
|||
return uri;
|
||||
}
|
||||
|
||||
/** Invoke the {@code memoryModeConsumer} with the configured {@link MemoryMode}. */
|
||||
public static void configureExporterMemoryMode(
|
||||
ConfigProperties config, Consumer<MemoryMode> memoryModeConsumer) {
|
||||
String memoryModeStr = config.getString("otel.java.experimental.exporter.memory_mode");
|
||||
if (memoryModeStr == null) {
|
||||
return;
|
||||
}
|
||||
MemoryMode memoryMode;
|
||||
try {
|
||||
memoryMode = MemoryMode.valueOf(memoryModeStr.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ConfigurationException("Unrecognized memory mode: " + memoryModeStr, e);
|
||||
}
|
||||
memoryModeConsumer.accept(memoryMode);
|
||||
}
|
||||
|
||||
private ExporterBuilderUtil() {}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import io.opentelemetry.exporter.internal.http.HttpExporter;
|
|||
import io.opentelemetry.exporter.internal.http.HttpExporterBuilder;
|
||||
import io.opentelemetry.exporter.internal.otlp.metrics.MetricsRequestMarshaler;
|
||||
import io.opentelemetry.sdk.common.CompletableResultCode;
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
import io.opentelemetry.sdk.metrics.Aggregation;
|
||||
import io.opentelemetry.sdk.metrics.InstrumentType;
|
||||
import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
|
||||
|
@ -31,16 +32,19 @@ public final class OtlpHttpMetricExporter implements MetricExporter {
|
|||
private final HttpExporter<MetricsRequestMarshaler> delegate;
|
||||
private final AggregationTemporalitySelector aggregationTemporalitySelector;
|
||||
private final DefaultAggregationSelector defaultAggregationSelector;
|
||||
private final MemoryMode memoryMode;
|
||||
|
||||
OtlpHttpMetricExporter(
|
||||
HttpExporterBuilder<MetricsRequestMarshaler> builder,
|
||||
HttpExporter<MetricsRequestMarshaler> delegate,
|
||||
AggregationTemporalitySelector aggregationTemporalitySelector,
|
||||
DefaultAggregationSelector defaultAggregationSelector) {
|
||||
DefaultAggregationSelector defaultAggregationSelector,
|
||||
MemoryMode memoryMode) {
|
||||
this.builder = builder;
|
||||
this.delegate = delegate;
|
||||
this.aggregationTemporalitySelector = aggregationTemporalitySelector;
|
||||
this.defaultAggregationSelector = defaultAggregationSelector;
|
||||
this.memoryMode = memoryMode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,7 +76,7 @@ public final class OtlpHttpMetricExporter implements MetricExporter {
|
|||
* @since 1.29.0
|
||||
*/
|
||||
public OtlpHttpMetricExporterBuilder toBuilder() {
|
||||
return new OtlpHttpMetricExporterBuilder(builder.copy());
|
||||
return new OtlpHttpMetricExporterBuilder(builder.copy(), memoryMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -85,6 +89,11 @@ public final class OtlpHttpMetricExporter implements MetricExporter {
|
|||
return defaultAggregationSelector.getDefaultAggregation(instrumentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryMode getMemoryMode() {
|
||||
return memoryMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits all the given metrics in a single batch to the OpenTelemetry collector.
|
||||
*
|
||||
|
|
|
@ -15,6 +15,7 @@ import io.opentelemetry.exporter.internal.compression.CompressorUtil;
|
|||
import io.opentelemetry.exporter.internal.http.HttpExporterBuilder;
|
||||
import io.opentelemetry.exporter.internal.otlp.metrics.MetricsRequestMarshaler;
|
||||
import io.opentelemetry.exporter.otlp.internal.OtlpUserAgent;
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
import io.opentelemetry.sdk.common.export.ProxyOptions;
|
||||
import io.opentelemetry.sdk.common.export.RetryPolicy;
|
||||
import io.opentelemetry.sdk.metrics.InstrumentType;
|
||||
|
@ -39,6 +40,7 @@ public final class OtlpHttpMetricExporterBuilder {
|
|||
|
||||
private static final AggregationTemporalitySelector DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR =
|
||||
AggregationTemporalitySelector.alwaysCumulative();
|
||||
private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.IMMUTABLE_DATA;
|
||||
|
||||
private final HttpExporterBuilder<MetricsRequestMarshaler> delegate;
|
||||
private AggregationTemporalitySelector aggregationTemporalitySelector =
|
||||
|
@ -46,15 +48,18 @@ public final class OtlpHttpMetricExporterBuilder {
|
|||
|
||||
private DefaultAggregationSelector defaultAggregationSelector =
|
||||
DefaultAggregationSelector.getDefault();
|
||||
private MemoryMode memoryMode;
|
||||
|
||||
OtlpHttpMetricExporterBuilder(HttpExporterBuilder<MetricsRequestMarshaler> delegate) {
|
||||
OtlpHttpMetricExporterBuilder(
|
||||
HttpExporterBuilder<MetricsRequestMarshaler> delegate, MemoryMode memoryMode) {
|
||||
this.delegate = delegate;
|
||||
this.memoryMode = memoryMode;
|
||||
delegate.setMeterProvider(MeterProvider::noop);
|
||||
OtlpUserAgent.addUserAgentHeader(delegate::addConstantHeaders);
|
||||
}
|
||||
|
||||
OtlpHttpMetricExporterBuilder() {
|
||||
this(new HttpExporterBuilder<>("otlp", "metric", DEFAULT_ENDPOINT));
|
||||
this(new HttpExporterBuilder<>("otlp", "metric", DEFAULT_ENDPOINT), DEFAULT_MEMORY_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -227,6 +232,13 @@ public final class OtlpHttpMetricExporterBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Set the {@link MemoryMode}. */
|
||||
OtlpHttpMetricExporterBuilder setMemoryMode(MemoryMode memoryMode) {
|
||||
requireNonNull(memoryMode, "memoryMode");
|
||||
this.memoryMode = memoryMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
OtlpHttpMetricExporterBuilder exportAsJson() {
|
||||
delegate.exportAsJson();
|
||||
return this;
|
||||
|
@ -239,6 +251,10 @@ public final class OtlpHttpMetricExporterBuilder {
|
|||
*/
|
||||
public OtlpHttpMetricExporter build() {
|
||||
return new OtlpHttpMetricExporter(
|
||||
delegate, delegate.build(), aggregationTemporalitySelector, defaultAggregationSelector);
|
||||
delegate,
|
||||
delegate.build(),
|
||||
aggregationTemporalitySelector,
|
||||
defaultAggregationSelector,
|
||||
memoryMode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,11 @@ package io.opentelemetry.exporter.otlp.internal;
|
|||
|
||||
import static io.opentelemetry.sdk.metrics.Aggregation.explicitBucketHistogram;
|
||||
|
||||
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder;
|
||||
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
import io.opentelemetry.sdk.common.export.RetryPolicy;
|
||||
import io.opentelemetry.sdk.metrics.Aggregation;
|
||||
import io.opentelemetry.sdk.metrics.InstrumentType;
|
||||
|
@ -19,6 +22,8 @@ import io.opentelemetry.sdk.metrics.internal.aggregator.AggregationUtil;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
|
@ -206,6 +211,44 @@ public final class OtlpConfigUtil {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@code #setMemoryMode} on the {@code Otlp{Protocol}MetricExporterBuilder} with the {@code
|
||||
* memoryMode}.
|
||||
*/
|
||||
public static void setMemoryModeOnOtlpMetricExporterBuilder(
|
||||
Object builder, MemoryMode memoryMode) {
|
||||
try {
|
||||
if (builder instanceof OtlpGrpcMetricExporterBuilder) {
|
||||
// Calling getDeclaredMethod causes all private methods to be read, which causes a
|
||||
// ClassNotFoundException when running with the OkHttHttpProvider as the private
|
||||
// setManagedChanel(io.grpc.ManagedChannel) is reached and io.grpc.ManagedChannel is not on
|
||||
// the classpath. io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricUtil provides a layer
|
||||
// of indirection which avoids scanning the OtlpGrpcMetricExporterBuilder private methods.
|
||||
Class<?> otlpGrpcMetricUtil =
|
||||
Class.forName("io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricUtil");
|
||||
Method method =
|
||||
otlpGrpcMetricUtil.getDeclaredMethod(
|
||||
"setMemoryMode", OtlpGrpcMetricExporterBuilder.class, MemoryMode.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(null, builder, memoryMode);
|
||||
} else if (builder instanceof OtlpHttpMetricExporterBuilder) {
|
||||
Method method =
|
||||
OtlpHttpMetricExporterBuilder.class.getDeclaredMethod(
|
||||
"setMemoryMode", MemoryMode.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(builder, memoryMode);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Can only set memory mode on OtlpHttpMetricExporterBuilder and OtlpGrpcMetricExporterBuilder.");
|
||||
}
|
||||
} catch (NoSuchMethodException
|
||||
| InvocationTargetException
|
||||
| IllegalAccessException
|
||||
| ClassNotFoundException e) {
|
||||
throw new IllegalStateException("Error calling setMemoryMode.", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static URL createUrl(URL context, String spec) {
|
||||
try {
|
||||
return new URL(context, spec);
|
||||
|
|
|
@ -9,6 +9,7 @@ import static io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil.DATA_TYPE_M
|
|||
import static io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil.PROTOCOL_GRPC;
|
||||
import static io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil.PROTOCOL_HTTP_PROTOBUF;
|
||||
|
||||
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
|
||||
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter;
|
||||
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder;
|
||||
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
|
||||
|
@ -48,6 +49,10 @@ public class OtlpMetricExporterProvider implements ConfigurableMetricExporterPro
|
|||
config, builder::setAggregationTemporalitySelector);
|
||||
OtlpConfigUtil.configureOtlpHistogramDefaultAggregation(
|
||||
config, builder::setDefaultAggregationSelector);
|
||||
ExporterBuilderUtil.configureExporterMemoryMode(
|
||||
config,
|
||||
memoryMode ->
|
||||
OtlpConfigUtil.setMemoryModeOnOtlpMetricExporterBuilder(builder, memoryMode));
|
||||
|
||||
return builder.build();
|
||||
} else if (protocol.equals(PROTOCOL_GRPC)) {
|
||||
|
@ -67,6 +72,10 @@ public class OtlpMetricExporterProvider implements ConfigurableMetricExporterPro
|
|||
config, builder::setAggregationTemporalitySelector);
|
||||
OtlpConfigUtil.configureOtlpHistogramDefaultAggregation(
|
||||
config, builder::setDefaultAggregationSelector);
|
||||
ExporterBuilderUtil.configureExporterMemoryMode(
|
||||
config,
|
||||
memoryMode ->
|
||||
OtlpConfigUtil.setMemoryModeOnOtlpMetricExporterBuilder(builder, memoryMode));
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import io.opentelemetry.exporter.internal.grpc.GrpcExporter;
|
|||
import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder;
|
||||
import io.opentelemetry.exporter.internal.otlp.metrics.MetricsRequestMarshaler;
|
||||
import io.opentelemetry.sdk.common.CompletableResultCode;
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
import io.opentelemetry.sdk.metrics.Aggregation;
|
||||
import io.opentelemetry.sdk.metrics.InstrumentType;
|
||||
import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
|
||||
|
@ -31,6 +32,7 @@ public final class OtlpGrpcMetricExporter implements MetricExporter {
|
|||
private final GrpcExporter<MetricsRequestMarshaler> delegate;
|
||||
private final AggregationTemporalitySelector aggregationTemporalitySelector;
|
||||
private final DefaultAggregationSelector defaultAggregationSelector;
|
||||
private final MemoryMode memoryMode;
|
||||
|
||||
/**
|
||||
* Returns a new {@link OtlpGrpcMetricExporter} using the default values.
|
||||
|
@ -57,11 +59,13 @@ public final class OtlpGrpcMetricExporter implements MetricExporter {
|
|||
GrpcExporterBuilder<MetricsRequestMarshaler> builder,
|
||||
GrpcExporter<MetricsRequestMarshaler> delegate,
|
||||
AggregationTemporalitySelector aggregationTemporalitySelector,
|
||||
DefaultAggregationSelector defaultAggregationSelector) {
|
||||
DefaultAggregationSelector defaultAggregationSelector,
|
||||
MemoryMode memoryMode) {
|
||||
this.builder = builder;
|
||||
this.delegate = delegate;
|
||||
this.aggregationTemporalitySelector = aggregationTemporalitySelector;
|
||||
this.defaultAggregationSelector = defaultAggregationSelector;
|
||||
this.memoryMode = memoryMode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,7 +76,7 @@ public final class OtlpGrpcMetricExporter implements MetricExporter {
|
|||
* @since 1.29.0
|
||||
*/
|
||||
public OtlpGrpcMetricExporterBuilder toBuilder() {
|
||||
return new OtlpGrpcMetricExporterBuilder(builder.copy());
|
||||
return new OtlpGrpcMetricExporterBuilder(builder.copy(), memoryMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -85,6 +89,11 @@ public final class OtlpGrpcMetricExporter implements MetricExporter {
|
|||
return defaultAggregationSelector.getDefaultAggregation(instrumentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryMode getMemoryMode() {
|
||||
return memoryMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits all the given metrics in a single batch to the OpenTelemetry collector.
|
||||
*
|
||||
|
|
|
@ -16,6 +16,7 @@ import io.opentelemetry.exporter.internal.compression.CompressorUtil;
|
|||
import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder;
|
||||
import io.opentelemetry.exporter.internal.otlp.metrics.MetricsRequestMarshaler;
|
||||
import io.opentelemetry.exporter.otlp.internal.OtlpUserAgent;
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
import io.opentelemetry.sdk.common.export.RetryPolicy;
|
||||
import io.opentelemetry.sdk.metrics.InstrumentType;
|
||||
import io.opentelemetry.sdk.metrics.export.AggregationTemporalitySelector;
|
||||
|
@ -46,6 +47,7 @@ public final class OtlpGrpcMetricExporterBuilder {
|
|||
private static final long DEFAULT_TIMEOUT_SECS = 10;
|
||||
private static final AggregationTemporalitySelector DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR =
|
||||
AggregationTemporalitySelector.alwaysCumulative();
|
||||
private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.IMMUTABLE_DATA;
|
||||
|
||||
// Visible for testing
|
||||
final GrpcExporterBuilder<MetricsRequestMarshaler> delegate;
|
||||
|
@ -55,9 +57,12 @@ public final class OtlpGrpcMetricExporterBuilder {
|
|||
|
||||
private DefaultAggregationSelector defaultAggregationSelector =
|
||||
DefaultAggregationSelector.getDefault();
|
||||
private MemoryMode memoryMode;
|
||||
|
||||
OtlpGrpcMetricExporterBuilder(GrpcExporterBuilder<MetricsRequestMarshaler> delegate) {
|
||||
OtlpGrpcMetricExporterBuilder(
|
||||
GrpcExporterBuilder<MetricsRequestMarshaler> delegate, MemoryMode memoryMode) {
|
||||
this.delegate = delegate;
|
||||
this.memoryMode = memoryMode;
|
||||
delegate.setMeterProvider(MeterProvider::noop);
|
||||
OtlpUserAgent.addUserAgentHeader(delegate::addConstantHeader);
|
||||
}
|
||||
|
@ -70,7 +75,8 @@ public final class OtlpGrpcMetricExporterBuilder {
|
|||
DEFAULT_TIMEOUT_SECS,
|
||||
DEFAULT_ENDPOINT,
|
||||
() -> MarshalerMetricsServiceGrpc::newFutureStub,
|
||||
GRPC_ENDPOINT_PATH));
|
||||
GRPC_ENDPOINT_PATH),
|
||||
DEFAULT_MEMORY_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -259,6 +265,13 @@ public final class OtlpGrpcMetricExporterBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Set the {@link MemoryMode}. */
|
||||
OtlpGrpcMetricExporterBuilder setMemoryMode(MemoryMode memoryMode) {
|
||||
requireNonNull(memoryMode, "memoryMode");
|
||||
this.memoryMode = memoryMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the exporter based on the builder's values.
|
||||
*
|
||||
|
@ -266,6 +279,10 @@ public final class OtlpGrpcMetricExporterBuilder {
|
|||
*/
|
||||
public OtlpGrpcMetricExporter build() {
|
||||
return new OtlpGrpcMetricExporter(
|
||||
delegate, delegate.build(), aggregationTemporalitySelector, defaultAggregationSelector);
|
||||
delegate,
|
||||
delegate.build(),
|
||||
aggregationTemporalitySelector,
|
||||
defaultAggregationSelector,
|
||||
memoryMode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.exporter.otlp.metrics;
|
||||
|
||||
import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil;
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
|
||||
final class OtlpGrpcMetricUtil {
|
||||
|
||||
private OtlpGrpcMetricUtil() {}
|
||||
|
||||
/** See {@link OtlpConfigUtil#setMemoryModeOnOtlpMetricExporterBuilder(Object, MemoryMode)}. */
|
||||
static void setMemoryMode(OtlpGrpcMetricExporterBuilder builder, MemoryMode memoryMode) {
|
||||
builder.setMemoryMode(memoryMode);
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
|
|||
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurationException;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
import io.opentelemetry.sdk.metrics.export.MetricExporter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -127,6 +128,7 @@ class OtlpMetricExporterProviderTest {
|
|||
verify(grpcBuilder, never()).setTrustedCertificates(any());
|
||||
verify(grpcBuilder, never()).setClientTls(any(), any());
|
||||
assertThat(grpcBuilder).extracting("delegate").extracting("retryPolicy").isNull();
|
||||
assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
|
||||
}
|
||||
Mockito.verifyNoInteractions(httpBuilder);
|
||||
}
|
||||
|
@ -176,6 +178,7 @@ class OtlpMetricExporterProviderTest {
|
|||
config.put("otel.exporter.otlp.metrics.compression", "gzip");
|
||||
config.put("otel.exporter.otlp.timeout", "1s");
|
||||
config.put("otel.exporter.otlp.metrics.timeout", "15s");
|
||||
config.put("otel.java.experimental.exporter.memory_mode", "reusable_data");
|
||||
|
||||
try (MetricExporter exporter =
|
||||
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
|
||||
|
@ -188,6 +191,7 @@ class OtlpMetricExporterProviderTest {
|
|||
verify(grpcBuilder).setTrustedCertificates(serverTls.certificate().getEncoded());
|
||||
verify(grpcBuilder)
|
||||
.setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded());
|
||||
assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.REUSABLE_DATA);
|
||||
}
|
||||
Mockito.verifyNoInteractions(httpBuilder);
|
||||
}
|
||||
|
@ -208,6 +212,7 @@ class OtlpMetricExporterProviderTest {
|
|||
verify(httpBuilder, never()).setTrustedCertificates(any());
|
||||
verify(httpBuilder, never()).setClientTls(any(), any());
|
||||
assertThat(httpBuilder).extracting("delegate").extracting("retryPolicy").isNull();
|
||||
assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
|
||||
}
|
||||
Mockito.verifyNoInteractions(grpcBuilder);
|
||||
}
|
||||
|
@ -260,6 +265,7 @@ class OtlpMetricExporterProviderTest {
|
|||
config.put("otel.exporter.otlp.metrics.compression", "gzip");
|
||||
config.put("otel.exporter.otlp.timeout", "1s");
|
||||
config.put("otel.exporter.otlp.metrics.timeout", "15s");
|
||||
config.put("otel.java.experimental.exporter.memory_mode", "reusable_data");
|
||||
|
||||
try (MetricExporter exporter =
|
||||
provider.createExporter(DefaultConfigProperties.createFromMap(config))) {
|
||||
|
@ -272,6 +278,7 @@ class OtlpMetricExporterProviderTest {
|
|||
verify(httpBuilder).setTrustedCertificates(serverTls.certificate().getEncoded());
|
||||
verify(httpBuilder)
|
||||
.setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded());
|
||||
assertThat(exporter.getMemoryMode()).isEqualTo(MemoryMode.REUSABLE_DATA);
|
||||
}
|
||||
Mockito.verifyNoInteractions(grpcBuilder);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ otelJava.moduleName.set("io.opentelemetry.exporter.prometheus")
|
|||
dependencies {
|
||||
api(project(":sdk:metrics"))
|
||||
|
||||
implementation(project(":exporters:common"))
|
||||
implementation(project(":sdk-extensions:autoconfigure-spi"))
|
||||
implementation("io.prometheus:prometheus-metrics-exporter-httpserver")
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
package io.opentelemetry.exporter.prometheus;
|
||||
|
||||
import io.opentelemetry.sdk.common.CompletableResultCode;
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
import io.opentelemetry.sdk.metrics.InstrumentType;
|
||||
import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
|
||||
import io.opentelemetry.sdk.metrics.export.CollectionRegistration;
|
||||
|
@ -32,11 +33,12 @@ import javax.annotation.Nullable;
|
|||
*/
|
||||
public final class PrometheusHttpServer implements MetricReader {
|
||||
|
||||
private final PrometheusHttpServerBuilder builder;
|
||||
private final HTTPServer httpServer;
|
||||
private final PrometheusMetricReader prometheusMetricReader;
|
||||
private final PrometheusRegistry prometheusRegistry;
|
||||
private final String host;
|
||||
private final PrometheusHttpServerBuilder builder;
|
||||
private final MemoryMode memoryMode;
|
||||
|
||||
/**
|
||||
* Returns a new {@link PrometheusHttpServer} which can be registered to an {@link
|
||||
|
@ -59,11 +61,13 @@ public final class PrometheusHttpServer implements MetricReader {
|
|||
@Nullable ExecutorService executor,
|
||||
PrometheusRegistry prometheusRegistry,
|
||||
boolean otelScopeEnabled,
|
||||
@Nullable Predicate<String> allowedResourceAttributesFilter) {
|
||||
@Nullable Predicate<String> allowedResourceAttributesFilter,
|
||||
MemoryMode memoryMode) {
|
||||
this.builder = builder;
|
||||
this.prometheusMetricReader =
|
||||
new PrometheusMetricReader(otelScopeEnabled, allowedResourceAttributesFilter);
|
||||
this.host = host;
|
||||
this.memoryMode = memoryMode;
|
||||
this.prometheusRegistry = prometheusRegistry;
|
||||
prometheusRegistry.register(prometheusMetricReader);
|
||||
try {
|
||||
|
@ -85,6 +89,11 @@ public final class PrometheusHttpServer implements MetricReader {
|
|||
return prometheusMetricReader.getAggregationTemporality(instrumentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryMode getMemoryMode() {
|
||||
return memoryMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(CollectionRegistration registration) {
|
||||
prometheusMetricReader.register(registration);
|
||||
|
|
|
@ -8,6 +8,7 @@ package io.opentelemetry.exporter.prometheus;
|
|||
import static io.opentelemetry.api.internal.Utils.checkArgument;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
import io.prometheus.metrics.model.registry.PrometheusRegistry;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.function.Predicate;
|
||||
|
@ -18,6 +19,7 @@ public final class PrometheusHttpServerBuilder {
|
|||
|
||||
static final int DEFAULT_PORT = 9464;
|
||||
private static final String DEFAULT_HOST = "0.0.0.0";
|
||||
private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.IMMUTABLE_DATA;
|
||||
|
||||
private String host = DEFAULT_HOST;
|
||||
private int port = DEFAULT_PORT;
|
||||
|
@ -25,6 +27,18 @@ public final class PrometheusHttpServerBuilder {
|
|||
private boolean otelScopeEnabled = true;
|
||||
@Nullable private Predicate<String> allowedResourceAttributesFilter;
|
||||
@Nullable private ExecutorService executor;
|
||||
private MemoryMode memoryMode = DEFAULT_MEMORY_MODE;
|
||||
|
||||
PrometheusHttpServerBuilder() {}
|
||||
|
||||
PrometheusHttpServerBuilder(PrometheusHttpServerBuilder builder) {
|
||||
this.host = builder.host;
|
||||
this.port = builder.port;
|
||||
this.prometheusRegistry = builder.prometheusRegistry;
|
||||
this.otelScopeEnabled = builder.otelScopeEnabled;
|
||||
this.allowedResourceAttributesFilter = builder.allowedResourceAttributesFilter;
|
||||
this.executor = builder.executor;
|
||||
}
|
||||
|
||||
/** Sets the host to bind to. If unset, defaults to {@value #DEFAULT_HOST}. */
|
||||
public PrometheusHttpServerBuilder setHost(String host) {
|
||||
|
@ -79,6 +93,13 @@ public final class PrometheusHttpServerBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/** Set the {@link MemoryMode}. */
|
||||
public PrometheusHttpServerBuilder setMemoryMode(MemoryMode memoryMode) {
|
||||
requireNonNull(memoryMode, "memoryMode");
|
||||
this.memoryMode = memoryMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@link PrometheusHttpServer} with the configuration of this builder which can be
|
||||
* registered with a {@link io.opentelemetry.sdk.metrics.SdkMeterProvider}.
|
||||
|
@ -91,17 +112,7 @@ public final class PrometheusHttpServerBuilder {
|
|||
executor,
|
||||
prometheusRegistry,
|
||||
otelScopeEnabled,
|
||||
allowedResourceAttributesFilter);
|
||||
}
|
||||
|
||||
PrometheusHttpServerBuilder() {}
|
||||
|
||||
PrometheusHttpServerBuilder(PrometheusHttpServerBuilder builder) {
|
||||
this.host = builder.host;
|
||||
this.port = builder.port;
|
||||
this.prometheusRegistry = builder.prometheusRegistry;
|
||||
this.otelScopeEnabled = builder.otelScopeEnabled;
|
||||
this.allowedResourceAttributesFilter = builder.allowedResourceAttributesFilter;
|
||||
this.executor = builder.executor;
|
||||
allowedResourceAttributesFilter,
|
||||
memoryMode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
package io.opentelemetry.exporter.prometheus.internal;
|
||||
|
||||
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
|
||||
import io.opentelemetry.exporter.prometheus.PrometheusHttpServer;
|
||||
import io.opentelemetry.exporter.prometheus.PrometheusHttpServerBuilder;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
|
@ -32,6 +33,8 @@ public class PrometheusMetricReaderProvider implements ConfigurableMetricReaderP
|
|||
prometheusBuilder.setHost(host);
|
||||
}
|
||||
|
||||
ExporterBuilderUtil.configureExporterMemoryMode(config, prometheusBuilder::setMemoryMode);
|
||||
|
||||
return prometheusBuilder.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import com.sun.net.httpserver.HttpServer;
|
|||
import io.opentelemetry.exporter.prometheus.PrometheusHttpServer;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
|
||||
import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties;
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
import io.opentelemetry.sdk.metrics.export.MetricReader;
|
||||
import io.prometheus.metrics.exporter.httpserver.HTTPServer;
|
||||
import java.io.IOException;
|
||||
|
@ -57,6 +58,7 @@ class PrometheusMetricReaderProviderTest {
|
|||
assertThat(server.getAddress().getHostName()).isEqualTo("0:0:0:0:0:0:0:0");
|
||||
assertThat(server.getAddress().getPort()).isEqualTo(9464);
|
||||
});
|
||||
assertThat(metricReader.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,6 +75,7 @@ class PrometheusMetricReaderProviderTest {
|
|||
Map<String, String> config = new HashMap<>();
|
||||
config.put("otel.exporter.prometheus.host", "localhost");
|
||||
config.put("otel.exporter.prometheus.port", String.valueOf(port));
|
||||
config.put("otel.java.experimental.exporter.memory_mode", "reusable_data");
|
||||
|
||||
when(configProperties.getInt(any())).thenReturn(null);
|
||||
when(configProperties.getString(any())).thenReturn(null);
|
||||
|
@ -87,6 +90,7 @@ class PrometheusMetricReaderProviderTest {
|
|||
assertThat(server.getAddress().getHostName()).isEqualTo("localhost");
|
||||
assertThat(server.getAddress().getPort()).isEqualTo(port);
|
||||
});
|
||||
assertThat(metricReader.getMemoryMode()).isEqualTo(MemoryMode.REUSABLE_DATA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,9 +38,12 @@ import io.opentelemetry.context.Context;
|
|||
import io.opentelemetry.context.Scope;
|
||||
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;
|
||||
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter;
|
||||
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder;
|
||||
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
|
||||
import io.opentelemetry.exporter.otlp.internal.OtlpConfigUtil;
|
||||
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter;
|
||||
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
|
||||
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder;
|
||||
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
|
||||
import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest;
|
||||
import io.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse;
|
||||
|
@ -63,6 +66,7 @@ import io.opentelemetry.proto.metrics.v1.Sum;
|
|||
import io.opentelemetry.proto.trace.v1.ResourceSpans;
|
||||
import io.opentelemetry.proto.trace.v1.ScopeSpans;
|
||||
import io.opentelemetry.proto.trace.v1.Span.Link;
|
||||
import io.opentelemetry.sdk.common.export.MemoryMode;
|
||||
import io.opentelemetry.sdk.logs.SdkLoggerProvider;
|
||||
import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor;
|
||||
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
|
||||
|
@ -93,6 +97,7 @@ import org.junit.jupiter.api.BeforeEach;
|
|||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.testcontainers.containers.BindMode;
|
||||
|
@ -195,7 +200,7 @@ abstract class OtlpExporterIntegrationTest {
|
|||
@ParameterizedTest
|
||||
@ValueSource(strings = {"gzip", "none"})
|
||||
void testOtlpGrpcTraceExport(String compression) {
|
||||
SpanExporter otlpGrpcTraceExporter =
|
||||
SpanExporter exporter =
|
||||
OtlpGrpcSpanExporter.builder()
|
||||
.setEndpoint(
|
||||
"http://"
|
||||
|
@ -205,7 +210,7 @@ abstract class OtlpExporterIntegrationTest {
|
|||
.setCompression(compression)
|
||||
.build();
|
||||
|
||||
testTraceExport(otlpGrpcTraceExporter);
|
||||
testTraceExport(exporter);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -227,7 +232,7 @@ abstract class OtlpExporterIntegrationTest {
|
|||
@ParameterizedTest
|
||||
@ValueSource(strings = {"gzip", "none"})
|
||||
void testOtlpHttpTraceExport(String compression) {
|
||||
SpanExporter otlpGrpcTraceExporter =
|
||||
SpanExporter exporter =
|
||||
OtlpHttpSpanExporter.builder()
|
||||
.setEndpoint(
|
||||
"http://"
|
||||
|
@ -238,7 +243,7 @@ abstract class OtlpExporterIntegrationTest {
|
|||
.setCompression(compression)
|
||||
.build();
|
||||
|
||||
testTraceExport(otlpGrpcTraceExporter);
|
||||
testTraceExport(exporter);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -328,7 +333,7 @@ abstract class OtlpExporterIntegrationTest {
|
|||
@ParameterizedTest
|
||||
@ValueSource(strings = {"gzip", "none"})
|
||||
void testOtlpGrpcMetricExport(String compression) {
|
||||
MetricExporter otlpGrpcMetricExporter =
|
||||
MetricExporter exporter =
|
||||
OtlpGrpcMetricExporter.builder()
|
||||
.setEndpoint(
|
||||
"http://"
|
||||
|
@ -338,7 +343,26 @@ abstract class OtlpExporterIntegrationTest {
|
|||
.setCompression(compression)
|
||||
.build();
|
||||
|
||||
testMetricExport(otlpGrpcMetricExporter);
|
||||
testMetricExport(exporter);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(MemoryMode.class)
|
||||
void testOtlpGrpcMetricExport_memoryMode(MemoryMode memoryMode) {
|
||||
OtlpGrpcMetricExporterBuilder builder = OtlpGrpcMetricExporter.builder();
|
||||
OtlpConfigUtil.setMemoryModeOnOtlpMetricExporterBuilder(builder, memoryMode);
|
||||
|
||||
MetricExporter exporter =
|
||||
builder
|
||||
.setEndpoint(
|
||||
"http://"
|
||||
+ collector.getHost()
|
||||
+ ":"
|
||||
+ collector.getMappedPort(COLLECTOR_OTLP_GRPC_PORT))
|
||||
.build();
|
||||
assertThat(exporter.getMemoryMode()).isEqualTo(memoryMode);
|
||||
|
||||
testMetricExport(exporter);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -360,7 +384,8 @@ abstract class OtlpExporterIntegrationTest {
|
|||
@ParameterizedTest
|
||||
@ValueSource(strings = {"gzip", "none"})
|
||||
void testOtlpHttpMetricExport(String compression) {
|
||||
MetricExporter otlpGrpcMetricExporter =
|
||||
|
||||
MetricExporter exporter =
|
||||
OtlpHttpMetricExporter.builder()
|
||||
.setEndpoint(
|
||||
"http://"
|
||||
|
@ -371,7 +396,27 @@ abstract class OtlpExporterIntegrationTest {
|
|||
.setCompression(compression)
|
||||
.build();
|
||||
|
||||
testMetricExport(otlpGrpcMetricExporter);
|
||||
testMetricExport(exporter);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(MemoryMode.class)
|
||||
void testOtlpHttpMetricExport_memoryMode(MemoryMode memoryMode) {
|
||||
OtlpHttpMetricExporterBuilder builder = OtlpHttpMetricExporter.builder();
|
||||
OtlpConfigUtil.setMemoryModeOnOtlpMetricExporterBuilder(builder, memoryMode);
|
||||
|
||||
MetricExporter exporter =
|
||||
builder
|
||||
.setEndpoint(
|
||||
"http://"
|
||||
+ collector.getHost()
|
||||
+ ":"
|
||||
+ collector.getMappedPort(COLLECTOR_OTLP_HTTP_PORT)
|
||||
+ "/v1/metrics")
|
||||
.build();
|
||||
assertThat(exporter.getMemoryMode()).isEqualTo(memoryMode);
|
||||
|
||||
testMetricExport(exporter);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -72,11 +72,18 @@ The OpenTelemetry SDK can be disabled entirely. If disabled, `AutoConfiguredOpen
|
|||
|
||||
The following configuration properties are common to all exporters:
|
||||
|
||||
| System property | Environment variable | Purpose |
|
||||
|-----------------------|-----------------------|----------------------------------------------------------------------------------------------------------------------------|
|
||||
| otel.traces.exporter | OTEL_TRACES_EXPORTER | List of exporters to be used for tracing, separated by commas. Default is `otlp`. `none` means no autoconfigured exporter. |
|
||||
| otel.metrics.exporter | OTEL_METRICS_EXPORTER | List of exporters to be used for metrics, separated by commas. Default is `otlp`. `none` means no autoconfigured exporter. |
|
||||
| otel.logs.exporter | OTEL_LOGS_EXPORTER | List of exporters to be used for logging, separated by commas. Default is `otlp`. `none` means no autoconfigured exporter. |
|
||||
| System property | Environment variable | Purpose |
|
||||
|---------------------------------------------|---------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| otel.traces.exporter | OTEL_TRACES_EXPORTER | List of exporters to be used for tracing, separated by commas. Default is `otlp`. `none` means no autoconfigured exporter. |
|
||||
| otel.metrics.exporter | OTEL_METRICS_EXPORTER | List of exporters to be used for metrics, separated by commas. Default is `otlp`. `none` means no autoconfigured exporter. |
|
||||
| otel.logs.exporter | OTEL_LOGS_EXPORTER | List of exporters to be used for logging, separated by commas. Default is `otlp`. `none` means no autoconfigured exporter. |
|
||||
| otel.java.experimental.exporter.memory_mode | OTEL_JAVA_EXPERIMENTAL_EXPORTER_MEMORY_MODE | If `reusable_data`, enable reusable memory mode (on exporters which support it) to reduce allocations. Default is `immutable_data`. This option is experimental and subject to change or removal.**[1]** |
|
||||
|
||||
**[1]**: NOTE: The exporters which adhere
|
||||
to `otel.java.experimental.exporter.memory_mode=reusable_data`
|
||||
are `OtlpGrpcMetricExporter`, `OtlpHttpMetricExporter`, and `PrometheusHttpServer`. Support for
|
||||
additional exporters may be added in the future.
|
||||
|
||||
|
||||
#### OTLP exporter (span, metric, and log exporters)
|
||||
|
||||
|
|
Loading…
Reference in New Issue