Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OTLP Stdout exporter #6632

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
Comparing source compatibility of opentelemetry-exporter-logging-otlp-1.42.0-SNAPSHOT.jar against opentelemetry-exporter-logging-otlp-1.41.0.jar
No changes.
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingLogRecordExporter (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) java.lang.String toString()
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingMetricExporter (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.metrics.Aggregation getDefaultAggregation(io.opentelemetry.sdk.metrics.InstrumentType)
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.export.MemoryMode getMemoryMode()
+++ NEW METHOD: PUBLIC(+) java.lang.String toString()
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingSpanExporter (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) java.lang.String toString()
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
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;
import io.opentelemetry.sdk.metrics.export.AggregationTemporalitySelector;
import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector;
import io.opentelemetry.sdk.metrics.internal.aggregator.AggregationUtil;
import java.net.URI;
Expand Down Expand Up @@ -97,4 +99,94 @@
}

private ExporterBuilderUtil() {}

/**
* Invoke the {@code aggregationTemporalitySelectorConsumer} with the configured {@link
* AggregationTemporality}.
*/
public static void configureOtlpAggregationTemporality(
ConfigProperties config,
Consumer<AggregationTemporalitySelector> aggregationTemporalitySelectorConsumer) {
String temporalityStr = config.getString("otel.exporter.otlp.metrics.temporality.preference");
if (temporalityStr == null) {
return;
}
AggregationTemporalitySelector temporalitySelector;
switch (temporalityStr.toLowerCase(Locale.ROOT)) {
case "cumulative":
temporalitySelector = AggregationTemporalitySelector.alwaysCumulative();
break;
case "delta":
temporalitySelector = AggregationTemporalitySelector.deltaPreferred();
break;
case "lowmemory":
temporalitySelector = AggregationTemporalitySelector.lowMemory();
break;

Check warning on line 124 in exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java

View check run for this annotation

Codecov / codecov/patch

exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java#L123-L124

Added lines #L123 - L124 were not covered by tests
default:
throw new ConfigurationException("Unrecognized aggregation temporality: " + temporalityStr);
}
aggregationTemporalitySelectorConsumer.accept(temporalitySelector);
}

public static void configureOtlpAggregationTemporality(
StructuredConfigProperties config,
Consumer<AggregationTemporalitySelector> aggregationTemporalitySelectorConsumer) {
String temporalityStr = config.getString("temporality_preference");
if (temporalityStr == null) {
return;
}
AggregationTemporalitySelector temporalitySelector;
switch (temporalityStr.toLowerCase(Locale.ROOT)) {
case "cumulative":
temporalitySelector = AggregationTemporalitySelector.alwaysCumulative();
break;

Check warning on line 142 in exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java

View check run for this annotation

Codecov / codecov/patch

exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java#L141-L142

Added lines #L141 - L142 were not covered by tests
case "delta":
temporalitySelector = AggregationTemporalitySelector.deltaPreferred();
break;
case "lowmemory":
temporalitySelector = AggregationTemporalitySelector.lowMemory();
break;

Check warning on line 148 in exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java

View check run for this annotation

Codecov / codecov/patch

exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java#L147-L148

Added lines #L147 - L148 were not covered by tests
default:
throw new ConfigurationException("Unrecognized temporality_preference: " + temporalityStr);

Check warning on line 150 in exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java

View check run for this annotation

Codecov / codecov/patch

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

Added line #L150 was not covered by tests
}
aggregationTemporalitySelectorConsumer.accept(temporalitySelector);
}

/**
* Invoke the {@code defaultAggregationSelectorConsumer} with the configured {@link
* DefaultAggregationSelector}.
*/
public static void configureOtlpHistogramDefaultAggregation(
ConfigProperties config,
Consumer<DefaultAggregationSelector> defaultAggregationSelectorConsumer) {
String defaultHistogramAggregation =
config.getString("otel.exporter.otlp.metrics.default.histogram.aggregation");
if (defaultHistogramAggregation != null) {
configureHistogramDefaultAggregation(
defaultHistogramAggregation, defaultAggregationSelectorConsumer);
}
}

