From ef927c7fca1be28bcb4a57d931087c082a6f566c Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 10 Oct 2024 13:32:55 +0200 Subject: [PATCH 1/4] add stdout memory mode --- .../OtlpStdoutExporterBuilderUtil.java | 19 +++ .../logs/OtlpStdoutLogRecordExporter.java | 18 ++- .../OtlpStdoutLogRecordExporterBuilder.java | 17 +- ...outLogRecordExporterComponentProvider.java | 2 + .../OtlpStdoutLogRecordExporterProvider.java | 2 + .../metrics/OtlpStdoutMetricExporter.java | 27 +++- .../OtlpStdoutMetricExporterBuilder.java | 16 ++ ...StdoutMetricExporterComponentProvider.java | 1 + .../OtlpStdoutMetricExporterProvider.java | 1 + .../traces/OtlpStdoutSpanExporter.java | 18 ++- .../traces/OtlpStdoutSpanExporterBuilder.java | 17 +- ...lpStdoutSpanExporterComponentProvider.java | 2 + .../OtlpStdoutSpanExporterProvider.java | 2 + .../otlp/AbstractOtlpStdoutExporterTest.java | 146 +++++++++++++----- .../otlp/OtlpStdoutLogRecordExporterTest.java | 9 +- .../otlp/OtlpStdoutMetricExporterTest.java | 14 +- .../otlp/OtlpStdoutSpanExporterTest.java | 9 +- .../http/logs/OtlpHttpLogRecordExporter.java | 39 ++--- .../http/metrics/OtlpHttpMetricExporter.java | 41 ++--- .../otlp/http/trace/OtlpHttpSpanExporter.java | 39 ++--- .../otlp/logs/OtlpGrpcLogRecordExporter.java | 39 ++--- .../otlp/metrics/OtlpGrpcMetricExporter.java | 41 ++--- .../otlp/trace/OtlpGrpcSpanExporter.java | 39 ++--- .../OtlpLogRecordExporterProviderTest.java | 13 +- .../OtlpSpanExporterProviderTest.java | 15 +- .../otlp/logs/LogReusableDataMarshaler.java | 51 ++++++ .../metrics/MetricReusableDataMarshaler.java | 51 ++++++ .../traces/SpanReusableDataMarshaler.java | 51 ++++++ 28 files changed, 504 insertions(+), 235 deletions(-) create mode 100644 exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/OtlpStdoutExporterBuilderUtil.java create mode 100644 exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java create mode 100644 exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java create mode 100644 exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/OtlpStdoutExporterBuilderUtil.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/OtlpStdoutExporterBuilderUtil.java new file mode 100644 index 00000000000..78079921c95 --- /dev/null +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/OtlpStdoutExporterBuilderUtil.java @@ -0,0 +1,19 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.logging.otlp.internal; + +import io.opentelemetry.sdk.common.export.MemoryMode; + +public class OtlpStdoutExporterBuilderUtil { + public OtlpStdoutExporterBuilderUtil() {} + + public static void validate(MemoryMode memoryMode, boolean wrapperJsonObject) { + if (memoryMode == MemoryMode.REUSABLE_DATA && !wrapperJsonObject) { + throw new IllegalArgumentException( + "Reusable data mode is not supported without wrapperJsonObject"); + } + } +} diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java index 96331e56d23..1b87143200c 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java @@ -5,10 +5,12 @@ package io.opentelemetry.exporter.logging.otlp.internal.logs; -import io.opentelemetry.exporter.internal.otlp.logs.LogsRequestMarshaler; +import io.opentelemetry.exporter.internal.marshal.Marshaler; +import io.opentelemetry.exporter.internal.otlp.logs.LogReusableDataMarshaler; import io.opentelemetry.exporter.internal.otlp.logs.ResourceLogsMarshaler; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.logs.export.LogRecordExporter; import java.util.Collection; @@ -33,11 +35,14 @@ public final class OtlpStdoutLogRecordExporter implements LogRecordExporter { private final Logger logger; private final JsonWriter jsonWriter; private final boolean wrapperJsonObject; + private final MemoryMode memoryMode; - OtlpStdoutLogRecordExporter(Logger logger, JsonWriter jsonWriter, boolean wrapperJsonObject) { + OtlpStdoutLogRecordExporter( + Logger logger, JsonWriter jsonWriter, boolean wrapperJsonObject, MemoryMode memoryMode) { this.logger = logger; this.jsonWriter = jsonWriter; this.wrapperJsonObject = wrapperJsonObject; + this.memoryMode = memoryMode; } /** Returns a new {@link OtlpStdoutLogRecordExporterBuilder}. */ @@ -53,8 +58,12 @@ public CompletableResultCode export(Collection logs) { } if (wrapperJsonObject) { - LogsRequestMarshaler request = LogsRequestMarshaler.create(logs); - return jsonWriter.write(request); + return new LogReusableDataMarshaler(memoryMode) { + @Override + public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { + return jsonWriter.write(exportRequest); + } + }.export(logs); } else { for (ResourceLogsMarshaler resourceLogs : ResourceLogsMarshaler.create(logs)) { CompletableResultCode resultCode = jsonWriter.write(resourceLogs); @@ -87,6 +96,7 @@ public String toString() { StringJoiner joiner = new StringJoiner(", ", "OtlpStdoutLogRecordExporter{", "}"); joiner.add("jsonWriter=" + jsonWriter); joiner.add("wrapperJsonObject=" + wrapperJsonObject); + joiner.add("memoryMode=" + memoryMode); return joiner.toString(); } } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterBuilder.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterBuilder.java index ea3f5c14234..d05fcf88fa1 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterBuilder.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterBuilder.java @@ -8,9 +8,11 @@ import static java.util.Objects.requireNonNull; import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingLogRecordExporter; +import io.opentelemetry.exporter.logging.otlp.internal.OtlpStdoutExporterBuilderUtil; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.LoggerJsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.StreamJsonWriter; +import io.opentelemetry.sdk.common.export.MemoryMode; import java.io.OutputStream; import java.util.logging.Logger; @@ -27,6 +29,7 @@ public final class OtlpStdoutLogRecordExporterBuilder { private final Logger logger; private JsonWriter jsonWriter; private boolean wrapperJsonObject = true; + private MemoryMode memoryMode = MemoryMode.IMMUTABLE_DATA; public OtlpStdoutLogRecordExporterBuilder(Logger logger) { this.logger = logger; @@ -44,6 +47,17 @@ public OtlpStdoutLogRecordExporterBuilder setWrapperJsonObject(boolean wrapperJs return this; } + /** + * Set the {@link MemoryMode}. If unset, defaults to {@link MemoryMode#IMMUTABLE_DATA}. + * + *

When memory mode is {@link MemoryMode#REUSABLE_DATA}, serialization is optimized to reduce + * memory allocation. + */ + public OtlpStdoutLogRecordExporterBuilder setMemoryMode(MemoryMode memoryMode) { + this.memoryMode = memoryMode; + return this; + } + /** * Sets the exporter to use the specified output stream. * @@ -71,6 +85,7 @@ public OtlpStdoutLogRecordExporterBuilder setOutput(Logger logger) { * @return a new exporter's instance */ public OtlpStdoutLogRecordExporter build() { - return new OtlpStdoutLogRecordExporter(logger, jsonWriter, wrapperJsonObject); + OtlpStdoutExporterBuilderUtil.validate(memoryMode, wrapperJsonObject); + return new OtlpStdoutLogRecordExporter(logger, jsonWriter, wrapperJsonObject, memoryMode); } } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterComponentProvider.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterComponentProvider.java index 0806b7f0b40..8afd4e58c85 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterComponentProvider.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterComponentProvider.java @@ -5,6 +5,7 @@ package io.opentelemetry.exporter.logging.otlp.internal.logs; +import io.opentelemetry.exporter.internal.ExporterBuilderUtil; import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties; import io.opentelemetry.sdk.logs.export.LogRecordExporter; @@ -31,6 +32,7 @@ public String getName() { @Override public LogRecordExporter create(StructuredConfigProperties config) { OtlpStdoutLogRecordExporterBuilder builder = OtlpStdoutLogRecordExporter.builder(); + ExporterBuilderUtil.configureExporterMemoryMode(config, builder::setMemoryMode); return builder.build(); } } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterProvider.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterProvider.java index 23ba0079295..08b8021590d 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterProvider.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterProvider.java @@ -5,6 +5,7 @@ package io.opentelemetry.exporter.logging.otlp.internal.logs; +import io.opentelemetry.exporter.internal.ExporterBuilderUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider; import io.opentelemetry.sdk.logs.export.LogRecordExporter; @@ -20,6 +21,7 @@ public final class OtlpStdoutLogRecordExporterProvider @Override public LogRecordExporter createExporter(ConfigProperties config) { OtlpStdoutLogRecordExporterBuilder builder = OtlpStdoutLogRecordExporter.builder(); + ExporterBuilderUtil.configureExporterMemoryMode(config, builder::setMemoryMode); return builder.build(); } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java index 81e9bef105c..fc900dd4261 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java @@ -5,10 +5,12 @@ package io.opentelemetry.exporter.logging.otlp.internal.metrics; -import io.opentelemetry.exporter.internal.otlp.metrics.MetricsRequestMarshaler; +import io.opentelemetry.exporter.internal.marshal.Marshaler; +import io.opentelemetry.exporter.internal.otlp.metrics.MetricReusableDataMarshaler; import io.opentelemetry.exporter.internal.otlp.metrics.ResourceMetricsMarshaler; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; 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; @@ -37,6 +39,7 @@ public final class OtlpStdoutMetricExporter implements MetricExporter { private final Logger logger; private final JsonWriter jsonWriter; private final boolean wrapperJsonObject; + private final MemoryMode memoryMode; private final AggregationTemporalitySelector aggregationTemporalitySelector; private final DefaultAggregationSelector defaultAggregationSelector; @@ -44,11 +47,13 @@ public final class OtlpStdoutMetricExporter implements MetricExporter { Logger logger, JsonWriter jsonWriter, boolean wrapperJsonObject, + MemoryMode memoryMode, AggregationTemporalitySelector aggregationTemporalitySelector, DefaultAggregationSelector defaultAggregationSelector) { this.logger = logger; this.jsonWriter = jsonWriter; this.wrapperJsonObject = wrapperJsonObject; + this.memoryMode = memoryMode; this.aggregationTemporalitySelector = aggregationTemporalitySelector; this.defaultAggregationSelector = defaultAggregationSelector; } @@ -69,6 +74,11 @@ public Aggregation getDefaultAggregation(InstrumentType instrumentType) { return defaultAggregationSelector.getDefaultAggregation(instrumentType); } + @Override + public MemoryMode getMemoryMode() { + return memoryMode; + } + @Override public CompletableResultCode export(Collection metrics) { if (isShutdown.get()) { @@ -76,8 +86,12 @@ public CompletableResultCode export(Collection metrics) { } if (wrapperJsonObject) { - MetricsRequestMarshaler request = MetricsRequestMarshaler.create(metrics); - return jsonWriter.write(request); + return new MetricReusableDataMarshaler(memoryMode) { + @Override + public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { + return jsonWriter.write(exportRequest); + } + }.export(metrics); } else { for (ResourceMetricsMarshaler resourceMetrics : ResourceMetricsMarshaler.create(metrics)) { CompletableResultCode resultCode = jsonWriter.write(resourceMetrics); @@ -110,6 +124,13 @@ public String toString() { StringJoiner joiner = new StringJoiner(", ", "OtlpStdoutMetricExporter{", "}"); joiner.add("jsonWriter=" + jsonWriter); joiner.add("wrapperJsonObject=" + wrapperJsonObject); + joiner.add("memoryMode=" + memoryMode); + joiner.add( + "aggregationTemporalitySelector=" + + AggregationTemporalitySelector.asString(aggregationTemporalitySelector)); + joiner.add( + "defaultAggregationSelector=" + + DefaultAggregationSelector.asString(defaultAggregationSelector)); return joiner.toString(); } } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterBuilder.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterBuilder.java index 63f16c09060..b4c235f1852 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterBuilder.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterBuilder.java @@ -8,9 +8,11 @@ import static java.util.Objects.requireNonNull; import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingMetricExporter; +import io.opentelemetry.exporter.logging.otlp.internal.OtlpStdoutExporterBuilderUtil; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.LoggerJsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.StreamJsonWriter; +import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.InstrumentType; import io.opentelemetry.sdk.metrics.export.AggregationTemporalitySelector; import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector; @@ -40,6 +42,7 @@ public final class OtlpStdoutMetricExporterBuilder { private final Logger logger; private JsonWriter jsonWriter; private boolean wrapperJsonObject = true; + private MemoryMode memoryMode = MemoryMode.IMMUTABLE_DATA; public OtlpStdoutMetricExporterBuilder(Logger logger) { this.logger = logger; @@ -57,6 +60,17 @@ public OtlpStdoutMetricExporterBuilder setWrapperJsonObject(boolean wrapperJsonO return this; } + /** + * Set the {@link MemoryMode}. If unset, defaults to {@link MemoryMode#IMMUTABLE_DATA}. + * + *

When memory mode is {@link MemoryMode#REUSABLE_DATA}, serialization is optimized to reduce + * memory allocation. + */ + public OtlpStdoutMetricExporterBuilder setMemoryMode(MemoryMode memoryMode) { + this.memoryMode = memoryMode; + return this; + } + /** * Sets the exporter to use the specified output stream. * @@ -114,10 +128,12 @@ public OtlpStdoutMetricExporterBuilder setDefaultAggregationSelector( * @return a new exporter's instance */ public OtlpStdoutMetricExporter build() { + OtlpStdoutExporterBuilderUtil.validate(memoryMode, wrapperJsonObject); return new OtlpStdoutMetricExporter( logger, jsonWriter, wrapperJsonObject, + memoryMode, aggregationTemporalitySelector, defaultAggregationSelector); } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterComponentProvider.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterComponentProvider.java index dd8b3f643fa..e1e2dc88153 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterComponentProvider.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterComponentProvider.java @@ -32,6 +32,7 @@ public String getName() { @Override public MetricExporter create(StructuredConfigProperties config) { OtlpStdoutMetricExporterBuilder builder = OtlpStdoutMetricExporter.builder(); + ExporterBuilderUtil.configureExporterMemoryMode(config, builder::setMemoryMode); ExporterBuilderUtil.configureOtlpAggregationTemporality( config, builder::setAggregationTemporalitySelector); ExporterBuilderUtil.configureOtlpHistogramDefaultAggregation( diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterProvider.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterProvider.java index 9eace851190..84f32f56c7b 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterProvider.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterProvider.java @@ -20,6 +20,7 @@ public final class OtlpStdoutMetricExporterProvider implements ConfigurableMetri @Override public MetricExporter createExporter(ConfigProperties config) { OtlpStdoutMetricExporterBuilder builder = OtlpStdoutMetricExporter.builder(); + ExporterBuilderUtil.configureExporterMemoryMode(config, builder::setMemoryMode); ExporterBuilderUtil.configureOtlpAggregationTemporality( config, builder::setAggregationTemporalitySelector); ExporterBuilderUtil.configureOtlpHistogramDefaultAggregation( diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java index 39c8829ef9b..cc1113a2a5d 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java @@ -5,10 +5,12 @@ package io.opentelemetry.exporter.logging.otlp.internal.traces; +import io.opentelemetry.exporter.internal.marshal.Marshaler; import io.opentelemetry.exporter.internal.otlp.traces.ResourceSpansMarshaler; -import io.opentelemetry.exporter.internal.otlp.traces.TraceRequestMarshaler; +import io.opentelemetry.exporter.internal.otlp.traces.SpanReusableDataMarshaler; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.trace.data.SpanData; import io.opentelemetry.sdk.trace.export.SpanExporter; import java.util.Collection; @@ -32,11 +34,14 @@ public final class OtlpStdoutSpanExporter implements SpanExporter { private final Logger logger; private final JsonWriter jsonWriter; private final boolean wrapperJsonObject; + private final MemoryMode memoryMode; - OtlpStdoutSpanExporter(Logger logger, JsonWriter jsonWriter, boolean wrapperJsonObject) { + OtlpStdoutSpanExporter( + Logger logger, JsonWriter jsonWriter, boolean wrapperJsonObject, MemoryMode memoryMode) { this.logger = logger; this.jsonWriter = jsonWriter; this.wrapperJsonObject = wrapperJsonObject; + this.memoryMode = memoryMode; } /** Returns a new {@link OtlpStdoutSpanExporterBuilder}. */ @@ -52,8 +57,12 @@ public CompletableResultCode export(Collection spans) { } if (wrapperJsonObject) { - TraceRequestMarshaler request = TraceRequestMarshaler.create(spans); - return jsonWriter.write(request); + return new SpanReusableDataMarshaler(memoryMode) { + @Override + public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { + return jsonWriter.write(exportRequest); + } + }.export(spans); } else { for (ResourceSpansMarshaler resourceSpans : ResourceSpansMarshaler.create(spans)) { CompletableResultCode resultCode = jsonWriter.write(resourceSpans); @@ -86,6 +95,7 @@ public String toString() { StringJoiner joiner = new StringJoiner(", ", "OtlpStdoutSpanExporter{", "}"); joiner.add("jsonWriter=" + jsonWriter); joiner.add("wrapperJsonObject=" + wrapperJsonObject); + joiner.add("memoryMode=" + memoryMode); return joiner.toString(); } } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterBuilder.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterBuilder.java index 2ca9e5a97b3..977c2935aa5 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterBuilder.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterBuilder.java @@ -8,9 +8,11 @@ import static java.util.Objects.requireNonNull; import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingSpanExporter; +import io.opentelemetry.exporter.logging.otlp.internal.OtlpStdoutExporterBuilderUtil; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.LoggerJsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.StreamJsonWriter; +import io.opentelemetry.sdk.common.export.MemoryMode; import java.io.OutputStream; import java.util.logging.Logger; @@ -27,6 +29,7 @@ public final class OtlpStdoutSpanExporterBuilder { private final Logger logger; private JsonWriter jsonWriter; private boolean wrapperJsonObject = true; + private MemoryMode memoryMode = MemoryMode.IMMUTABLE_DATA; public OtlpStdoutSpanExporterBuilder(Logger logger) { this.logger = logger; @@ -44,6 +47,17 @@ public OtlpStdoutSpanExporterBuilder setWrapperJsonObject(boolean wrapperJsonObj return this; } + /** + * Set the {@link MemoryMode}. If unset, defaults to {@link MemoryMode#IMMUTABLE_DATA}. + * + *

When memory mode is {@link MemoryMode#REUSABLE_DATA}, serialization is optimized to reduce + * memory allocation. + */ + public OtlpStdoutSpanExporterBuilder setMemoryMode(MemoryMode memoryMode) { + this.memoryMode = memoryMode; + return this; + } + /** * Sets the exporter to use the specified output stream. * @@ -71,6 +85,7 @@ public OtlpStdoutSpanExporterBuilder setOutput(Logger logger) { * @return a new exporter's instance */ public OtlpStdoutSpanExporter build() { - return new OtlpStdoutSpanExporter(logger, jsonWriter, wrapperJsonObject); + OtlpStdoutExporterBuilderUtil.validate(memoryMode, wrapperJsonObject); + return new OtlpStdoutSpanExporter(logger, jsonWriter, wrapperJsonObject, memoryMode); } } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterComponentProvider.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterComponentProvider.java index 1d60e1a37b8..af299c16251 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterComponentProvider.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterComponentProvider.java @@ -5,6 +5,7 @@ package io.opentelemetry.exporter.logging.otlp.internal.traces; +import io.opentelemetry.exporter.internal.ExporterBuilderUtil; import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties; import io.opentelemetry.sdk.trace.export.SpanExporter; @@ -31,6 +32,7 @@ public String getName() { @Override public SpanExporter create(StructuredConfigProperties config) { OtlpStdoutSpanExporterBuilder builder = OtlpStdoutSpanExporter.builder(); + ExporterBuilderUtil.configureExporterMemoryMode(config, builder::setMemoryMode); return builder.build(); } } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterProvider.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterProvider.java index e5d2f008315..84514492f24 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterProvider.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterProvider.java @@ -5,6 +5,7 @@ package io.opentelemetry.exporter.logging.otlp.internal.traces; +import io.opentelemetry.exporter.internal.ExporterBuilderUtil; import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider; import io.opentelemetry.sdk.trace.export.SpanExporter; @@ -19,6 +20,7 @@ public final class OtlpStdoutSpanExporterProvider implements ConfigurableSpanExp @Override public SpanExporter createExporter(ConfigProperties config) { OtlpStdoutSpanExporterBuilder builder = OtlpStdoutSpanExporter.builder(); + ExporterBuilderUtil.configureExporterMemoryMode(config, builder::setMemoryMode); return builder.build(); } diff --git a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/AbstractOtlpStdoutExporterTest.java b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/AbstractOtlpStdoutExporterTest.java index b18f432a4de..3988fae332d 100644 --- a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/AbstractOtlpStdoutExporterTest.java +++ b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/AbstractOtlpStdoutExporterTest.java @@ -6,8 +6,11 @@ package io.opentelemetry.exporter.logging.otlp; import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.google.common.collect.ImmutableList; import com.google.common.collect.Streams; @@ -16,6 +19,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider; import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties; +import io.opentelemetry.sdk.common.export.MemoryMode; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -27,6 +31,7 @@ import java.nio.file.Path; import java.util.ServiceLoader; import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; import java.util.stream.Stream; import javax.annotation.Nullable; import org.json.JSONException; @@ -75,7 +80,7 @@ public AbstractOtlpStdoutExporterTest( } protected abstract T createExporter( - @Nullable OutputStream outputStream, boolean wrapperJsonObject); + @Nullable OutputStream outputStream, MemoryMode memoryMode, boolean wrapperJsonObject); protected abstract T createDefaultExporter(); @@ -128,12 +133,13 @@ enum OutputType { } public static class TestCase { - + private final MemoryMode memoryMode; private final boolean wrapperJsonObject; private final OutputType outputType; - public TestCase(OutputType outputType, boolean wrapperJsonObject) { + public TestCase(OutputType outputType, MemoryMode memoryMode, boolean wrapperJsonObject) { this.outputType = outputType; + this.memoryMode = memoryMode; this.wrapperJsonObject = wrapperJsonObject; } @@ -144,25 +150,55 @@ public OutputType getOutputType() { public boolean isWrapperJsonObject() { return wrapperJsonObject; } + + public MemoryMode getMemoryMode() { + return memoryMode; + } } static Stream exportTestCases() { return ImmutableList.of( - testCase(OutputType.SYSTEM_OUT, /* wrapperJsonObject= */ true), - testCase(OutputType.SYSTEM_OUT, /* wrapperJsonObject= */ false), - testCase(OutputType.FILE, /* wrapperJsonObject= */ true), - testCase(OutputType.FILE, /* wrapperJsonObject= */ false), - testCase(OutputType.FILE_AND_BUFFERED_WRITER, /* wrapperJsonObject= */ true), - testCase(OutputType.FILE_AND_BUFFERED_WRITER, /* wrapperJsonObject= */ false), - testCase(OutputType.LOGGER, /* wrapperJsonObject= */ true), - testCase(OutputType.LOGGER, /* wrapperJsonObject= */ false)) + testCase(OutputType.SYSTEM_OUT, MemoryMode.IMMUTABLE_DATA, /* wrapperJsonObject= */ true), + testCase(OutputType.SYSTEM_OUT, MemoryMode.IMMUTABLE_DATA, /* wrapperJsonObject= */ false), + testCase(OutputType.FILE, MemoryMode.IMMUTABLE_DATA, /* wrapperJsonObject= */ true), + testCase(OutputType.FILE, MemoryMode.IMMUTABLE_DATA, /* wrapperJsonObject= */ false), + testCase( + OutputType.FILE_AND_BUFFERED_WRITER, + MemoryMode.IMMUTABLE_DATA, + /* wrapperJsonObject= */ true), + testCase( + OutputType.FILE_AND_BUFFERED_WRITER, + MemoryMode.IMMUTABLE_DATA, + /* wrapperJsonObject= */ false), + testCase(OutputType.LOGGER, MemoryMode.IMMUTABLE_DATA, /* wrapperJsonObject= */ true), + testCase(OutputType.LOGGER, MemoryMode.IMMUTABLE_DATA, /* wrapperJsonObject= */ false), + testCase(OutputType.SYSTEM_OUT, MemoryMode.REUSABLE_DATA, /* wrapperJsonObject= */ true), + testCase(OutputType.SYSTEM_OUT, MemoryMode.REUSABLE_DATA, /* wrapperJsonObject= */ false), + testCase(OutputType.FILE, MemoryMode.REUSABLE_DATA, /* wrapperJsonObject= */ true), + testCase(OutputType.FILE, MemoryMode.REUSABLE_DATA, /* wrapperJsonObject= */ false), + testCase( + OutputType.FILE_AND_BUFFERED_WRITER, + MemoryMode.REUSABLE_DATA, + /* wrapperJsonObject= */ true), + testCase( + OutputType.FILE_AND_BUFFERED_WRITER, + MemoryMode.REUSABLE_DATA, + /* wrapperJsonObject= */ false), + testCase(OutputType.LOGGER, MemoryMode.REUSABLE_DATA, /* wrapperJsonObject= */ true), + testCase(OutputType.LOGGER, MemoryMode.REUSABLE_DATA, /* wrapperJsonObject= */ false)) .stream(); } - private static Arguments testCase(OutputType type, boolean wrapperJsonObject) { + private static Arguments testCase( + OutputType type, MemoryMode memoryMode, boolean wrapperJsonObject) { return Arguments.of( - "output=" + type + ", wrapperJsonObject=" + wrapperJsonObject, - new TestCase(type, wrapperJsonObject)); + "output=" + + type + + ", wrapperJsonObject=" + + wrapperJsonObject + + ", memoryMode=" + + memoryMode, + new TestCase(type, memoryMode, wrapperJsonObject)); } @SuppressWarnings("SystemOut") @@ -190,8 +226,19 @@ void exportWithProgrammaticConfig(String name, TestCase testCase) default: throw new IllegalStateException("Unexpected value: " + testCase.getOutputType()); } - T exporter = createExporter(outputStream, testCase.isWrapperJsonObject()); - testDataExporter.export(exporter); + + Supplier exporter = + () -> + createExporter(outputStream, testCase.getMemoryMode(), testCase.isWrapperJsonObject()); + + if (testCase.getMemoryMode() == MemoryMode.REUSABLE_DATA && !testCase.isWrapperJsonObject()) { + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(exporter::get) + .withMessage("Reusable data mode is not supported without wrapperJsonObject"); + return; + } + + testDataExporter.export(exporter.get()); String output = output(outputStream, file); String expectedJson = testDataExporter.getExpectedJson(testCase.isWrapperJsonObject()); @@ -215,40 +262,69 @@ void testShutdown() { @Test void defaultToString() { - assertFullToString(createDefaultExporter(), defaultConfigString); + assertThat(createDefaultExporter()).hasToString(defaultConfigString); - assertFullToString( - loadExporter(DefaultConfigProperties.createFromMap(emptyMap())), defaultConfigString); + assertThat(exporterFromProvider(DefaultConfigProperties.createFromMap(emptyMap()))) + .hasToString(defaultConfigString); } - protected Object exporterFromComponentProvider(StructuredConfigProperties properties) { - return ((ComponentProvider) - loadSpi(ComponentProvider.class) - .filter( - p -> { - ComponentProvider c = (ComponentProvider) p; - return "experimental-otlp/stdout".equals(c.getName()) - && c.getType().equals(componentProviderType); - }) - .findFirst() - .orElseThrow(() -> new IllegalStateException("No provider found"))) - .create(properties); + @Test + void providerConfig() { + assertThat( + exporterFromProvider( + DefaultConfigProperties.createFromMap( + singletonMap("otel.java.experimental.exporter.memory_mode", "immutable_data")))) + .extracting("memoryMode") + .isEqualTo(MemoryMode.IMMUTABLE_DATA); + assertThat( + exporterFromProvider( + DefaultConfigProperties.createFromMap( + singletonMap("otel.java.experimental.exporter.memory_mode", "reusable_data")))) + .extracting("memoryMode") + .isEqualTo(MemoryMode.REUSABLE_DATA); } @Test void componentProviderConfig() { StructuredConfigProperties properties = mock(StructuredConfigProperties.class); - Object exporter = exporterFromComponentProvider(properties); + T exporter = exporterFromComponentProvider(properties); assertThat(exporter).extracting("wrapperJsonObject").isEqualTo(true); + assertThat(exporter).extracting("memoryMode").isEqualTo(MemoryMode.IMMUTABLE_DATA); assertThat(exporter) .extracting("jsonWriter") .extracting(Object::toString) .isEqualTo("StreamJsonWriter{outputStream=stdout}"); + + when(properties.getString("memory_mode")).thenReturn("IMMUTABLE_DATA"); + assertThat(exporterFromComponentProvider(properties)) + .extracting("memoryMode") + .isEqualTo(MemoryMode.IMMUTABLE_DATA); + + when(properties.getString("memory_mode")).thenReturn("REUSABLE_DATA"); + assertThat(exporterFromComponentProvider(properties)) + .extracting("memoryMode") + .isEqualTo(MemoryMode.REUSABLE_DATA); } @SuppressWarnings("unchecked") - protected T loadExporter(ConfigProperties config) { + protected T exporterFromComponentProvider(StructuredConfigProperties properties) { + return (T) + ((ComponentProvider) + loadSpi(ComponentProvider.class) + .filter( + p -> { + ComponentProvider c = (ComponentProvider) p; + return "experimental-otlp/stdout".equals(c.getName()) + && c.getType().equals(componentProviderType); + }) + .findFirst() + .orElseThrow(() -> new IllegalStateException("No provider found"))) + .create(properties); + } + + @SuppressWarnings("unchecked") + protected T exporterFromProvider(ConfigProperties config) { Object provider = loadProvider(); try { @@ -280,8 +356,4 @@ private Object loadProvider() { protected static Stream loadSpi(Class type) { return Streams.stream(ServiceLoader.load(type, type.getClassLoader()).iterator()); } - - private void assertFullToString(T exporter, String expected) { - assertThat(exporter.toString()).isEqualTo(expected); - } } diff --git a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutLogRecordExporterTest.java b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutLogRecordExporterTest.java index e234b9745dc..c19fba0fe3e 100644 --- a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutLogRecordExporterTest.java +++ b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutLogRecordExporterTest.java @@ -8,6 +8,7 @@ import io.opentelemetry.exporter.logging.otlp.internal.logs.OtlpStdoutLogRecordExporter; import io.opentelemetry.exporter.logging.otlp.internal.logs.OtlpStdoutLogRecordExporterBuilder; import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider; +import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.logs.export.LogRecordExporter; import java.io.OutputStream; import java.util.logging.Logger; @@ -22,7 +23,7 @@ public OtlpStdoutLogRecordExporterTest() { OtlpStdoutLogRecordExporter.class, ConfigurableLogRecordExporterProvider.class, LogRecordExporter.class, - "OtlpStdoutLogRecordExporter{jsonWriter=StreamJsonWriter{outputStream=stdout}, wrapperJsonObject=true}"); + "OtlpStdoutLogRecordExporter{jsonWriter=StreamJsonWriter{outputStream=stdout}, wrapperJsonObject=true, memoryMode=IMMUTABLE_DATA}"); } @Override @@ -32,9 +33,11 @@ protected OtlpStdoutLogRecordExporter createDefaultExporter() { @Override protected OtlpStdoutLogRecordExporter createExporter( - @Nullable OutputStream outputStream, boolean wrapperJsonObject) { + @Nullable OutputStream outputStream, MemoryMode memoryMode, boolean wrapperJsonObject) { OtlpStdoutLogRecordExporterBuilder builder = - OtlpStdoutLogRecordExporter.builder().setWrapperJsonObject(wrapperJsonObject); + OtlpStdoutLogRecordExporter.builder() + .setMemoryMode(memoryMode) + .setWrapperJsonObject(wrapperJsonObject); if (outputStream != null) { builder.setOutput(outputStream); } else { diff --git a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutMetricExporterTest.java b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutMetricExporterTest.java index fdc6d945fc4..fc081e229f4 100644 --- a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutMetricExporterTest.java +++ b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutMetricExporterTest.java @@ -16,6 +16,7 @@ import io.opentelemetry.sdk.autoconfigure.spi.internal.DefaultConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.internal.StructuredConfigProperties; import io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider; +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; @@ -36,7 +37,7 @@ public OtlpStdoutMetricExporterTest() { OtlpStdoutMetricExporter.class, ConfigurableMetricExporterProvider.class, MetricExporter.class, - "OtlpStdoutMetricExporter{jsonWriter=StreamJsonWriter{outputStream=stdout}, wrapperJsonObject=true}"); + "OtlpStdoutMetricExporter{jsonWriter=StreamJsonWriter{outputStream=stdout}, wrapperJsonObject=true, memoryMode=IMMUTABLE_DATA, aggregationTemporalitySelector=AggregationTemporalitySelector{COUNTER=CUMULATIVE, UP_DOWN_COUNTER=CUMULATIVE, HISTOGRAM=CUMULATIVE, OBSERVABLE_COUNTER=CUMULATIVE, OBSERVABLE_UP_DOWN_COUNTER=CUMULATIVE, OBSERVABLE_GAUGE=CUMULATIVE, GAUGE=CUMULATIVE}, defaultAggregationSelector=DefaultAggregationSelector{COUNTER=default, UP_DOWN_COUNTER=default, HISTOGRAM=default, OBSERVABLE_COUNTER=default, OBSERVABLE_UP_DOWN_COUNTER=default, OBSERVABLE_GAUGE=default, GAUGE=default}}"); } @Override @@ -46,9 +47,11 @@ protected OtlpStdoutMetricExporter createDefaultExporter() { @Override protected OtlpStdoutMetricExporter createExporter( - @Nullable OutputStream outputStream, boolean wrapperJsonObject) { + @Nullable OutputStream outputStream, MemoryMode memoryMode, boolean wrapperJsonObject) { OtlpStdoutMetricExporterBuilder builder = - OtlpStdoutMetricExporter.builder().setWrapperJsonObject(wrapperJsonObject); + OtlpStdoutMetricExporter.builder() + .setMemoryMode(memoryMode) + .setWrapperJsonObject(wrapperJsonObject); if (outputStream != null) { builder.setOutput(outputStream); } else { @@ -61,7 +64,7 @@ protected OtlpStdoutMetricExporter createExporter( @Test void providerMetricConfig() { OtlpStdoutMetricExporter exporter = - loadExporter( + exporterFromProvider( DefaultConfigProperties.createFromMap( ImmutableMap.of( "otel.exporter.otlp.metrics.temporality.preference", @@ -83,8 +86,7 @@ void componentProviderMetricConfig() { when(properties.getString("default_histogram_aggregation")) .thenReturn("BASE2_EXPONENTIAL_BUCKET_HISTOGRAM"); - OtlpStdoutMetricExporter exporter = - (OtlpStdoutMetricExporter) exporterFromComponentProvider(properties); + OtlpStdoutMetricExporter exporter = exporterFromComponentProvider(properties); assertThat(exporter.getAggregationTemporality(InstrumentType.COUNTER)) .isEqualTo(AggregationTemporality.DELTA); diff --git a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutSpanExporterTest.java b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutSpanExporterTest.java index 472ff4cd731..01d3a96ccd2 100644 --- a/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutSpanExporterTest.java +++ b/exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpStdoutSpanExporterTest.java @@ -8,6 +8,7 @@ import io.opentelemetry.exporter.logging.otlp.internal.traces.OtlpStdoutSpanExporter; import io.opentelemetry.exporter.logging.otlp.internal.traces.OtlpStdoutSpanExporterBuilder; import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider; +import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.trace.export.SpanExporter; import java.io.OutputStream; import java.util.logging.Logger; @@ -21,7 +22,7 @@ public OtlpStdoutSpanExporterTest() { OtlpStdoutSpanExporter.class, ConfigurableSpanExporterProvider.class, SpanExporter.class, - "OtlpStdoutSpanExporter{jsonWriter=StreamJsonWriter{outputStream=stdout}, wrapperJsonObject=true}"); + "OtlpStdoutSpanExporter{jsonWriter=StreamJsonWriter{outputStream=stdout}, wrapperJsonObject=true, memoryMode=IMMUTABLE_DATA}"); } @Override @@ -31,9 +32,11 @@ protected OtlpStdoutSpanExporter createDefaultExporter() { @Override protected OtlpStdoutSpanExporter createExporter( - @Nullable OutputStream outputStream, boolean wrapperJsonObject) { + @Nullable OutputStream outputStream, MemoryMode memoryMode, boolean wrapperJsonObject) { OtlpStdoutSpanExporterBuilder builder = - OtlpStdoutSpanExporter.builder().setWrapperJsonObject(wrapperJsonObject); + OtlpStdoutSpanExporter.builder() + .setMemoryMode(memoryMode) + .setWrapperJsonObject(wrapperJsonObject); if (outputStream != null) { builder.setOutput(outputStream); } else { diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java index 4f3202ceb99..ff79f86dea8 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java @@ -8,15 +8,12 @@ import io.opentelemetry.exporter.internal.http.HttpExporter; import io.opentelemetry.exporter.internal.http.HttpExporterBuilder; import io.opentelemetry.exporter.internal.marshal.Marshaler; -import io.opentelemetry.exporter.internal.otlp.logs.LogsRequestMarshaler; -import io.opentelemetry.exporter.internal.otlp.logs.LowAllocationLogsRequestMarshaler; +import io.opentelemetry.exporter.internal.otlp.logs.LogReusableDataMarshaler; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.logs.export.LogRecordExporter; -import java.util.ArrayDeque; import java.util.Collection; -import java.util.Deque; import java.util.StringJoiner; import javax.annotation.concurrent.ThreadSafe; @@ -28,10 +25,9 @@ @ThreadSafe public final class OtlpHttpLogRecordExporter implements LogRecordExporter { - private final Deque marshalerPool = new ArrayDeque<>(); private final HttpExporterBuilder builder; private final HttpExporter delegate; - private final MemoryMode memoryMode; + private final LogReusableDataMarshaler marshaler; OtlpHttpLogRecordExporter( HttpExporterBuilder builder, @@ -39,7 +35,13 @@ public final class OtlpHttpLogRecordExporter implements LogRecordExporter { MemoryMode memoryMode) { this.builder = builder; this.delegate = delegate; - this.memoryMode = memoryMode; + this.marshaler = + new LogReusableDataMarshaler(memoryMode) { + @Override + public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { + return delegate.export(exportRequest, numItems); + } + }; } /** @@ -71,7 +73,7 @@ public static OtlpHttpLogRecordExporterBuilder builder() { * @since 1.29.0 */ public OtlpHttpLogRecordExporterBuilder toBuilder() { - return new OtlpHttpLogRecordExporterBuilder(builder.copy(), memoryMode); + return new OtlpHttpLogRecordExporterBuilder(builder.copy(), marshaler.getMemoryMode()); } /** @@ -82,24 +84,7 @@ public OtlpHttpLogRecordExporterBuilder toBuilder() { */ @Override public CompletableResultCode export(Collection logs) { - if (memoryMode == MemoryMode.REUSABLE_DATA) { - LowAllocationLogsRequestMarshaler marshaler = marshalerPool.poll(); - if (marshaler == null) { - marshaler = new LowAllocationLogsRequestMarshaler(); - } - LowAllocationLogsRequestMarshaler exportMarshaler = marshaler; - exportMarshaler.initialize(logs); - return delegate - .export(exportMarshaler, logs.size()) - .whenComplete( - () -> { - exportMarshaler.reset(); - marshalerPool.add(exportMarshaler); - }); - } - // MemoryMode == MemoryMode.IMMUTABLE_DATA - LogsRequestMarshaler request = LogsRequestMarshaler.create(logs); - return delegate.export(request, logs.size()); + return marshaler.export(logs); } @Override @@ -117,7 +102,7 @@ public CompletableResultCode shutdown() { public String toString() { StringJoiner joiner = new StringJoiner(", ", "OtlpHttpLogRecordExporter{", "}"); joiner.add(builder.toString(false)); - joiner.add("memoryMode=" + memoryMode); + joiner.add("memoryMode=" + marshaler.getMemoryMode()); return joiner.toString(); } } diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java index 1634d47fee5..5206c2ed615 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java @@ -8,8 +8,7 @@ import io.opentelemetry.exporter.internal.http.HttpExporter; import io.opentelemetry.exporter.internal.http.HttpExporterBuilder; import io.opentelemetry.exporter.internal.marshal.Marshaler; -import io.opentelemetry.exporter.internal.otlp.metrics.LowAllocationMetricsRequestMarshaler; -import io.opentelemetry.exporter.internal.otlp.metrics.MetricsRequestMarshaler; +import io.opentelemetry.exporter.internal.otlp.metrics.MetricReusableDataMarshaler; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.Aggregation; @@ -19,9 +18,7 @@ import io.opentelemetry.sdk.metrics.export.AggregationTemporalitySelector; import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector; import io.opentelemetry.sdk.metrics.export.MetricExporter; -import java.util.ArrayDeque; import java.util.Collection; -import java.util.Deque; import java.util.StringJoiner; import javax.annotation.concurrent.ThreadSafe; @@ -33,12 +30,11 @@ @ThreadSafe public final class OtlpHttpMetricExporter implements MetricExporter { - private final Deque marshalerPool = new ArrayDeque<>(); private final HttpExporterBuilder builder; private final HttpExporter delegate; private final AggregationTemporalitySelector aggregationTemporalitySelector; private final DefaultAggregationSelector defaultAggregationSelector; - private final MemoryMode memoryMode; + private final MetricReusableDataMarshaler marshaler; OtlpHttpMetricExporter( HttpExporterBuilder builder, @@ -50,7 +46,13 @@ public final class OtlpHttpMetricExporter implements MetricExporter { this.delegate = delegate; this.aggregationTemporalitySelector = aggregationTemporalitySelector; this.defaultAggregationSelector = defaultAggregationSelector; - this.memoryMode = memoryMode; + this.marshaler = + new MetricReusableDataMarshaler(memoryMode) { + @Override + public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { + return delegate.export(exportRequest, numItems); + } + }; } /** @@ -82,7 +84,7 @@ public static OtlpHttpMetricExporterBuilder builder() { * @since 1.29.0 */ public OtlpHttpMetricExporterBuilder toBuilder() { - return new OtlpHttpMetricExporterBuilder(builder.copy(), memoryMode); + return new OtlpHttpMetricExporterBuilder(builder.copy(), marshaler.getMemoryMode()); } @Override @@ -97,7 +99,7 @@ public Aggregation getDefaultAggregation(InstrumentType instrumentType) { @Override public MemoryMode getMemoryMode() { - return memoryMode; + return marshaler.getMemoryMode(); } /** @@ -108,24 +110,7 @@ public MemoryMode getMemoryMode() { */ @Override public CompletableResultCode export(Collection metrics) { - if (memoryMode == MemoryMode.REUSABLE_DATA) { - LowAllocationMetricsRequestMarshaler marshaler = marshalerPool.poll(); - if (marshaler == null) { - marshaler = new LowAllocationMetricsRequestMarshaler(); - } - LowAllocationMetricsRequestMarshaler exportMarshaler = marshaler; - exportMarshaler.initialize(metrics); - return delegate - .export(exportMarshaler, metrics.size()) - .whenComplete( - () -> { - exportMarshaler.reset(); - marshalerPool.add(exportMarshaler); - }); - } - // MemoryMode == MemoryMode.IMMUTABLE_DATA - MetricsRequestMarshaler request = MetricsRequestMarshaler.create(metrics); - return delegate.export(request, metrics.size()); + return marshaler.export(metrics); } /** @@ -154,7 +139,7 @@ public String toString() { joiner.add( "defaultAggregationSelector=" + DefaultAggregationSelector.asString(defaultAggregationSelector)); - joiner.add("memoryMode=" + memoryMode); + joiner.add("memoryMode=" + marshaler.getMemoryMode()); return joiner.toString(); } } diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java index 86d4016adb6..8123eb4299c 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java @@ -8,15 +8,12 @@ import io.opentelemetry.exporter.internal.http.HttpExporter; import io.opentelemetry.exporter.internal.http.HttpExporterBuilder; import io.opentelemetry.exporter.internal.marshal.Marshaler; -import io.opentelemetry.exporter.internal.otlp.traces.LowAllocationTraceRequestMarshaler; -import io.opentelemetry.exporter.internal.otlp.traces.TraceRequestMarshaler; +import io.opentelemetry.exporter.internal.otlp.traces.SpanReusableDataMarshaler; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.trace.data.SpanData; import io.opentelemetry.sdk.trace.export.SpanExporter; -import java.util.ArrayDeque; import java.util.Collection; -import java.util.Deque; import java.util.StringJoiner; import javax.annotation.concurrent.ThreadSafe; @@ -28,10 +25,9 @@ @ThreadSafe public final class OtlpHttpSpanExporter implements SpanExporter { - private final Deque marshalerPool = new ArrayDeque<>(); private final HttpExporterBuilder builder; private final HttpExporter delegate; - private final MemoryMode memoryMode; + private final SpanReusableDataMarshaler marshaler; OtlpHttpSpanExporter( HttpExporterBuilder builder, @@ -39,7 +35,13 @@ public final class OtlpHttpSpanExporter implements SpanExporter { MemoryMode memoryMode) { this.builder = builder; this.delegate = delegate; - this.memoryMode = memoryMode; + this.marshaler = + new SpanReusableDataMarshaler(memoryMode) { + @Override + public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { + return delegate.export(exportRequest, numItems); + } + }; } /** @@ -71,7 +73,7 @@ public static OtlpHttpSpanExporterBuilder builder() { * @since 1.29.0 */ public OtlpHttpSpanExporterBuilder toBuilder() { - return new OtlpHttpSpanExporterBuilder(builder.copy(), memoryMode); + return new OtlpHttpSpanExporterBuilder(builder.copy(), marshaler.getMemoryMode()); } /** @@ -82,24 +84,7 @@ public OtlpHttpSpanExporterBuilder toBuilder() { */ @Override public CompletableResultCode export(Collection spans) { - if (memoryMode == MemoryMode.REUSABLE_DATA) { - LowAllocationTraceRequestMarshaler marshaler = marshalerPool.poll(); - if (marshaler == null) { - marshaler = new LowAllocationTraceRequestMarshaler(); - } - LowAllocationTraceRequestMarshaler exportMarshaler = marshaler; - exportMarshaler.initialize(spans); - return delegate - .export(exportMarshaler, spans.size()) - .whenComplete( - () -> { - exportMarshaler.reset(); - marshalerPool.add(exportMarshaler); - }); - } - // MemoryMode == MemoryMode.IMMUTABLE_DATA - TraceRequestMarshaler request = TraceRequestMarshaler.create(spans); - return delegate.export(request, spans.size()); + return marshaler.export(spans); } /** @@ -122,7 +107,7 @@ public CompletableResultCode shutdown() { public String toString() { StringJoiner joiner = new StringJoiner(", ", "OtlpHttpSpanExporter{", "}"); joiner.add(builder.toString(false)); - joiner.add("memoryMode=" + memoryMode); + joiner.add("memoryMode=" + marshaler.getMemoryMode()); return joiner.toString(); } } diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java index efde0010450..70e00f8fdd2 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java @@ -8,15 +8,12 @@ import io.opentelemetry.exporter.internal.grpc.GrpcExporter; import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder; import io.opentelemetry.exporter.internal.marshal.Marshaler; -import io.opentelemetry.exporter.internal.otlp.logs.LogsRequestMarshaler; -import io.opentelemetry.exporter.internal.otlp.logs.LowAllocationLogsRequestMarshaler; +import io.opentelemetry.exporter.internal.otlp.logs.LogReusableDataMarshaler; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.logs.export.LogRecordExporter; -import java.util.ArrayDeque; import java.util.Collection; -import java.util.Deque; import java.util.StringJoiner; import javax.annotation.concurrent.ThreadSafe; @@ -28,10 +25,9 @@ @ThreadSafe public final class OtlpGrpcLogRecordExporter implements LogRecordExporter { - private final Deque marshalerPool = new ArrayDeque<>(); private final GrpcExporterBuilder builder; private final GrpcExporter delegate; - private final MemoryMode memoryMode; + private final LogReusableDataMarshaler marshaler; /** * Returns a new {@link OtlpGrpcLogRecordExporter} using the default values. @@ -60,7 +56,13 @@ public static OtlpGrpcLogRecordExporterBuilder builder() { MemoryMode memoryMode) { this.builder = builder; this.delegate = delegate; - this.memoryMode = memoryMode; + this.marshaler = + new LogReusableDataMarshaler(memoryMode) { + @Override + public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { + return delegate.export(exportRequest, numItems); + } + }; } /** @@ -71,7 +73,7 @@ public static OtlpGrpcLogRecordExporterBuilder builder() { * @since 1.29.0 */ public OtlpGrpcLogRecordExporterBuilder toBuilder() { - return new OtlpGrpcLogRecordExporterBuilder(builder.copy(), memoryMode); + return new OtlpGrpcLogRecordExporterBuilder(builder.copy(), marshaler.getMemoryMode()); } /** @@ -82,24 +84,7 @@ public OtlpGrpcLogRecordExporterBuilder toBuilder() { */ @Override public CompletableResultCode export(Collection logs) { - if (memoryMode == MemoryMode.REUSABLE_DATA) { - LowAllocationLogsRequestMarshaler marshaler = marshalerPool.poll(); - if (marshaler == null) { - marshaler = new LowAllocationLogsRequestMarshaler(); - } - LowAllocationLogsRequestMarshaler exportMarshaler = marshaler; - exportMarshaler.initialize(logs); - return delegate - .export(exportMarshaler, logs.size()) - .whenComplete( - () -> { - exportMarshaler.reset(); - marshalerPool.add(exportMarshaler); - }); - } - // MemoryMode == MemoryMode.IMMUTABLE_DATA - LogsRequestMarshaler request = LogsRequestMarshaler.create(logs); - return delegate.export(request, logs.size()); + return marshaler.export(logs); } @Override @@ -120,7 +105,7 @@ public CompletableResultCode shutdown() { public String toString() { StringJoiner joiner = new StringJoiner(", ", "OtlpGrpcLogRecordExporter{", "}"); joiner.add(builder.toString(false)); - joiner.add("memoryMode=" + memoryMode); + joiner.add("memoryMode=" + marshaler.getMemoryMode()); return joiner.toString(); } } diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java index 1a9d3ed20e2..9be47837c45 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java @@ -8,8 +8,7 @@ import io.opentelemetry.exporter.internal.grpc.GrpcExporter; import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder; import io.opentelemetry.exporter.internal.marshal.Marshaler; -import io.opentelemetry.exporter.internal.otlp.metrics.LowAllocationMetricsRequestMarshaler; -import io.opentelemetry.exporter.internal.otlp.metrics.MetricsRequestMarshaler; +import io.opentelemetry.exporter.internal.otlp.metrics.MetricReusableDataMarshaler; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.metrics.Aggregation; @@ -19,9 +18,7 @@ import io.opentelemetry.sdk.metrics.export.AggregationTemporalitySelector; import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector; import io.opentelemetry.sdk.metrics.export.MetricExporter; -import java.util.ArrayDeque; import java.util.Collection; -import java.util.Deque; import java.util.StringJoiner; import javax.annotation.concurrent.ThreadSafe; @@ -33,12 +30,11 @@ @ThreadSafe public final class OtlpGrpcMetricExporter implements MetricExporter { - private final Deque marshalerPool = new ArrayDeque<>(); private final GrpcExporterBuilder builder; private final GrpcExporter delegate; private final AggregationTemporalitySelector aggregationTemporalitySelector; private final DefaultAggregationSelector defaultAggregationSelector; - private final MemoryMode memoryMode; + private final MetricReusableDataMarshaler marshaler; /** * Returns a new {@link OtlpGrpcMetricExporter} using the default values. @@ -71,7 +67,13 @@ public static OtlpGrpcMetricExporterBuilder builder() { this.delegate = delegate; this.aggregationTemporalitySelector = aggregationTemporalitySelector; this.defaultAggregationSelector = defaultAggregationSelector; - this.memoryMode = memoryMode; + this.marshaler = + new MetricReusableDataMarshaler(memoryMode) { + @Override + public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { + return delegate.export(exportRequest, numItems); + } + }; } /** @@ -82,7 +84,7 @@ public static OtlpGrpcMetricExporterBuilder builder() { * @since 1.29.0 */ public OtlpGrpcMetricExporterBuilder toBuilder() { - return new OtlpGrpcMetricExporterBuilder(builder.copy(), memoryMode); + return new OtlpGrpcMetricExporterBuilder(builder.copy(), marshaler.getMemoryMode()); } @Override @@ -97,7 +99,7 @@ public Aggregation getDefaultAggregation(InstrumentType instrumentType) { @Override public MemoryMode getMemoryMode() { - return memoryMode; + return marshaler.getMemoryMode(); } /** @@ -108,24 +110,7 @@ public MemoryMode getMemoryMode() { */ @Override public CompletableResultCode export(Collection metrics) { - if (memoryMode == MemoryMode.REUSABLE_DATA) { - LowAllocationMetricsRequestMarshaler marshaler = marshalerPool.poll(); - if (marshaler == null) { - marshaler = new LowAllocationMetricsRequestMarshaler(); - } - LowAllocationMetricsRequestMarshaler exportMarshaler = marshaler; - exportMarshaler.initialize(metrics); - return delegate - .export(exportMarshaler, metrics.size()) - .whenComplete( - () -> { - exportMarshaler.reset(); - marshalerPool.add(exportMarshaler); - }); - } - // MemoryMode == MemoryMode.IMMUTABLE_DATA - MetricsRequestMarshaler request = MetricsRequestMarshaler.create(metrics); - return delegate.export(request, metrics.size()); + return marshaler.export(metrics); } /** @@ -157,7 +142,7 @@ public String toString() { joiner.add( "defaultAggregationSelector=" + DefaultAggregationSelector.asString(defaultAggregationSelector)); - joiner.add("memoryMode=" + memoryMode); + joiner.add("memoryMode=" + marshaler.getMemoryMode()); return joiner.toString(); } } diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java index a2c29d87bc1..20df05bd742 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java @@ -8,15 +8,12 @@ import io.opentelemetry.exporter.internal.grpc.GrpcExporter; import io.opentelemetry.exporter.internal.grpc.GrpcExporterBuilder; import io.opentelemetry.exporter.internal.marshal.Marshaler; -import io.opentelemetry.exporter.internal.otlp.traces.LowAllocationTraceRequestMarshaler; -import io.opentelemetry.exporter.internal.otlp.traces.TraceRequestMarshaler; +import io.opentelemetry.exporter.internal.otlp.traces.SpanReusableDataMarshaler; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.export.MemoryMode; import io.opentelemetry.sdk.trace.data.SpanData; import io.opentelemetry.sdk.trace.export.SpanExporter; -import java.util.ArrayDeque; import java.util.Collection; -import java.util.Deque; import java.util.StringJoiner; import javax.annotation.concurrent.ThreadSafe; @@ -24,10 +21,9 @@ @ThreadSafe public final class OtlpGrpcSpanExporter implements SpanExporter { - private final Deque marshalerPool = new ArrayDeque<>(); private final GrpcExporterBuilder builder; private final GrpcExporter delegate; - private final MemoryMode memoryMode; + private final SpanReusableDataMarshaler marshaler; /** * Returns a new {@link OtlpGrpcSpanExporter} using the default values. @@ -56,7 +52,13 @@ public static OtlpGrpcSpanExporterBuilder builder() { MemoryMode memoryMode) { this.builder = builder; this.delegate = delegate; - this.memoryMode = memoryMode; + this.marshaler = + new SpanReusableDataMarshaler(memoryMode) { + @Override + public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { + return delegate.export(exportRequest, numItems); + } + }; } /** @@ -67,7 +69,7 @@ public static OtlpGrpcSpanExporterBuilder builder() { * @since 1.29.0 */ public OtlpGrpcSpanExporterBuilder toBuilder() { - return new OtlpGrpcSpanExporterBuilder(builder.copy(), memoryMode); + return new OtlpGrpcSpanExporterBuilder(builder.copy(), marshaler.getMemoryMode()); } /** @@ -78,24 +80,7 @@ public OtlpGrpcSpanExporterBuilder toBuilder() { */ @Override public CompletableResultCode export(Collection spans) { - if (memoryMode == MemoryMode.REUSABLE_DATA) { - LowAllocationTraceRequestMarshaler marshaler = marshalerPool.poll(); - if (marshaler == null) { - marshaler = new LowAllocationTraceRequestMarshaler(); - } - LowAllocationTraceRequestMarshaler exportMarshaler = marshaler; - exportMarshaler.initialize(spans); - return delegate - .export(exportMarshaler, spans.size()) - .whenComplete( - () -> { - exportMarshaler.reset(); - marshalerPool.add(exportMarshaler); - }); - } - // MemoryMode == MemoryMode.IMMUTABLE_DATA - TraceRequestMarshaler request = TraceRequestMarshaler.create(spans); - return delegate.export(request, spans.size()); + return marshaler.export(spans); } /** @@ -121,7 +106,7 @@ public CompletableResultCode shutdown() { public String toString() { StringJoiner joiner = new StringJoiner(", ", "OtlpGrpcSpanExporter{", "}"); joiner.add(builder.toString(false)); - joiner.add("memoryMode=" + memoryMode); + joiner.add("memoryMode=" + marshaler.getMemoryMode()); return joiner.toString(); } } diff --git a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java index 2f882b3ebfd..bab89d8a69a 100644 --- a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java +++ b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpLogRecordExporterProviderTest.java @@ -30,6 +30,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import org.assertj.core.api.AbstractObjectAssert; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -128,11 +129,15 @@ void createExporter_GrpcDefaults() { verify(grpcBuilder, never()).setTrustedCertificates(any()); verify(grpcBuilder, never()).setClientTls(any(), any()); assertThat(grpcBuilder).extracting("delegate").extracting("retryPolicy").isNotNull(); - assertThat(exporter).extracting("memoryMode").isEqualTo(MemoryMode.IMMUTABLE_DATA); + getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA); } Mockito.verifyNoInteractions(httpBuilder); } + private static AbstractObjectAssert getMemoryMode(LogRecordExporter exporter) { + return assertThat(exporter).extracting("marshaler").extracting("memoryMode"); + } + @Test void createExporter_GrpcWithGeneralConfiguration() throws CertificateEncodingException { Map config = new HashMap<>(); @@ -191,7 +196,7 @@ void createExporter_GrpcWithSignalConfiguration() throws CertificateEncodingExce verify(grpcBuilder).setTrustedCertificates(serverTls.certificate().getEncoded()); verify(grpcBuilder) .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded()); - assertThat(exporter).extracting("memoryMode").isEqualTo(MemoryMode.REUSABLE_DATA); + getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA); } Mockito.verifyNoInteractions(httpBuilder); } @@ -211,7 +216,7 @@ void createExporter_HttpDefaults() { verify(httpBuilder, never()).setTrustedCertificates(any()); verify(httpBuilder, never()).setClientTls(any(), any()); assertThat(httpBuilder).extracting("delegate").extracting("retryPolicy").isNotNull(); - assertThat(exporter).extracting("memoryMode").isEqualTo(MemoryMode.IMMUTABLE_DATA); + getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA); } Mockito.verifyNoInteractions(grpcBuilder); } @@ -277,7 +282,7 @@ void createExporter_HttpWithSignalConfiguration() throws CertificateEncodingExce verify(httpBuilder).setTrustedCertificates(serverTls.certificate().getEncoded()); verify(httpBuilder) .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded()); - assertThat(exporter).extracting("memoryMode").isEqualTo(MemoryMode.REUSABLE_DATA); + getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA); } Mockito.verifyNoInteractions(grpcBuilder); } diff --git a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java index 06d39054a0f..084826d47ff 100644 --- a/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java +++ b/exporters/otlp/all/src/test/java/io/opentelemetry/exporter/otlp/internal/OtlpSpanExporterProviderTest.java @@ -30,6 +30,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import org.assertj.core.api.AbstractObjectAssert; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -129,11 +130,15 @@ void createExporter_GrpcDefaults() { verify(grpcBuilder, never()).setTrustedCertificates(any()); verify(grpcBuilder, never()).setClientTls(any(), any()); assertThat(grpcBuilder).extracting("delegate").extracting("retryPolicy").isNotNull(); - assertThat(exporter).extracting("memoryMode").isEqualTo(MemoryMode.IMMUTABLE_DATA); + getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA); } Mockito.verifyNoInteractions(httpBuilder); } + private static AbstractObjectAssert getMemoryMode(SpanExporter exporter) { + return assertThat(exporter).extracting("marshaler").extracting("memoryMode"); + } + @Test void createExporter_GrpcWithGeneralConfiguration() throws CertificateEncodingException { Map config = new HashMap<>(); @@ -192,7 +197,7 @@ void createExporter_GrpcWithSignalConfiguration() throws CertificateEncodingExce verify(grpcBuilder).setTrustedCertificates(serverTls.certificate().getEncoded()); verify(grpcBuilder) .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded()); - assertThat(exporter).extracting("memoryMode").isEqualTo(MemoryMode.REUSABLE_DATA); + getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA); } Mockito.verifyNoInteractions(httpBuilder); } @@ -212,7 +217,7 @@ void createExporter_HttpDefaults() { verify(httpBuilder, never()).setTrustedCertificates(any()); verify(httpBuilder, never()).setClientTls(any(), any()); assertThat(httpBuilder).extracting("delegate").extracting("retryPolicy").isNotNull(); - assertThat(exporter).extracting("memoryMode").isEqualTo(MemoryMode.IMMUTABLE_DATA); + getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA); } Mockito.verifyNoInteractions(grpcBuilder); } @@ -244,7 +249,7 @@ void createExporter_HttpWithGeneralConfiguration() throws CertificateEncodingExc verify(httpBuilder) .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded()); assertThat(httpBuilder).extracting("delegate").extracting("retryPolicy").isNull(); - assertThat(exporter).extracting("memoryMode").isEqualTo(MemoryMode.IMMUTABLE_DATA); + getMemoryMode(exporter).isEqualTo(MemoryMode.IMMUTABLE_DATA); } Mockito.verifyNoInteractions(grpcBuilder); } @@ -281,7 +286,7 @@ void createExporter_HttpWithSignalConfiguration() throws CertificateEncodingExce verify(httpBuilder).setTrustedCertificates(serverTls.certificate().getEncoded()); verify(httpBuilder) .setClientTls(clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded()); - assertThat(exporter).extracting("memoryMode").isEqualTo(MemoryMode.REUSABLE_DATA); + getMemoryMode(exporter).isEqualTo(MemoryMode.REUSABLE_DATA); } Mockito.verifyNoInteractions(grpcBuilder); } diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java new file mode 100644 index 00000000000..307b0dc89f9 --- /dev/null +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java @@ -0,0 +1,51 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.internal.otlp.logs; + +import io.opentelemetry.exporter.internal.marshal.Marshaler; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.common.export.MemoryMode; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Deque; + +public abstract class LogReusableDataMarshaler { + + private final Deque marshalerPool = new ArrayDeque<>(); + + private final MemoryMode memoryMode; + + public LogReusableDataMarshaler(MemoryMode memoryMode) { + this.memoryMode = memoryMode; + } + + public MemoryMode getMemoryMode() { + return memoryMode; + } + + public abstract CompletableResultCode doExport(Marshaler exportRequest, int numItems); + + public CompletableResultCode export(Collection logs) { + if (memoryMode == MemoryMode.REUSABLE_DATA) { + LowAllocationLogsRequestMarshaler marshaler = marshalerPool.poll(); + if (marshaler == null) { + marshaler = new LowAllocationLogsRequestMarshaler(); + } + LowAllocationLogsRequestMarshaler exportMarshaler = marshaler; + exportMarshaler.initialize(logs); + return doExport(exportMarshaler, logs.size()) + .whenComplete( + () -> { + exportMarshaler.reset(); + marshalerPool.add(exportMarshaler); + }); + } + // MemoryMode == MemoryMode.IMMUTABLE_DATA + LogsRequestMarshaler request = LogsRequestMarshaler.create(logs); + return doExport(request, logs.size()); + } +} diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java new file mode 100644 index 00000000000..5f43ab3db32 --- /dev/null +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java @@ -0,0 +1,51 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.internal.otlp.metrics; + +import io.opentelemetry.exporter.internal.marshal.Marshaler; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.common.export.MemoryMode; +import io.opentelemetry.sdk.metrics.data.MetricData; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Deque; + +public abstract class MetricReusableDataMarshaler { + + private final Deque marshalerPool = new ArrayDeque<>(); + + private final MemoryMode memoryMode; + + public MetricReusableDataMarshaler(MemoryMode memoryMode) { + this.memoryMode = memoryMode; + } + + public MemoryMode getMemoryMode() { + return memoryMode; + } + + public abstract CompletableResultCode doExport(Marshaler exportRequest, int numItems); + + public CompletableResultCode export(Collection metrics) { + if (memoryMode == MemoryMode.REUSABLE_DATA) { + LowAllocationMetricsRequestMarshaler marshaler = marshalerPool.poll(); + if (marshaler == null) { + marshaler = new LowAllocationMetricsRequestMarshaler(); + } + LowAllocationMetricsRequestMarshaler exportMarshaler = marshaler; + exportMarshaler.initialize(metrics); + return doExport(exportMarshaler, metrics.size()) + .whenComplete( + () -> { + exportMarshaler.reset(); + marshalerPool.add(exportMarshaler); + }); + } + // MemoryMode == MemoryMode.IMMUTABLE_DATA + MetricsRequestMarshaler request = MetricsRequestMarshaler.create(metrics); + return doExport(request, metrics.size()); + } +} diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java new file mode 100644 index 00000000000..919fa515b0a --- /dev/null +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java @@ -0,0 +1,51 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.exporter.internal.otlp.traces; + +import io.opentelemetry.exporter.internal.marshal.Marshaler; +import io.opentelemetry.sdk.common.CompletableResultCode; +import io.opentelemetry.sdk.common.export.MemoryMode; +import io.opentelemetry.sdk.trace.data.SpanData; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Deque; + +public abstract class SpanReusableDataMarshaler { + + private final Deque marshalerPool = new ArrayDeque<>(); + + private final MemoryMode memoryMode; + + public SpanReusableDataMarshaler(MemoryMode memoryMode) { + this.memoryMode = memoryMode; + } + + public MemoryMode getMemoryMode() { + return memoryMode; + } + + public abstract CompletableResultCode doExport(Marshaler exportRequest, int numItems); + + public CompletableResultCode export(Collection spans) { + if (memoryMode == MemoryMode.REUSABLE_DATA) { + LowAllocationTraceRequestMarshaler marshaler = marshalerPool.poll(); + if (marshaler == null) { + marshaler = new LowAllocationTraceRequestMarshaler(); + } + LowAllocationTraceRequestMarshaler exportMarshaler = marshaler; + exportMarshaler.initialize(spans); + return doExport(exportMarshaler, spans.size()) + .whenComplete( + () -> { + exportMarshaler.reset(); + marshalerPool.add(exportMarshaler); + }); + } + // MemoryMode == MemoryMode.IMMUTABLE_DATA + TraceRequestMarshaler request = TraceRequestMarshaler.create(spans); + return doExport(request, spans.size()); + } +} From 9ce3fec6d73b2c78a47a6a8ef02068ad2519e3f7 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 16 Oct 2024 08:41:53 +0200 Subject: [PATCH 2/4] pr review --- .../OtlpStdoutExporterBuilderUtil.java | 19 ------------------- .../logs/OtlpStdoutLogRecordExporter.java | 10 +++------- .../OtlpStdoutLogRecordExporterBuilder.java | 6 ++++-- .../metrics/OtlpStdoutMetricExporter.java | 10 +++------- .../OtlpStdoutMetricExporterBuilder.java | 6 ++++-- .../traces/OtlpStdoutSpanExporter.java | 10 +++------- .../traces/OtlpStdoutSpanExporterBuilder.java | 6 ++++-- .../http/logs/OtlpHttpLogRecordExporter.java | 8 +------- .../http/metrics/OtlpHttpMetricExporter.java | 8 +------- .../otlp/http/trace/OtlpHttpSpanExporter.java | 8 +------- .../otlp/logs/OtlpGrpcLogRecordExporter.java | 8 +------- .../otlp/metrics/OtlpGrpcMetricExporter.java | 8 +------- .../otlp/trace/OtlpGrpcSpanExporter.java | 8 +------- .../otlp/logs/LogReusableDataMarshaler.java | 15 +++++++++------ .../metrics/MetricReusableDataMarshaler.java | 15 +++++++++------ .../traces/SpanReusableDataMarshaler.java | 15 +++++++++------ 16 files changed, 54 insertions(+), 106 deletions(-) delete mode 100644 exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/OtlpStdoutExporterBuilderUtil.java diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/OtlpStdoutExporterBuilderUtil.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/OtlpStdoutExporterBuilderUtil.java deleted file mode 100644 index 78079921c95..00000000000 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/OtlpStdoutExporterBuilderUtil.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.exporter.logging.otlp.internal; - -import io.opentelemetry.sdk.common.export.MemoryMode; - -public class OtlpStdoutExporterBuilderUtil { - public OtlpStdoutExporterBuilderUtil() {} - - public static void validate(MemoryMode memoryMode, boolean wrapperJsonObject) { - if (memoryMode == MemoryMode.REUSABLE_DATA && !wrapperJsonObject) { - throw new IllegalArgumentException( - "Reusable data mode is not supported without wrapperJsonObject"); - } - } -} diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java index 1b87143200c..986340d45e5 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java @@ -5,7 +5,6 @@ package io.opentelemetry.exporter.logging.otlp.internal.logs; -import io.opentelemetry.exporter.internal.marshal.Marshaler; import io.opentelemetry.exporter.internal.otlp.logs.LogReusableDataMarshaler; import io.opentelemetry.exporter.internal.otlp.logs.ResourceLogsMarshaler; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; @@ -58,12 +57,9 @@ public CompletableResultCode export(Collection logs) { } if (wrapperJsonObject) { - return new LogReusableDataMarshaler(memoryMode) { - @Override - public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { - return jsonWriter.write(exportRequest); - } - }.export(logs); + return new LogReusableDataMarshaler( + memoryMode, (marshaler, numItems) -> jsonWriter.write(marshaler)) + .export(logs); } else { for (ResourceLogsMarshaler resourceLogs : ResourceLogsMarshaler.create(logs)) { CompletableResultCode resultCode = jsonWriter.write(resourceLogs); diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterBuilder.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterBuilder.java index d05fcf88fa1..76e6adb20ad 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterBuilder.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterBuilder.java @@ -8,7 +8,6 @@ import static java.util.Objects.requireNonNull; import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingLogRecordExporter; -import io.opentelemetry.exporter.logging.otlp.internal.OtlpStdoutExporterBuilderUtil; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.LoggerJsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.StreamJsonWriter; @@ -85,7 +84,10 @@ public OtlpStdoutLogRecordExporterBuilder setOutput(Logger logger) { * @return a new exporter's instance */ public OtlpStdoutLogRecordExporter build() { - OtlpStdoutExporterBuilderUtil.validate(memoryMode, wrapperJsonObject); + if (memoryMode == MemoryMode.REUSABLE_DATA && !wrapperJsonObject) { + throw new IllegalArgumentException( + "Reusable data mode is not supported without wrapperJsonObject"); + } return new OtlpStdoutLogRecordExporter(logger, jsonWriter, wrapperJsonObject, memoryMode); } } diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java index fc900dd4261..4563ec08c16 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java @@ -5,7 +5,6 @@ package io.opentelemetry.exporter.logging.otlp.internal.metrics; -import io.opentelemetry.exporter.internal.marshal.Marshaler; import io.opentelemetry.exporter.internal.otlp.metrics.MetricReusableDataMarshaler; import io.opentelemetry.exporter.internal.otlp.metrics.ResourceMetricsMarshaler; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; @@ -86,12 +85,9 @@ public CompletableResultCode export(Collection metrics) { } if (wrapperJsonObject) { - return new MetricReusableDataMarshaler(memoryMode) { - @Override - public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { - return jsonWriter.write(exportRequest); - } - }.export(metrics); + return new MetricReusableDataMarshaler( + memoryMode, (marshaler, numItems) -> jsonWriter.write(marshaler)) + .export(metrics); } else { for (ResourceMetricsMarshaler resourceMetrics : ResourceMetricsMarshaler.create(metrics)) { CompletableResultCode resultCode = jsonWriter.write(resourceMetrics); diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterBuilder.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterBuilder.java index b4c235f1852..945ffd778bd 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterBuilder.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterBuilder.java @@ -8,7 +8,6 @@ import static java.util.Objects.requireNonNull; import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingMetricExporter; -import io.opentelemetry.exporter.logging.otlp.internal.OtlpStdoutExporterBuilderUtil; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.LoggerJsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.StreamJsonWriter; @@ -128,7 +127,10 @@ public OtlpStdoutMetricExporterBuilder setDefaultAggregationSelector( * @return a new exporter's instance */ public OtlpStdoutMetricExporter build() { - OtlpStdoutExporterBuilderUtil.validate(memoryMode, wrapperJsonObject); + if (memoryMode == MemoryMode.REUSABLE_DATA && !wrapperJsonObject) { + throw new IllegalArgumentException( + "Reusable data mode is not supported without wrapperJsonObject"); + } return new OtlpStdoutMetricExporter( logger, jsonWriter, diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java index cc1113a2a5d..5e95301ee0b 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java @@ -5,7 +5,6 @@ package io.opentelemetry.exporter.logging.otlp.internal.traces; -import io.opentelemetry.exporter.internal.marshal.Marshaler; import io.opentelemetry.exporter.internal.otlp.traces.ResourceSpansMarshaler; import io.opentelemetry.exporter.internal.otlp.traces.SpanReusableDataMarshaler; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; @@ -57,12 +56,9 @@ public CompletableResultCode export(Collection spans) { } if (wrapperJsonObject) { - return new SpanReusableDataMarshaler(memoryMode) { - @Override - public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { - return jsonWriter.write(exportRequest); - } - }.export(spans); + return new SpanReusableDataMarshaler( + memoryMode, (marshaler, numItems) -> jsonWriter.write(marshaler)) + .export(spans); } else { for (ResourceSpansMarshaler resourceSpans : ResourceSpansMarshaler.create(spans)) { CompletableResultCode resultCode = jsonWriter.write(resourceSpans); diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterBuilder.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterBuilder.java index 977c2935aa5..341f63c6e49 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterBuilder.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterBuilder.java @@ -8,7 +8,6 @@ import static java.util.Objects.requireNonNull; import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingSpanExporter; -import io.opentelemetry.exporter.logging.otlp.internal.OtlpStdoutExporterBuilderUtil; import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.LoggerJsonWriter; import io.opentelemetry.exporter.logging.otlp.internal.writer.StreamJsonWriter; @@ -85,7 +84,10 @@ public OtlpStdoutSpanExporterBuilder setOutput(Logger logger) { * @return a new exporter's instance */ public OtlpStdoutSpanExporter build() { - OtlpStdoutExporterBuilderUtil.validate(memoryMode, wrapperJsonObject); + if (memoryMode == MemoryMode.REUSABLE_DATA && !wrapperJsonObject) { + throw new IllegalArgumentException( + "Reusable data mode is not supported without wrapperJsonObject"); + } return new OtlpStdoutSpanExporter(logger, jsonWriter, wrapperJsonObject, memoryMode); } } diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java index ff79f86dea8..dcc8b4bcc7a 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/logs/OtlpHttpLogRecordExporter.java @@ -35,13 +35,7 @@ public final class OtlpHttpLogRecordExporter implements LogRecordExporter { MemoryMode memoryMode) { this.builder = builder; this.delegate = delegate; - this.marshaler = - new LogReusableDataMarshaler(memoryMode) { - @Override - public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { - return delegate.export(exportRequest, numItems); - } - }; + this.marshaler = new LogReusableDataMarshaler(memoryMode, delegate::export); } /** diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java index 5206c2ed615..87d7b4c7a10 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/metrics/OtlpHttpMetricExporter.java @@ -46,13 +46,7 @@ public final class OtlpHttpMetricExporter implements MetricExporter { this.delegate = delegate; this.aggregationTemporalitySelector = aggregationTemporalitySelector; this.defaultAggregationSelector = defaultAggregationSelector; - this.marshaler = - new MetricReusableDataMarshaler(memoryMode) { - @Override - public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { - return delegate.export(exportRequest, numItems); - } - }; + this.marshaler = new MetricReusableDataMarshaler(memoryMode, delegate::export); } /** diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java index 8123eb4299c..71870e12b54 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/http/trace/OtlpHttpSpanExporter.java @@ -35,13 +35,7 @@ public final class OtlpHttpSpanExporter implements SpanExporter { MemoryMode memoryMode) { this.builder = builder; this.delegate = delegate; - this.marshaler = - new SpanReusableDataMarshaler(memoryMode) { - @Override - public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { - return delegate.export(exportRequest, numItems); - } - }; + this.marshaler = new SpanReusableDataMarshaler(memoryMode, delegate::export); } /** diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java index 70e00f8fdd2..e85cb76b78f 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/logs/OtlpGrpcLogRecordExporter.java @@ -56,13 +56,7 @@ public static OtlpGrpcLogRecordExporterBuilder builder() { MemoryMode memoryMode) { this.builder = builder; this.delegate = delegate; - this.marshaler = - new LogReusableDataMarshaler(memoryMode) { - @Override - public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { - return delegate.export(exportRequest, numItems); - } - }; + this.marshaler = new LogReusableDataMarshaler(memoryMode, delegate::export); } /** diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java index 9be47837c45..5dd48db4908 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/metrics/OtlpGrpcMetricExporter.java @@ -67,13 +67,7 @@ public static OtlpGrpcMetricExporterBuilder builder() { this.delegate = delegate; this.aggregationTemporalitySelector = aggregationTemporalitySelector; this.defaultAggregationSelector = defaultAggregationSelector; - this.marshaler = - new MetricReusableDataMarshaler(memoryMode) { - @Override - public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { - return delegate.export(exportRequest, numItems); - } - }; + this.marshaler = new MetricReusableDataMarshaler(memoryMode, delegate::export); } /** diff --git a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java index 20df05bd742..6d0d3d2fffa 100644 --- a/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java +++ b/exporters/otlp/all/src/main/java/io/opentelemetry/exporter/otlp/trace/OtlpGrpcSpanExporter.java @@ -52,13 +52,7 @@ public static OtlpGrpcSpanExporterBuilder builder() { MemoryMode memoryMode) { this.builder = builder; this.delegate = delegate; - this.marshaler = - new SpanReusableDataMarshaler(memoryMode) { - @Override - public CompletableResultCode doExport(Marshaler exportRequest, int numItems) { - return delegate.export(exportRequest, numItems); - } - }; + this.marshaler = new SpanReusableDataMarshaler(memoryMode, delegate::export); } /** diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java index 307b0dc89f9..9ce03ddafef 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java @@ -12,23 +12,25 @@ import java.util.ArrayDeque; import java.util.Collection; import java.util.Deque; +import java.util.function.BiFunction; -public abstract class LogReusableDataMarshaler { +public class LogReusableDataMarshaler { private final Deque marshalerPool = new ArrayDeque<>(); private final MemoryMode memoryMode; + private final BiFunction doExport; - public LogReusableDataMarshaler(MemoryMode memoryMode) { + public LogReusableDataMarshaler( + MemoryMode memoryMode, BiFunction doExport) { this.memoryMode = memoryMode; + this.doExport = doExport; } public MemoryMode getMemoryMode() { return memoryMode; } - public abstract CompletableResultCode doExport(Marshaler exportRequest, int numItems); - public CompletableResultCode export(Collection logs) { if (memoryMode == MemoryMode.REUSABLE_DATA) { LowAllocationLogsRequestMarshaler marshaler = marshalerPool.poll(); @@ -37,7 +39,8 @@ public CompletableResultCode export(Collection logs) { } LowAllocationLogsRequestMarshaler exportMarshaler = marshaler; exportMarshaler.initialize(logs); - return doExport(exportMarshaler, logs.size()) + return doExport + .apply(exportMarshaler, logs.size()) .whenComplete( () -> { exportMarshaler.reset(); @@ -46,6 +49,6 @@ public CompletableResultCode export(Collection logs) { } // MemoryMode == MemoryMode.IMMUTABLE_DATA LogsRequestMarshaler request = LogsRequestMarshaler.create(logs); - return doExport(request, logs.size()); + return doExport.apply(request, logs.size()); } } diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java index 5f43ab3db32..fb9fb8d2fa8 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java @@ -12,23 +12,25 @@ import java.util.ArrayDeque; import java.util.Collection; import java.util.Deque; +import java.util.function.BiFunction; -public abstract class MetricReusableDataMarshaler { +public class MetricReusableDataMarshaler { private final Deque marshalerPool = new ArrayDeque<>(); private final MemoryMode memoryMode; + private final BiFunction doExport; - public MetricReusableDataMarshaler(MemoryMode memoryMode) { + public MetricReusableDataMarshaler( + MemoryMode memoryMode, BiFunction doExport) { this.memoryMode = memoryMode; + this.doExport = doExport; } public MemoryMode getMemoryMode() { return memoryMode; } - public abstract CompletableResultCode doExport(Marshaler exportRequest, int numItems); - public CompletableResultCode export(Collection metrics) { if (memoryMode == MemoryMode.REUSABLE_DATA) { LowAllocationMetricsRequestMarshaler marshaler = marshalerPool.poll(); @@ -37,7 +39,8 @@ public CompletableResultCode export(Collection metrics) { } LowAllocationMetricsRequestMarshaler exportMarshaler = marshaler; exportMarshaler.initialize(metrics); - return doExport(exportMarshaler, metrics.size()) + return doExport + .apply(exportMarshaler, metrics.size()) .whenComplete( () -> { exportMarshaler.reset(); @@ -46,6 +49,6 @@ public CompletableResultCode export(Collection metrics) { } // MemoryMode == MemoryMode.IMMUTABLE_DATA MetricsRequestMarshaler request = MetricsRequestMarshaler.create(metrics); - return doExport(request, metrics.size()); + return doExport.apply(request, metrics.size()); } } diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java index 919fa515b0a..9cc2a617b2e 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java @@ -12,23 +12,25 @@ import java.util.ArrayDeque; import java.util.Collection; import java.util.Deque; +import java.util.function.BiFunction; -public abstract class SpanReusableDataMarshaler { +public class SpanReusableDataMarshaler { private final Deque marshalerPool = new ArrayDeque<>(); private final MemoryMode memoryMode; + private final BiFunction doExport; - public SpanReusableDataMarshaler(MemoryMode memoryMode) { + public SpanReusableDataMarshaler( + MemoryMode memoryMode, BiFunction doExport) { this.memoryMode = memoryMode; + this.doExport = doExport; } public MemoryMode getMemoryMode() { return memoryMode; } - public abstract CompletableResultCode doExport(Marshaler exportRequest, int numItems); - public CompletableResultCode export(Collection spans) { if (memoryMode == MemoryMode.REUSABLE_DATA) { LowAllocationTraceRequestMarshaler marshaler = marshalerPool.poll(); @@ -37,7 +39,8 @@ public CompletableResultCode export(Collection spans) { } LowAllocationTraceRequestMarshaler exportMarshaler = marshaler; exportMarshaler.initialize(spans); - return doExport(exportMarshaler, spans.size()) + return doExport + .apply(exportMarshaler, spans.size()) .whenComplete( () -> { exportMarshaler.reset(); @@ -46,6 +49,6 @@ public CompletableResultCode export(Collection spans) { } // MemoryMode == MemoryMode.IMMUTABLE_DATA TraceRequestMarshaler request = TraceRequestMarshaler.create(spans); - return doExport(request, spans.size()); + return doExport.apply(request, spans.size()); } } From cfabe230f7330c03932b6c281cf26dd62d680d3c Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 16 Oct 2024 12:05:21 +0200 Subject: [PATCH 3/4] pr review --- .../logs/OtlpStdoutLogRecordExporter.java | 40 ++++++++++++------- .../metrics/OtlpStdoutMetricExporter.java | 40 ++++++++++++------- .../traces/OtlpStdoutSpanExporter.java | 40 ++++++++++++------- 3 files changed, 78 insertions(+), 42 deletions(-) diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java index 986340d45e5..11798e938f0 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java @@ -15,6 +15,7 @@ import java.util.Collection; import java.util.StringJoiner; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; @@ -35,6 +36,7 @@ public final class OtlpStdoutLogRecordExporter implements LogRecordExporter { private final JsonWriter jsonWriter; private final boolean wrapperJsonObject; private final MemoryMode memoryMode; + private final Function, CompletableResultCode> marshaler; OtlpStdoutLogRecordExporter( Logger logger, JsonWriter jsonWriter, boolean wrapperJsonObject, MemoryMode memoryMode) { @@ -42,6 +44,7 @@ public final class OtlpStdoutLogRecordExporter implements LogRecordExporter { this.jsonWriter = jsonWriter; this.wrapperJsonObject = wrapperJsonObject; this.memoryMode = memoryMode; + marshaler = createMarshaler(jsonWriter, memoryMode, wrapperJsonObject); } /** Returns a new {@link OtlpStdoutLogRecordExporterBuilder}. */ @@ -50,26 +53,35 @@ public static OtlpStdoutLogRecordExporterBuilder builder() { return new OtlpStdoutLogRecordExporterBuilder(LOGGER).setOutput(System.out); } + private static Function, CompletableResultCode> createMarshaler( + JsonWriter jsonWriter, MemoryMode memoryMode, boolean wrapperJsonObject) { + if (wrapperJsonObject) { + LogReusableDataMarshaler reusableDataMarshaler = + new LogReusableDataMarshaler( + memoryMode, (marshaler, numItems) -> jsonWriter.write(marshaler)); + return reusableDataMarshaler::export; + } else { + return logs -> { + // no support for low allocation marshaler + for (ResourceLogsMarshaler marshaler : ResourceLogsMarshaler.create(logs)) { + CompletableResultCode resultCode = jsonWriter.write(marshaler); + if (!resultCode.isSuccess()) { + // already logged + return resultCode; + } + } + return CompletableResultCode.ofSuccess(); + }; + } + } + @Override public CompletableResultCode export(Collection logs) { if (isShutdown.get()) { return CompletableResultCode.ofFailure(); } - if (wrapperJsonObject) { - return new LogReusableDataMarshaler( - memoryMode, (marshaler, numItems) -> jsonWriter.write(marshaler)) - .export(logs); - } else { - for (ResourceLogsMarshaler resourceLogs : ResourceLogsMarshaler.create(logs)) { - CompletableResultCode resultCode = jsonWriter.write(resourceLogs); - if (!resultCode.isSuccess()) { - // already logged - return resultCode; - } - } - return CompletableResultCode.ofSuccess(); - } + return marshaler.apply(logs); } @Override diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java index 4563ec08c16..4294c1d2571 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporter.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.StringJoiner; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; @@ -39,6 +40,7 @@ public final class OtlpStdoutMetricExporter implements MetricExporter { private final JsonWriter jsonWriter; private final boolean wrapperJsonObject; private final MemoryMode memoryMode; + private final Function, CompletableResultCode> marshaler; private final AggregationTemporalitySelector aggregationTemporalitySelector; private final DefaultAggregationSelector defaultAggregationSelector; @@ -55,6 +57,7 @@ public final class OtlpStdoutMetricExporter implements MetricExporter { this.memoryMode = memoryMode; this.aggregationTemporalitySelector = aggregationTemporalitySelector; this.defaultAggregationSelector = defaultAggregationSelector; + marshaler = createMarshaler(jsonWriter, memoryMode, wrapperJsonObject); } /** Returns a new {@link OtlpStdoutMetricExporterBuilder}. */ @@ -63,6 +66,28 @@ public static OtlpStdoutMetricExporterBuilder builder() { return new OtlpStdoutMetricExporterBuilder(LOGGER).setOutput(System.out); } + private static Function, CompletableResultCode> createMarshaler( + JsonWriter jsonWriter, MemoryMode memoryMode, boolean wrapperJsonObject) { + if (wrapperJsonObject) { + MetricReusableDataMarshaler reusableDataMarshaler = + new MetricReusableDataMarshaler( + memoryMode, (marshaler, numItems) -> jsonWriter.write(marshaler)); + return reusableDataMarshaler::export; + } else { + return metrics -> { + // no support for low allocation marshaler + for (ResourceMetricsMarshaler marshaler : ResourceMetricsMarshaler.create(metrics)) { + CompletableResultCode resultCode = jsonWriter.write(marshaler); + if (!resultCode.isSuccess()) { + // already logged + return resultCode; + } + } + return CompletableResultCode.ofSuccess(); + }; + } + } + @Override public AggregationTemporality getAggregationTemporality(InstrumentType instrumentType) { return aggregationTemporalitySelector.getAggregationTemporality(instrumentType); @@ -84,20 +109,7 @@ public CompletableResultCode export(Collection metrics) { return CompletableResultCode.ofFailure(); } - if (wrapperJsonObject) { - return new MetricReusableDataMarshaler( - memoryMode, (marshaler, numItems) -> jsonWriter.write(marshaler)) - .export(metrics); - } else { - for (ResourceMetricsMarshaler resourceMetrics : ResourceMetricsMarshaler.create(metrics)) { - CompletableResultCode resultCode = jsonWriter.write(resourceMetrics); - if (!resultCode.isSuccess()) { - // already logged - return resultCode; - } - } - return CompletableResultCode.ofSuccess(); - } + return marshaler.apply(metrics); } @Override diff --git a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java index 5e95301ee0b..187cdacc245 100644 --- a/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java +++ b/exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporter.java @@ -15,6 +15,7 @@ import java.util.Collection; import java.util.StringJoiner; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; @@ -34,6 +35,7 @@ public final class OtlpStdoutSpanExporter implements SpanExporter { private final JsonWriter jsonWriter; private final boolean wrapperJsonObject; private final MemoryMode memoryMode; + private final Function, CompletableResultCode> marshaler; OtlpStdoutSpanExporter( Logger logger, JsonWriter jsonWriter, boolean wrapperJsonObject, MemoryMode memoryMode) { @@ -41,6 +43,7 @@ public final class OtlpStdoutSpanExporter implements SpanExporter { this.jsonWriter = jsonWriter; this.wrapperJsonObject = wrapperJsonObject; this.memoryMode = memoryMode; + marshaler = createMarshaler(jsonWriter, memoryMode, wrapperJsonObject); } /** Returns a new {@link OtlpStdoutSpanExporterBuilder}. */ @@ -49,26 +52,35 @@ public static OtlpStdoutSpanExporterBuilder builder() { return new OtlpStdoutSpanExporterBuilder(LOGGER).setOutput(System.out); } + private static Function, CompletableResultCode> createMarshaler( + JsonWriter jsonWriter, MemoryMode memoryMode, boolean wrapperJsonObject) { + if (wrapperJsonObject) { + SpanReusableDataMarshaler reusableDataMarshaler = + new SpanReusableDataMarshaler( + memoryMode, (marshaler, numItems) -> jsonWriter.write(marshaler)); + return reusableDataMarshaler::export; + } else { + return spans -> { + // no support for low allocation marshaler + for (ResourceSpansMarshaler marshaler : ResourceSpansMarshaler.create(spans)) { + CompletableResultCode resultCode = jsonWriter.write(marshaler); + if (!resultCode.isSuccess()) { + // already logged + return resultCode; + } + } + return CompletableResultCode.ofSuccess(); + }; + } + } + @Override public CompletableResultCode export(Collection spans) { if (isShutdown.get()) { return CompletableResultCode.ofFailure(); } - if (wrapperJsonObject) { - return new SpanReusableDataMarshaler( - memoryMode, (marshaler, numItems) -> jsonWriter.write(marshaler)) - .export(spans); - } else { - for (ResourceSpansMarshaler resourceSpans : ResourceSpansMarshaler.create(spans)) { - CompletableResultCode resultCode = jsonWriter.write(resourceSpans); - if (!resultCode.isSuccess()) { - // already logged - return resultCode; - } - } - return CompletableResultCode.ofSuccess(); - } + return marshaler.apply(spans); } @Override From bb62e71f71702f69c6852af91cbc589f19568359 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 17 Oct 2024 17:11:31 +0200 Subject: [PATCH 4/4] internal class note --- .../exporter/internal/otlp/logs/LogReusableDataMarshaler.java | 4 ++++ .../internal/otlp/metrics/MetricReusableDataMarshaler.java | 4 ++++ .../internal/otlp/traces/SpanReusableDataMarshaler.java | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java index 9ce03ddafef..5f3fc50a5f5 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/logs/LogReusableDataMarshaler.java @@ -14,6 +14,10 @@ import java.util.Deque; import java.util.function.BiFunction; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ public class LogReusableDataMarshaler { private final Deque marshalerPool = new ArrayDeque<>(); diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java index fb9fb8d2fa8..c143e94fa5d 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/metrics/MetricReusableDataMarshaler.java @@ -14,6 +14,10 @@ import java.util.Deque; import java.util.function.BiFunction; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ public class MetricReusableDataMarshaler { private final Deque marshalerPool = new ArrayDeque<>(); diff --git a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java index 9cc2a617b2e..af69e811c89 100644 --- a/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java +++ b/exporters/otlp/common/src/main/java/io/opentelemetry/exporter/internal/otlp/traces/SpanReusableDataMarshaler.java @@ -14,6 +14,10 @@ import java.util.Deque; import java.util.function.BiFunction; +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ public class SpanReusableDataMarshaler { private final Deque marshalerPool = new ArrayDeque<>();