Skip to content

Commit 56aa059

Browse files
Add JSON pretty-print support to logging-otlp exporters
Closes #5972
1 parent 3ea5e08 commit 56aa059

11 files changed

Lines changed: 99 additions & 20 deletions

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ public final class OtlpJsonLoggingLogRecordExporter implements LogRecordExporter
2929
/** Returns a new {@link OtlpJsonLoggingLogRecordExporter}. */
3030
public static LogRecordExporter create() {
3131
OtlpStdoutLogRecordExporter delegate =
32-
new OtlpStdoutLogRecordExporterBuilder(logger).setWrapperJsonObject(false).build();
32+
new OtlpStdoutLogRecordExporterBuilder(logger)
33+
.setWrapperJsonObject(false)
34+
.setPrettyPrint(true)
35+
.build();
3336
return new OtlpJsonLoggingLogRecordExporter(delegate);
3437
}
3538

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ public static MetricExporter create() {
4242
*/
4343
public static MetricExporter create(AggregationTemporality aggregationTemporality) {
4444
OtlpStdoutMetricExporter delegate =
45-
new OtlpStdoutMetricExporterBuilder(logger).setWrapperJsonObject(false).build();
45+
new OtlpStdoutMetricExporterBuilder(logger)
46+
.setWrapperJsonObject(false)
47+
.setPrettyPrint(true)
48+
.build();
4649
return new OtlpJsonLoggingMetricExporter(delegate, aggregationTemporality);
4750
}
4851

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ public final class OtlpJsonLoggingSpanExporter implements SpanExporter {
2727
/** Returns a new {@link OtlpJsonLoggingSpanExporter}. */
2828
public static SpanExporter create() {
2929
OtlpStdoutSpanExporter delegate =
30-
new OtlpStdoutSpanExporterBuilder(logger).setWrapperJsonObject(false).build();
30+
new OtlpStdoutSpanExporterBuilder(logger)
31+
.setWrapperJsonObject(false)
32+
.setPrettyPrint(true)
33+
.build();
3134
return new OtlpJsonLoggingSpanExporter(delegate);
3235
}
3336

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import io.opentelemetry.sdk.common.export.MemoryMode;
1515
import java.io.OutputStream;
1616
import java.util.logging.Logger;
17+
import javax.annotation.Nullable;
1718

1819
/**
1920
* Builder for {@link OtlpJsonLoggingLogRecordExporter}.
@@ -26,13 +27,14 @@ public final class OtlpStdoutLogRecordExporterBuilder {
2627
private static final String TYPE = "log records";
2728

2829
private final Logger logger;
29-
private JsonWriter jsonWriter;
30+
@Nullable private OutputStream outputStream;
31+
@Nullable private Logger outputLogger;
3032
private boolean wrapperJsonObject = true;
3133
private MemoryMode memoryMode = MemoryMode.IMMUTABLE_DATA;
34+
private boolean prettyPrint;
3235

3336
public OtlpStdoutLogRecordExporterBuilder(Logger logger) {
3437
this.logger = logger;
35-
this.jsonWriter = new LoggerJsonWriter(logger, TYPE);
3638
}
3739

3840
/**
@@ -57,6 +59,12 @@ public OtlpStdoutLogRecordExporterBuilder setMemoryMode(MemoryMode memoryMode) {
5759
return this;
5860
}
5961

62+
/** Sets the exporter to use pretty-printed JSON output. */
63+
public OtlpStdoutLogRecordExporterBuilder setPrettyPrint(boolean prettyPrint) {
64+
this.prettyPrint = prettyPrint;
65+
return this;
66+
}
67+
6068
/**
6169
* Sets the exporter to use the specified output stream.
6270
*
@@ -67,14 +75,16 @@ public OtlpStdoutLogRecordExporterBuilder setMemoryMode(MemoryMode memoryMode) {
6775
*/
6876
public OtlpStdoutLogRecordExporterBuilder setOutput(OutputStream outputStream) {
6977
requireNonNull(outputStream, "outputStream");
70-
this.jsonWriter = new StreamJsonWriter(outputStream, TYPE);
78+
this.outputStream = outputStream;
79+
this.outputLogger = null;
7180
return this;
7281
}
7382

7483
/** Sets the exporter to use the specified logger. */
7584
public OtlpStdoutLogRecordExporterBuilder setOutput(Logger logger) {
7685
requireNonNull(logger, "logger");
77-
this.jsonWriter = new LoggerJsonWriter(logger, TYPE);
86+
this.outputLogger = logger;
87+
this.outputStream = null;
7888
return this;
7989
}
8090

@@ -88,6 +98,13 @@ public OtlpStdoutLogRecordExporter build() {
8898
throw new IllegalArgumentException(
8999
"Reusable data mode is not supported without wrapperJsonObject");
90100
}
101+
JsonWriter jsonWriter;
102+
if (outputStream != null) {
103+
jsonWriter = new StreamJsonWriter(outputStream, TYPE, prettyPrint);
104+
} else {
105+
Logger writerLogger = outputLogger != null ? outputLogger : this.logger;
106+
jsonWriter = new LoggerJsonWriter(writerLogger, TYPE, prettyPrint);
107+
}
91108
return new OtlpStdoutLogRecordExporter(logger, jsonWriter, wrapperJsonObject, memoryMode);
92109
}
93110
}

exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/metrics/OtlpStdoutMetricExporterBuilder.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import io.opentelemetry.sdk.metrics.export.MetricExporter;
1919
import java.io.OutputStream;
2020
import java.util.logging.Logger;
21+
import javax.annotation.Nullable;
2122

2223
/**
2324
* Builder for {@link OtlpJsonLoggingMetricExporter}.
@@ -39,13 +40,14 @@ public final class OtlpStdoutMetricExporterBuilder {
3940
DefaultAggregationSelector.getDefault();
4041

4142
private final Logger logger;
42-
private JsonWriter jsonWriter;
43+
@Nullable private OutputStream outputStream;
44+
@Nullable private Logger outputLogger;
4345
private boolean wrapperJsonObject = true;
4446
private MemoryMode memoryMode = MemoryMode.IMMUTABLE_DATA;
47+
private boolean prettyPrint;
4548

4649
public OtlpStdoutMetricExporterBuilder(Logger logger) {
4750
this.logger = logger;
48-
this.jsonWriter = new LoggerJsonWriter(logger, TYPE);
4951
}
5052

5153
/**
@@ -70,6 +72,12 @@ public OtlpStdoutMetricExporterBuilder setMemoryMode(MemoryMode memoryMode) {
7072
return this;
7173
}
7274

75+
/** Sets the exporter to use pretty-printed JSON output. */
76+
public OtlpStdoutMetricExporterBuilder setPrettyPrint(boolean prettyPrint) {
77+
this.prettyPrint = prettyPrint;
78+
return this;
79+
}
80+
7381
/**
7482
* Sets the exporter to use the specified output stream.
7583
*
@@ -80,14 +88,16 @@ public OtlpStdoutMetricExporterBuilder setMemoryMode(MemoryMode memoryMode) {
8088
*/
8189
public OtlpStdoutMetricExporterBuilder setOutput(OutputStream outputStream) {
8290
requireNonNull(outputStream, "outputStream");
83-
this.jsonWriter = new StreamJsonWriter(outputStream, TYPE);
91+
this.outputStream = outputStream;
92+
this.outputLogger = null;
8493
return this;
8594
}
8695

8796
/** Sets the exporter to use the specified logger. */
8897
public OtlpStdoutMetricExporterBuilder setOutput(Logger logger) {
8998
requireNonNull(logger, "logger");
90-
this.jsonWriter = new LoggerJsonWriter(logger, TYPE);
99+
this.outputLogger = logger;
100+
this.outputStream = null;
91101
return this;
92102
}
93103

@@ -131,6 +141,13 @@ public OtlpStdoutMetricExporter build() {
131141
throw new IllegalArgumentException(
132142
"Reusable data mode is not supported without wrapperJsonObject");
133143
}
144+
JsonWriter jsonWriter;
145+
if (outputStream != null) {
146+
jsonWriter = new StreamJsonWriter(outputStream, TYPE, prettyPrint);
147+
} else {
148+
Logger writerLogger = outputLogger != null ? outputLogger : this.logger;
149+
jsonWriter = new LoggerJsonWriter(writerLogger, TYPE, prettyPrint);
150+
}
134151
return new OtlpStdoutMetricExporter(
135152
logger,
136153
jsonWriter,

exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/traces/OtlpStdoutSpanExporterBuilder.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import io.opentelemetry.sdk.common.export.MemoryMode;
1515
import java.io.OutputStream;
1616
import java.util.logging.Logger;
17+
import javax.annotation.Nullable;
1718

1819
/**
1920
* Builder for {@link OtlpJsonLoggingSpanExporter}.
@@ -26,13 +27,14 @@ public final class OtlpStdoutSpanExporterBuilder {
2627
private static final String TYPE = "spans";
2728

2829
private final Logger logger;
29-
private JsonWriter jsonWriter;
30+
@Nullable private OutputStream outputStream;
31+
@Nullable private Logger outputLogger;
3032
private boolean wrapperJsonObject = true;
3133
private MemoryMode memoryMode = MemoryMode.IMMUTABLE_DATA;
34+
private boolean prettyPrint;
3235

3336
public OtlpStdoutSpanExporterBuilder(Logger logger) {
3437
this.logger = logger;
35-
this.jsonWriter = new LoggerJsonWriter(logger, TYPE);
3638
}
3739

3840
/**
@@ -57,6 +59,12 @@ public OtlpStdoutSpanExporterBuilder setMemoryMode(MemoryMode memoryMode) {
5759
return this;
5860
}
5961

62+
/** Sets the exporter to use pretty-printed JSON output. */
63+
public OtlpStdoutSpanExporterBuilder setPrettyPrint(boolean prettyPrint) {
64+
this.prettyPrint = prettyPrint;
65+
return this;
66+
}
67+
6068
/**
6169
* Sets the exporter to use the specified output stream.
6270
*
@@ -67,14 +75,16 @@ public OtlpStdoutSpanExporterBuilder setMemoryMode(MemoryMode memoryMode) {
6775
*/
6876
public OtlpStdoutSpanExporterBuilder setOutput(OutputStream outputStream) {
6977
requireNonNull(outputStream, "outputStream");
70-
this.jsonWriter = new StreamJsonWriter(outputStream, TYPE);
78+
this.outputStream = outputStream;
79+
this.outputLogger = null;
7180
return this;
7281
}
7382

7483
/** Sets the exporter to use the specified logger. */
7584
public OtlpStdoutSpanExporterBuilder setOutput(Logger logger) {
7685
requireNonNull(logger, "logger");
77-
this.jsonWriter = new LoggerJsonWriter(logger, TYPE);
86+
this.outputLogger = logger;
87+
this.outputStream = null;
7888
return this;
7989
}
8090

@@ -88,6 +98,13 @@ public OtlpStdoutSpanExporter build() {
8898
throw new IllegalArgumentException(
8999
"Reusable data mode is not supported without wrapperJsonObject");
90100
}
101+
JsonWriter jsonWriter;
102+
if (outputStream != null) {
103+
jsonWriter = new StreamJsonWriter(outputStream, TYPE, prettyPrint);
104+
} else {
105+
Logger writerLogger = outputLogger != null ? outputLogger : this.logger;
106+
jsonWriter = new LoggerJsonWriter(writerLogger, TYPE, prettyPrint);
107+
}
91108
return new OtlpStdoutSpanExporter(logger, jsonWriter, wrapperJsonObject, memoryMode);
92109
}
93110
}

exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/writer/LoggerJsonWriter.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,25 @@ public class LoggerJsonWriter implements JsonWriter {
2323

2424
private final Logger logger;
2525
private final String type;
26+
private final boolean prettyPrint;
2627

2728
public LoggerJsonWriter(Logger logger, String type) {
29+
this(logger, type, /* prettyPrint= */ false);
30+
}
31+
32+
public LoggerJsonWriter(Logger logger, String type, boolean prettyPrint) {
2833
this.logger = logger;
2934
this.type = type;
35+
this.prettyPrint = prettyPrint;
3036
}
3137

3238
@Override
3339
public CompletableResultCode write(Marshaler exportRequest) {
3440
SegmentedStringWriter sw = new SegmentedStringWriter(JSON_FACTORY._getBufferRecycler());
3541
try (JsonGenerator gen = JsonUtil.create(sw)) {
42+
if (prettyPrint) {
43+
gen.useDefaultPrettyPrinter();
44+
}
3645
exportRequest.writeJsonToGenerator(gen);
3746
} catch (IOException e) {
3847
logger.log(Level.WARNING, "Unable to write OTLP JSON " + type, e);

exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/internal/writer/StreamJsonWriter.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,29 @@ public class StreamJsonWriter implements JsonWriter {
2929

3030
private final String type;
3131
private final OutputStream outputStream;
32+
private final boolean prettyPrint;
3233

3334
public StreamJsonWriter(OutputStream originalStream, String type) {
35+
this(originalStream, type, /* prettyPrint= */ false);
36+
}
37+
38+
public StreamJsonWriter(OutputStream originalStream, String type, boolean prettyPrint) {
3439
this.outputStream = originalStream;
3540
this.type = type;
41+
this.prettyPrint = prettyPrint;
3642
}
3743

3844
@Override
3945
public CompletableResultCode write(Marshaler exportRequest) {
4046
try {
41-
exportRequest.writeJsonWithNewline(
47+
JsonGenerator generator =
4248
JSON_FACTORY
4349
.createGenerator(outputStream)
44-
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET));
50+
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
51+
if (prettyPrint) {
52+
generator.useDefaultPrettyPrinter();
53+
}
54+
exportRequest.writeJsonWithNewline(generator);
4555
return CompletableResultCode.ofSuccess();
4656
} catch (IOException e) {
4757
logger.log(Level.WARNING, "Unable to write OTLP JSON " + type, e);

exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogRecordExporterTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void log() throws Exception {
4242
String message = logs.getEvents().get(0).getMessage();
4343
String expectedJson = testDataExporter.getExpectedJson(false);
4444
JSONAssert.assertEquals("Got \n" + message, expectedJson, message, /* strict= */ false);
45-
assertThat(message).doesNotContain("\n");
45+
assertThat(message).contains("\n");
4646
}
4747

4848
@Test

exporters/logging-otlp/src/test/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingMetricExporterTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ void log() throws Exception {
5757
String message = logs.getEvents().get(0).getMessage();
5858
String expectedJson = testDataExporter.getExpectedJson(false);
5959
JSONAssert.assertEquals("Got \n" + message, expectedJson, message, /* strict= */ false);
60-
assertThat(message).doesNotContain("\n");
60+
assertThat(message).contains("\n");
6161
}
6262

6363
@Test

0 commit comments

Comments
 (0)