/**
* Invoke the {@code defaultAggregationSelectorConsumer} with the configured {@link
* DefaultAggregationSelector}.
*/
public static void configureOtlpHistogramDefaultAggregation(
StructuredConfigProperties config,
Consumer<DefaultAggregationSelector> defaultAggregationSelectorConsumer) {
String defaultHistogramAggregation = config.getString("default_histogram_aggregation");
if (defaultHistogramAggregation == null) {
return;
}
if (AggregationUtil.aggregationName(Aggregation.base2ExponentialBucketHistogram())
.equalsIgnoreCase(defaultHistogramAggregation)) {
defaultAggregationSelectorConsumer.accept(
DefaultAggregationSelector.getDefault()
.with(InstrumentType.HISTOGRAM, Aggregation.base2ExponentialBucketHistogram()));
} else if (!AggregationUtil.aggregationName(explicitBucketHistogram())

Check warning on line 186 in exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java

View check run for this annotation

Codecov / codecov/patch

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

Added line #L186 was not covered by tests
.equalsIgnoreCase(defaultHistogramAggregation)) {
throw new ConfigurationException(

Check warning on line 188 in exporters/common/src/main/java/io/opentelemetry/exporter/internal/ExporterBuilderUtil.java

View check run for this annotation

Codecov / codecov/patch

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

Added line #L188 was not covered by tests
"Unrecognized default_histogram_aggregation: " + defaultHistogramAggregation);
}
}
}
1 change: 1 addition & 0 deletions exporters/logging-otlp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ dependencies {

testImplementation(project(":sdk:testing"))

testImplementation("com.google.guava:guava")
testImplementation("org.skyscreamer:jsonassert")
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@

package io.opentelemetry.exporter.logging.otlp;

import static io.opentelemetry.exporter.logging.otlp.JsonUtil.JSON_FACTORY;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.io.SegmentedStringWriter;
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.InternalBuilder;
import io.opentelemetry.exporter.logging.otlp.internal.logs.LogRecordBuilderAccessUtil;
import io.opentelemetry.exporter.logging.otlp.internal.logs.OtlpJsonLoggingLogRecordExporterBuilder;
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.io.IOException;
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;

Expand All @@ -32,40 +36,80 @@

private final AtomicBoolean isShutdown = new AtomicBoolean();

private final JsonWriter jsonWriter;

private final Function<Collection<LogRecordData>, CompletableResultCode> marshaler;
private final MemoryMode memoryMode;
private final boolean wrapperJsonObject;

static {
LogRecordBuilderAccessUtil.setToExporter(
builder ->
new OtlpJsonLoggingLogRecordExporter(
builder.getJsonWriter(), builder.getMemoryMode(), builder.isWrapperJsonObject()));
LogRecordBuilderAccessUtil.setToBuilder(
exporter ->
InternalBuilder.forLogs()
.setJsonWriter(exporter.jsonWriter)
.setWrapperJsonObject(exporter.wrapperJsonObject)
.setMemoryMode(exporter.memoryMode));
}

/** Returns a new {@link OtlpJsonLoggingLogRecordExporter}. */
public static LogRecordExporter create() {
return new OtlpJsonLoggingLogRecordExporter();
return OtlpJsonLoggingLogRecordExporterBuilder.create().build();
}

private OtlpJsonLoggingLogRecordExporter() {}
OtlpJsonLoggingLogRecordExporter(
JsonWriter jsonWriter, MemoryMode memoryMode, boolean wrapperJsonObject) {
this.memoryMode = memoryMode;
this.wrapperJsonObject = wrapperJsonObject;
this.jsonWriter = jsonWriter;

marshaler = createMarshaler(jsonWriter, memoryMode, wrapperJsonObject);
}

private static Function<Collection<LogRecordData>, CompletableResultCode> createMarshaler(
JsonWriter jsonWriter, MemoryMode memoryMode, boolean wrapperJsonObject) {

if (wrapperJsonObject) {
LogReusableDataMarshaler reusableDataMarshaler =
new LogReusableDataMarshaler(memoryMode) {
@Override
public CompletableResultCode doExport(Marshaler exportRequest, int numItems) {
return jsonWriter.write(exportRequest);
}
};

return reusableDataMarshaler::export;
} else {
return logs -> {
// not support for low allocation marshaler

for (ResourceLogsMarshaler resourceLogs : ResourceLogsMarshaler.create(logs)) {
CompletableResultCode resultCode = jsonWriter.write(resourceLogs);
if (!resultCode.isSuccess()) {
// already logged
return resultCode;

Check warning on line 93 in exporters/logging-otlp/src/main/java/io/opentelemetry/exporter/logging/otlp/OtlpJsonLoggingLogRecordExporter.java

View check run for this annotation

Codecov / codecov/patch

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

Added line #L93 was not covered by tests
}
}
return CompletableResultCode.ofSuccess();
};
}
}

@Override
public CompletableResultCode export(Collection<LogRecordData> logs) {
if (isShutdown.get()) {
return CompletableResultCode.ofFailure();
}

ResourceLogsMarshaler[] allResourceLogs = ResourceLogsMarshaler.create(logs);
for (ResourceLogsMarshaler resourceLogs : allResourceLogs) {
SegmentedStringWriter sw = new SegmentedStringWriter(JSON_FACTORY._getBufferRecycler());
try (JsonGenerator gen = JsonUtil.create(sw)) {
resourceLogs.writeJsonTo(gen);
} catch (IOException e) {
// Shouldn't happen in practice, just skip it.
continue;
}
try {
logger.log(Level.INFO, sw.getAndClear());
} catch (IOException e) {
logger.log(Level.WARNING, "Unable to read OTLP JSON log records", e);
}
}
return CompletableResultCode.ofSuccess();
return marshaler.apply(logs);
}

@Override
public CompletableResultCode flush() {
return CompletableResultCode.ofSuccess();
return jsonWriter.flush();
}

@Override
Expand All @@ -75,4 +119,13 @@
}
return CompletableResultCode.ofSuccess();
}

@Override
public String toString() {
StringJoiner joiner = new StringJoiner(", ", "OtlpJsonLoggingLogRecordExporter{", "}");
joiner.add("memoryMode=" + memoryMode);
joiner.add("wrapperJsonObject=" + wrapperJsonObject);
joiner.add("jsonWriter=" + jsonWriter);
return joiner.toString();
}
}
Loading
Loading