Skip to content

Commit

Permalink
Metric exporter REUSABLE_DATA memory mode configuration options (#6304)
Browse files Browse the repository at this point in the history
  • Loading branch information
jack-berg authored Apr 5, 2024
1 parent ff0480c commit 4d8f4f3
Show file tree
Hide file tree
Showing 18 changed files with 274 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -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()
1 change: 1 addition & 0 deletions exporters/common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -33,5 +38,21 @@ public static URI validateEndpoint(String endpoint) {
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() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
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;
Expand All @@ -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;
}

/**
Expand Down Expand Up @@ -72,7 +76,7 @@ public static OtlpHttpMetricExporterBuilder builder() {
* @since 1.29.0
*/
public OtlpHttpMetricExporterBuilder toBuilder() {
return new OtlpHttpMetricExporterBuilder(builder.copy());
return new OtlpHttpMetricExporterBuilder(builder.copy(), memoryMode);
}

@Override
Expand All @@ -85,6 +89,11 @@ public Aggregation getDefaultAggregation(InstrumentType instrumentType) {
return defaultAggregationSelector.getDefaultAggregation(instrumentType);
}

@Override
public MemoryMode getMemoryMode() {
return memoryMode;
}

/**
* Submits all the given metrics in a single batch to the OpenTelemetry collector.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
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;
Expand All @@ -39,22 +40,26 @@ 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 =
DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR;

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);
}

/**
Expand Down Expand Up @@ -227,6 +232,13 @@ public OtlpHttpMetricExporterBuilder setProxyOptions(ProxyOptions proxyOptions)
return this;
}

/** Set the {@link MemoryMode}. */
OtlpHttpMetricExporterBuilder setMemoryMode(MemoryMode memoryMode) {
requireNonNull(memoryMode, "memoryMode");
this.memoryMode = memoryMode;
return this;
}

OtlpHttpMetricExporterBuilder exportAsJson() {
delegate.exportAsJson();
return this;
Expand All @@ -239,6 +251,10 @@ OtlpHttpMetricExporterBuilder exportAsJson() {
*/
public OtlpHttpMetricExporter build() {
return new OtlpHttpMetricExporter(
delegate, delegate.build(), aggregationTemporalitySelector, defaultAggregationSelector);
delegate,
delegate.build(),
aggregationTemporalitySelector,
defaultAggregationSelector,
memoryMode);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@

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;
Expand All @@ -19,6 +22,8 @@
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;
Expand Down Expand Up @@ -206,6 +211,44 @@ public static void configureOtlpHistogramDefaultAggregation(
}
}

/**
* 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
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;
Expand Down Expand Up @@ -48,6 +49,10 @@ public MetricExporter createExporter(ConfigProperties config) {
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)) {
Expand All @@ -67,6 +72,10 @@ public MetricExporter createExporter(ConfigProperties config) {
config, builder::setAggregationTemporalitySelector);
OtlpConfigUtil.configureOtlpHistogramDefaultAggregation(
config, builder::setDefaultAggregationSelector);
ExporterBuilderUtil.configureExporterMemoryMode(
config,
memoryMode ->
OtlpConfigUtil.setMemoryModeOnOtlpMetricExporterBuilder(builder, memoryMode));

return builder.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
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;
Expand All @@ -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.
Expand All @@ -57,11 +59,13 @@ public static OtlpGrpcMetricExporterBuilder builder() {
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;
}

/**
Expand All @@ -72,7 +76,7 @@ public static OtlpGrpcMetricExporterBuilder builder() {
* @since 1.29.0
*/
public OtlpGrpcMetricExporterBuilder toBuilder() {
return new OtlpGrpcMetricExporterBuilder(builder.copy());
return new OtlpGrpcMetricExporterBuilder(builder.copy(), memoryMode);
}

@Override
Expand All @@ -85,6 +89,11 @@ public Aggregation getDefaultAggregation(InstrumentType instrumentType) {
return defaultAggregationSelector.getDefaultAggregation(instrumentType);
}

@Override
public MemoryMode getMemoryMode() {
return memoryMode;
}

/**
* Submits all the given metrics in a single batch to the OpenTelemetry collector.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
Expand All @@ -70,7 +75,8 @@ public final class OtlpGrpcMetricExporterBuilder {
DEFAULT_TIMEOUT_SECS,
DEFAULT_ENDPOINT,
() -> MarshalerMetricsServiceGrpc::newFutureStub,
GRPC_ENDPOINT_PATH));
GRPC_ENDPOINT_PATH),
DEFAULT_MEMORY_MODE);
}

/**
Expand Down Expand Up @@ -259,13 +265,24 @@ public OtlpGrpcMetricExporterBuilder setRetryPolicy(RetryPolicy retryPolicy) {
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.
*
* @return a new exporter's instance
*/
public OtlpGrpcMetricExporter build() {
return new OtlpGrpcMetricExporter(
delegate, delegate.build(), aggregationTemporalitySelector, defaultAggregationSelector);
delegate,
delegate.build(),
aggregationTemporalitySelector,
defaultAggregationSelector,
memoryMode);
}
}
Loading

0 comments on commit 4d8f4f3

Please sign in to comment.