Fix OTLP metric exporter toBuilder() loosing temporality (#7280)

This commit is contained in:
Jonas Kunz 2025-04-17 18:39:35 +02:00 committed by GitHub
parent f17b8b0414
commit 65472798f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 125 additions and 18 deletions

View File

@ -32,8 +32,10 @@ public final class OtlpHttpMetricExporter implements MetricExporter {
private final HttpExporterBuilder<Marshaler> builder;
private final HttpExporter<Marshaler> delegate;
private final AggregationTemporalitySelector aggregationTemporalitySelector;
private final DefaultAggregationSelector defaultAggregationSelector;
// Visible for testing
final AggregationTemporalitySelector aggregationTemporalitySelector;
// Visible for testing
final DefaultAggregationSelector defaultAggregationSelector;
private final MetricReusableDataMarshaler marshaler;
OtlpHttpMetricExporter(
@ -78,7 +80,11 @@ public final class OtlpHttpMetricExporter implements MetricExporter {
* @since 1.29.0
*/
public OtlpHttpMetricExporterBuilder toBuilder() {
return new OtlpHttpMetricExporterBuilder(builder.copy(), marshaler.getMemoryMode());
return new OtlpHttpMetricExporterBuilder(
builder.copy(),
aggregationTemporalitySelector,
defaultAggregationSelector,
marshaler.getMemoryMode());
}
@Override

View File

@ -47,22 +47,30 @@ public final class OtlpHttpMetricExporterBuilder {
private static final MemoryMode DEFAULT_MEMORY_MODE = MemoryMode.REUSABLE_DATA;
private final HttpExporterBuilder<Marshaler> delegate;
private AggregationTemporalitySelector aggregationTemporalitySelector =
DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR;
private DefaultAggregationSelector defaultAggregationSelector =
DefaultAggregationSelector.getDefault();
private AggregationTemporalitySelector aggregationTemporalitySelector;
private DefaultAggregationSelector defaultAggregationSelector;
private MemoryMode memoryMode;
OtlpHttpMetricExporterBuilder(HttpExporterBuilder<Marshaler> delegate, MemoryMode memoryMode) {
OtlpHttpMetricExporterBuilder(
HttpExporterBuilder<Marshaler> delegate,
AggregationTemporalitySelector aggregationTemporalitySelector,
DefaultAggregationSelector defaultAggregationSelector,
MemoryMode memoryMode) {
this.delegate = delegate;
this.aggregationTemporalitySelector = aggregationTemporalitySelector;
this.defaultAggregationSelector = defaultAggregationSelector;
this.memoryMode = memoryMode;
delegate.setMeterProvider(MeterProvider::noop);
OtlpUserAgent.addUserAgentHeader(delegate::addConstantHeaders);
}
OtlpHttpMetricExporterBuilder() {
this(new HttpExporterBuilder<>("otlp", "metric", DEFAULT_ENDPOINT), DEFAULT_MEMORY_MODE);
this(
new HttpExporterBuilder<>("otlp", "metric", DEFAULT_ENDPOINT),
DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR,
DefaultAggregationSelector.getDefault(),
DEFAULT_MEMORY_MODE);
}
/**

View File

@ -32,8 +32,10 @@ public final class OtlpGrpcMetricExporter implements MetricExporter {
private final GrpcExporterBuilder<Marshaler> builder;
private final GrpcExporter<Marshaler> delegate;
private final AggregationTemporalitySelector aggregationTemporalitySelector;
private final DefaultAggregationSelector defaultAggregationSelector;
// Visible for testing
final AggregationTemporalitySelector aggregationTemporalitySelector;
// Visible for testing
final DefaultAggregationSelector defaultAggregationSelector;
private final MetricReusableDataMarshaler marshaler;
/**
@ -78,7 +80,11 @@ public final class OtlpGrpcMetricExporter implements MetricExporter {
* @since 1.29.0
*/
public OtlpGrpcMetricExporterBuilder toBuilder() {
return new OtlpGrpcMetricExporterBuilder(builder.copy(), marshaler.getMemoryMode());
return new OtlpGrpcMetricExporterBuilder(
builder.copy(),
aggregationTemporalitySelector,
defaultAggregationSelector,
marshaler.getMemoryMode());
}
@Override

View File

@ -56,15 +56,18 @@ public final class OtlpGrpcMetricExporterBuilder {
// Visible for testing
final GrpcExporterBuilder<Marshaler> delegate;
private AggregationTemporalitySelector aggregationTemporalitySelector =
DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR;
private DefaultAggregationSelector defaultAggregationSelector =
DefaultAggregationSelector.getDefault();
private AggregationTemporalitySelector aggregationTemporalitySelector;
private DefaultAggregationSelector defaultAggregationSelector;
private MemoryMode memoryMode;
OtlpGrpcMetricExporterBuilder(GrpcExporterBuilder<Marshaler> delegate, MemoryMode memoryMode) {
OtlpGrpcMetricExporterBuilder(
GrpcExporterBuilder<Marshaler> delegate,
AggregationTemporalitySelector aggregationTemporalitySelector,
DefaultAggregationSelector defaultAggregationSelector,
MemoryMode memoryMode) {
this.delegate = delegate;
this.aggregationTemporalitySelector = aggregationTemporalitySelector;
this.defaultAggregationSelector = defaultAggregationSelector;
this.memoryMode = memoryMode;
delegate.setMeterProvider(MeterProvider::noop);
OtlpUserAgent.addUserAgentHeader(delegate::addConstantHeader);
@ -79,6 +82,8 @@ public final class OtlpGrpcMetricExporterBuilder {
DEFAULT_ENDPOINT,
() -> MarshalerMetricsServiceGrpc::newFutureStub,
GRPC_ENDPOINT_PATH),
DEFAULT_AGGREGATION_TEMPORALITY_SELECTOR,
DefaultAggregationSelector.getDefault(),
DEFAULT_MEMORY_MODE);
}

View File

@ -0,0 +1,41 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.otlp.http.metrics;
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.sdk.common.export.MemoryMode;
import io.opentelemetry.sdk.metrics.export.AggregationTemporalitySelector;
import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
class OtlpHttpMetricExporterBuilderTest {
@Test
void verifyToBuilderPreservesSettings() {
AggregationTemporalitySelector temporalitySelector =
Mockito.mock(AggregationTemporalitySelector.class);
DefaultAggregationSelector defaultAggregationSelector =
Mockito.mock(DefaultAggregationSelector.class);
OtlpHttpMetricExporter original =
OtlpHttpMetricExporter.builder()
.setMemoryMode(MemoryMode.IMMUTABLE_DATA)
.setAggregationTemporalitySelector(temporalitySelector)
.setDefaultAggregationSelector(defaultAggregationSelector)
.build();
OtlpHttpMetricExporter copy = original.toBuilder().build();
assertThat(copy.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
assertThat(copy.aggregationTemporalitySelector).isSameAs(temporalitySelector);
assertThat(copy.defaultAggregationSelector).isSameAs(defaultAggregationSelector);
original.close();
copy.close();
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.exporter.otlp.metrics;
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.sdk.common.export.MemoryMode;
import io.opentelemetry.sdk.metrics.export.AggregationTemporalitySelector;
import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
class OtlpGrpcMetricExporterBuilderTest {
@Test
void verifyToBuilderPreservesSettings() {
AggregationTemporalitySelector temporalitySelector =
Mockito.mock(AggregationTemporalitySelector.class);
DefaultAggregationSelector defaultAggregationSelector =
Mockito.mock(DefaultAggregationSelector.class);
OtlpGrpcMetricExporter original =
OtlpGrpcMetricExporter.builder()
.setMemoryMode(MemoryMode.IMMUTABLE_DATA)
.setAggregationTemporalitySelector(temporalitySelector)
.setDefaultAggregationSelector(defaultAggregationSelector)
.build();
OtlpGrpcMetricExporter copy = original.toBuilder().build();
assertThat(copy.getMemoryMode()).isEqualTo(MemoryMode.IMMUTABLE_DATA);
assertThat(copy.aggregationTemporalitySelector).isSameAs(temporalitySelector);
assertThat(copy.defaultAggregationSelector).isSameAs(defaultAggregationSelector);
original.close();
copy.close();
}
}