Skip to content

Commit b927d9d

Browse files
authored
Stdout exporter for span and metrics (#6750)
1 parent eb53fe3 commit b927d9d

File tree

35 files changed

+1704
-720
lines changed

35 files changed

+1704
-720
lines changed

exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import io.opentelemetry.sdk.common.export.MemoryMode;
1414
import io.opentelemetry.sdk.metrics.Aggregation;
1515
import io.opentelemetry.sdk.metrics.InstrumentType;
16+
import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
17+
import io.opentelemetry.sdk.metrics.export.AggregationTemporalitySelector;
1618
import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector;
1719
import io.opentelemetry.sdk.metrics.internal.aggregator.AggregationUtil;
1820
import java.net.URI;
@@ -96,5 +98,95 @@ public static void configureHistogramDefaultAggregation(
9698
}
9799
}
98100

101+
/**
102+
* Invoke the {@code aggregationTemporalitySelectorConsumer} with the configured {@link
103+
* AggregationTemporality}.
104+
*/
105+
public static void configureOtlpAggregationTemporality(
106+
ConfigProperties config,
107+
Consumer<AggregationTemporalitySelector> aggregationTemporalitySelectorConsumer) {
108+
String temporalityStr = config.getString("otel.exporter.otlp.metrics.temporality.preference");
109+
if (temporalityStr == null) {
110+
return;
111+
}
112+
AggregationTemporalitySelector temporalitySelector;
113+
switch (temporalityStr.toLowerCase(Locale.ROOT)) {
114+
case "cumulative":
115+
temporalitySelector = AggregationTemporalitySelector.alwaysCumulative();
116+
break;
117+
case "delta":
118+
temporalitySelector = AggregationTemporalitySelector.deltaPreferred();
119+
break;
120+
case "lowmemory":
121+
temporalitySelector = AggregationTemporalitySelector.lowMemory();
122+
break;
123+
default:
124+
throw new ConfigurationException("Unrecognized aggregation temporality: " + temporalityStr);
125+
}
126+
aggregationTemporalitySelectorConsumer.accept(temporalitySelector);
127+
}
128+
129+
public static void configureOtlpAggregationTemporality(
130+
StructuredConfigProperties config,
131+
Consumer<AggregationTemporalitySelector> aggregationTemporalitySelectorConsumer) {
132+
String temporalityStr = config.getString("temporality_preference");
133+
if (temporalityStr == null) {
134+
return;
135+
}
136+
AggregationTemporalitySelector temporalitySelector;
137+
switch (temporalityStr.toLowerCase(Locale.ROOT)) {
138+
case "cumulative":
139+
temporalitySelector = AggregationTemporalitySelector.alwaysCumulative();
140+
break;
141+
case "delta":
142+
temporalitySelector = AggregationTemporalitySelector.deltaPreferred();
143+
break;
144+
case "lowmemory":
145+
temporalitySelector = AggregationTemporalitySelector.lowMemory();
146+
break;
147+
default:
148+
throw new ConfigurationException("Unrecognized temporality_preference: " + temporalityStr);
149+
}
150+
aggregationTemporalitySelectorConsumer.accept(temporalitySelector);
151+
}
152+
153+
/**
154+
* Invoke the {@code defaultAggregationSelectorConsumer} with the configured {@link
155+
* DefaultAggregationSelector}.
156+
*/
157+
public static void configureOtlpHistogramDefaultAggregation(
158+
ConfigProperties config,
159+
Consumer<DefaultAggregationSelector> defaultAggregationSelectorConsumer) {
160+
String defaultHistogramAggregation =
161+
config.getString("otel.exporter.otlp.metrics.default.histogram.aggregation");
162+
if (defaultHistogramAggregation != null) {
163+
configureHistogramDefaultAggregation(
164+
defaultHistogramAggregation, defaultAggregationSelectorConsumer);
165+
}
166+
}
167+
168+
/**
169+
* Invoke the {@code defaultAggregationSelectorConsumer} with the configured {@link
170+
* DefaultAggregationSelector}.
171+
*/
172+
public static void configureOtlpHistogramDefaultAggregation(
173+
StructuredConfigProperties config,
174+
Consumer<DefaultAggregationSelector> defaultAggregationSelectorConsumer) {
175+
String defaultHistogramAggregation = config.getString("default_histogram_aggregation");
176+
if (defaultHistogramAggregation == null) {
177+
return;
178+
}
179+
if (AggregationUtil.aggregationName(Aggregation.base2ExponentialBucketHistogram())
180+
.equalsIgnoreCase(defaultHistogramAggregation)) {
181+
defaultAggregationSelectorConsumer.accept(
182+
DefaultAggregationSelector.getDefault()
183+
.with(InstrumentType.HISTOGRAM, Aggregation.base2ExponentialBucketHistogram()));
184+
} else if (!AggregationUtil.aggregationName(explicitBucketHistogram())
185+
.equalsIgnoreCase(defaultHistogramAggregation)) {
186+
throw new ConfigurationException(
187+
"Unrecognized default_histogram_aggregation: " + defaultHistogramAggregation);
188+
}
189+
}
190+
99191
private ExporterBuilderUtil() {}
100192
}

exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingMetricExporter.java

Lines changed: 26 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,14 @@
55

66
package io.opentelemetry.exporter.logging.otlp;
77

8-
import static io.opentelemetry.exporter.logging.otlp.internal.writer.JsonUtil.JSON_FACTORY;
9-
10-
import com.fasterxml.jackson.core.JsonGenerator;
11-
import com.fasterxml.jackson.core.io.SegmentedStringWriter;
12-
import io.opentelemetry.exporter.internal.otlp.metrics.ResourceMetricsMarshaler;
13-
import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonUtil;
8+
import io.opentelemetry.exporter.logging.otlp.internal.metrics.OtlpStdoutMetricExporter;
9+
import io.opentelemetry.exporter.logging.otlp.internal.metrics.OtlpStdoutMetricExporterBuilder;
1410
import io.opentelemetry.sdk.common.CompletableResultCode;
1511
import io.opentelemetry.sdk.metrics.InstrumentType;
1612
import io.opentelemetry.sdk.metrics.data.AggregationTemporality;
1713
import io.opentelemetry.sdk.metrics.data.MetricData;
1814
import io.opentelemetry.sdk.metrics.export.MetricExporter;
19-
import java.io.IOException;
2015
import java.util.Collection;
21-
import java.util.concurrent.atomic.AtomicBoolean;
22-
import java.util.logging.Level;
2316
import java.util.logging.Logger;
2417

2518
/**
@@ -31,30 +24,49 @@ public final class OtlpJsonLoggingMetricExporter implements MetricExporter {
3124
private static final Logger logger =
3225
Logger.getLogger(OtlpJsonLoggingMetricExporter.class.getName());
3326

34-
private final AtomicBoolean isShutdown = new AtomicBoolean();
35-
3627
private final AggregationTemporality aggregationTemporality;
3728

29+
private final OtlpStdoutMetricExporter delegate;
30+
3831
/**
3932
* Returns a new {@link OtlpJsonLoggingMetricExporter} with a aggregation temporality of {@link
4033
* AggregationTemporality#CUMULATIVE}.
4134
*/
4235
public static MetricExporter create() {
43-
return new OtlpJsonLoggingMetricExporter(AggregationTemporality.CUMULATIVE);
36+
return create(AggregationTemporality.CUMULATIVE);
4437
}
4538

4639
/**
4740
* Returns a new {@link OtlpJsonLoggingMetricExporter} with the given {@code
4841
* aggregationTemporality}.
4942
*/
5043
public static MetricExporter create(AggregationTemporality aggregationTemporality) {
51-
return new OtlpJsonLoggingMetricExporter(aggregationTemporality);
44+
OtlpStdoutMetricExporter delegate =
45+
new OtlpStdoutMetricExporterBuilder(logger).setWrapperJsonObject(false).build();
46+
return new OtlpJsonLoggingMetricExporter(delegate, aggregationTemporality);
5247
}
5348

