org.apache.rocketmq.shaded.io.opentelemetry.sdk.logs.export.SimpleLogProcessor Maven / Gradle / Ivy
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package org.apache.rocketmq.shaded.io.opentelemetry.sdk.logs.export;
import static java.util.Objects.requireNonNull;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.common.CompletableResultCode;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.logs.LogProcessor;
import org.apache.rocketmq.shaded.io.opentelemetry.sdk.logs.data.LogData;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* An implementation of the {@link LogProcessor} that passes {@link LogData} directly to the
* configured exporter.
*
* This processor will cause all logs to be exported directly as they finish, meaning each export
* request will have a single log. Most backends will not perform well with a single log per request
* so unless you know what you're doing, strongly consider using {@link BatchLogProcessor} instead,
* including in special environments such as serverless runtimes. {@link SimpleLogProcessor} is
* generally meant to for testing only.
*/
public final class SimpleLogProcessor implements LogProcessor {
private static final Logger logger = Logger.getLogger(SimpleLogProcessor.class.getName());
private final LogExporter logExporter;
private final Set pendingExports =
Collections.newSetFromMap(new ConcurrentHashMap<>());
private final AtomicBoolean isShutdown = new AtomicBoolean(false);
/**
* Returns a new {@link SimpleLogProcessor} which exports logs to the {@link LogExporter}
* synchronously.
*
* This processor will cause all logs to be exported directly as they finish, meaning each
* export request will have a single log. Most backends will not perform well with a single log
* per request so unless you know what you're doing, strongly consider using {@link
* BatchLogProcessor} instead, including in special environments such as serverless runtimes.
* {@link SimpleLogProcessor} is generally meant to for testing only.
*/
public static LogProcessor create(LogExporter exporter) {
requireNonNull(exporter, "exporter");
return new SimpleLogProcessor(exporter);
}
SimpleLogProcessor(LogExporter logExporter) {
this.logExporter = requireNonNull(logExporter, "logExporter");
}
@Override
public void emit(LogData logData) {
try {
List logs = Collections.singletonList(logData);
CompletableResultCode result = logExporter.export(logs);
pendingExports.add(result);
result.whenComplete(
() -> {
pendingExports.remove(result);
if (!result.isSuccess()) {
logger.log(Level.FINE, "Exporter failed");
}
});
} catch (RuntimeException e) {
logger.log(Level.WARNING, "Exporter threw an Exception", e);
}
}
@Override
public CompletableResultCode shutdown() {
if (isShutdown.getAndSet(true)) {
return CompletableResultCode.ofSuccess();
}
CompletableResultCode result = new CompletableResultCode();
CompletableResultCode flushResult = forceFlush();
flushResult.whenComplete(
() -> {
CompletableResultCode shutdownResult = logExporter.shutdown();
shutdownResult.whenComplete(
() -> {
if (!flushResult.isSuccess() || !shutdownResult.isSuccess()) {
result.fail();
} else {
result.succeed();
}
});
});
return result;
}
@Override
public CompletableResultCode forceFlush() {
return CompletableResultCode.ofAll(pendingExports);
}
}