54-
private OtlpJsonLoggingMetricExporter(AggregationTemporality aggregationTemporality) {
49+
OtlpJsonLoggingMetricExporter(
50+
OtlpStdoutMetricExporter delegate, AggregationTemporality aggregationTemporality) {
51+
this.delegate = delegate;
5552
this.aggregationTemporality = aggregationTemporality;
5653
}
5754

55+
@Override
56+
public CompletableResultCode export(Collection<MetricData> logs) {
57+
return delegate.export(logs);
58+
}
59+
60+
@Override
61+
public CompletableResultCode flush() {
62+
return delegate.flush();
63+
}
64+
65+
@Override
66+
public CompletableResultCode shutdown() {
67+
return delegate.shutdown();
68+
}
69+
5870
/**
5971
* Return the aggregation temporality.
6072
*
@@ -69,41 +81,4 @@ public AggregationTemporality getPreferredTemporality() {
6981
public AggregationTemporality getAggregationTemporality(InstrumentType instrumentType) {
7082
return aggregationTemporality;
7183
}
72-
73-
@Override
74-
public CompletableResultCode export(Collection<MetricData> metrics) {
75-
if (isShutdown.get()) {
76-
return CompletableResultCode.ofFailure();
77-
}
78-
79-
ResourceMetricsMarshaler[] allResourceMetrics = ResourceMetricsMarshaler.create(metrics);
80-
for (ResourceMetricsMarshaler resourceMetrics : allResourceMetrics) {
81-
SegmentedStringWriter sw = new SegmentedStringWriter(JSON_FACTORY._getBufferRecycler());
82-
try (JsonGenerator gen = JsonUtil.create(sw)) {
83-
resourceMetrics.writeJsonTo(gen);
84-
} catch (IOException e) {
85-
// Shouldn't happen in practice, just skip it.
86-
continue;
87-
}
88-
try {
89-
logger.log(Level.INFO, sw.getAndClear());
90-
} catch (IOException e) {
91-
logger.log(Level.WARNING, "Unable to read OTLP JSON metrics", e);
92-
}
93-
}
94-
return CompletableResultCode.ofSuccess();
95-
}
96-
97-
@Override
98-
public CompletableResultCode flush() {
99-
return CompletableResultCode.ofSuccess();
100-
}
101-
102-
@Override
103-
public CompletableResultCode shutdown() {
104-
if (!isShutdown.compareAndSet(false, true)) {
105-
logger.log(Level.INFO, "Calling shutdown() multiple times.");
106-
}
107-
return CompletableResultCode.ofSuccess();
108-
}
10984
}

exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingSpanExporter.java

Lines changed: 13 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,12 @@
55

66
package io.opentelemetry.exporter.logging.otlp;
77

8-
import static io.opentelemetry.exporter.logging.otlp.internal.writer.JsonUtil.JSON_FACTORY;
9-
10-
import com.fasterxml.jackson.core.JsonGenerator;
11-
import com.fasterxml.jackson.core.io.SegmentedStringWriter;
12-
import io.opentelemetry.exporter.internal.otlp.traces.ResourceSpansMarshaler;
13-
import io.opentelemetry.exporter.logging.otlp.internal.writer.JsonUtil;
8+
import io.opentelemetry.exporter.logging.otlp.internal.traces.OtlpStdoutSpanExporter;
9+
import io.opentelemetry.exporter.logging.otlp.internal.traces.OtlpStdoutSpanExporterBuilder;
1410
import io.opentelemetry.sdk.common.CompletableResultCode;
1511
import io.opentelemetry.sdk.trace.data.SpanData;
1612
import io.opentelemetry.sdk.trace.export.SpanExporter;
17-
import java.io.IOException;
1813
import java.util.Collection;
19-
import java.util.concurrent.atomic.AtomicBoolean;
20-
import java.util.logging.Level;
2114
import java.util.logging.Logger;
2215

2316
/**
@@ -29,49 +22,31 @@ public final class OtlpJsonLoggingSpanExporter implements SpanExporter {
2922
private static final Logger logger =
3023
Logger.getLogger(OtlpJsonLoggingSpanExporter.class.getName());
3124

32-
private final AtomicBoolean isShutdown = new AtomicBoolean();
25+
private final OtlpStdoutSpanExporter delegate;
3326

3427
/** Returns a new {@link OtlpJsonLoggingSpanExporter}. */
3528
public static SpanExporter create() {
36-
return new OtlpJsonLoggingSpanExporter();
29+
OtlpStdoutSpanExporter delegate =
30+
new OtlpStdoutSpanExporterBuilder(logger).setWrapperJsonObject(false).build();
31+
return new OtlpJsonLoggingSpanExporter(delegate);
3732
}
3833

39-
private OtlpJsonLoggingSpanExporter() {}
34+
OtlpJsonLoggingSpanExporter(OtlpStdoutSpanExporter delegate) {
35+
this.delegate = delegate;
36+
}
4037

4138
@Override
42-
public CompletableResultCode export(Collection<SpanData> spans) {
43-
if (isShutdown.get()) {
44-
return CompletableResultCode.ofFailure();
45-
}
46-
47-
ResourceSpansMarshaler[] allResourceSpans = ResourceSpansMarshaler.create(spans);
48-
for (ResourceSpansMarshaler resourceSpans : allResourceSpans) {
49-
SegmentedStringWriter sw = new SegmentedStringWriter(JSON_FACTORY._getBufferRecycler());
50-
try (JsonGenerator gen = JsonUtil.create(sw)) {
51-
resourceSpans.writeJsonTo(gen);
52-
} catch (IOException e) {
53-
// Shouldn't happen in practice, just skip it.
54-
continue;
55-
}
56-
try {
57-
logger.log(Level.INFO, sw.getAndClear());
58-
} catch (IOException e) {
59-
logger.log(Level.WARNING, "Unable to read OTLP JSON spans", e);
60-
}
61-
}
62-
return CompletableResultCode.ofSuccess();
39+
public CompletableResultCode export(Collection<SpanData> logs) {
40+
return delegate.export(logs);
6341
}
6442

6543
@Override
6644
public CompletableResultCode flush() {
67-
return CompletableResultCode.ofSuccess();
45+
return delegate.flush();
6846
}
6947

7048
@Override
7149
public CompletableResultCode shutdown() {
72-
if (!isShutdown.compareAndSet(false, true)) {
73-
logger.log(Level.INFO, "Calling shutdown() multiple times.");
74-
}
75-
return CompletableResultCode.ofSuccess();
50+
return delegate.shutdown();
7651
}
7752
}

exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/LoggingLogRecordExporterProvider.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
1717
* at any time.
1818
*/
19-
public class LoggingLogRecordExporterProvider implements ConfigurableLogRecordExporterProvider {
19+
public final class LoggingLogRecordExporterProvider
20+
implements ConfigurableLogRecordExporterProvider {
2021

2122
@Override
2223
public LogRecordExporter createExporter(ConfigProperties config) {

exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
2424
* at any time.
2525
*/
26-
public class OtlpStdoutLogRecordExporter implements LogRecordExporter {
26+
public final class OtlpStdoutLogRecordExporter implements LogRecordExporter {
2727

2828
private static final Logger LOGGER =
2929
Logger.getLogger(OtlpStdoutLogRecordExporter.class.getName());

exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterComponentProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
1616
* at any time.
1717
*/
18-
public class OtlpStdoutLogRecordExporterComponentProvider
18+
public final class OtlpStdoutLogRecordExporterComponentProvider
1919
implements ComponentProvider<LogRecordExporter> {
2020

2121
@Override

exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/logs/OtlpStdoutLogRecordExporterProvider.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
1616
* at any time.
1717
*/
18-
public class OtlpStdoutLogRecordExporterProvider implements ConfigurableLogRecordExporterProvider {
18+
public final class OtlpStdoutLogRecordExporterProvider
19+
implements ConfigurableLogRecordExporterProvider {
1920
@Override
2021
public LogRecordExporter createExporter(ConfigProperties config) {
2122
OtlpStdoutLogRecordExporterBuilder builder = OtlpStdoutLogRecordExporter.builder();
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
package io.opentelemetry.exporter.logging.otlp.internal;
6+
package io.opentelemetry.exporter.logging.otlp.internal.metrics;
77

88
import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingMetricExporter;
99
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
@@ -16,7 +16,8 @@
1616
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
1717
* at any time.
1818
*/
19-
public class LoggingMetricExporterProvider implements ConfigurableMetricExporterProvider {
19+
public final class LoggingMetricExporterProvider implements ConfigurableMetricExporterProvider {
20+
2021
@Override
2122
public MetricExporter createExporter(ConfigProperties config) {
2223
return OtlpJsonLoggingMetricExporter.create();

0 commit comments

Comments
 (0)