From a960f73a1894dd035bacf11130fd5f9acb93f476 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Thu, 9 Jun 2022 12:35:00 +0200 Subject: [PATCH] Switch thin logger to synchronous in order to support native images --- .../argeo/init/logging/ThinLoggerFinder.java | 3 +- .../org/argeo/init/logging/ThinLogging.java | 61 +++++++++++++------ 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/org.argeo.init/src/org/argeo/init/logging/ThinLoggerFinder.java b/org.argeo.init/src/org/argeo/init/logging/ThinLoggerFinder.java index f443b2e66..47cb14655 100644 --- a/org.argeo.init/src/org/argeo/init/logging/ThinLoggerFinder.java +++ b/org.argeo.init/src/org/argeo/init/logging/ThinLoggerFinder.java @@ -21,11 +21,12 @@ public class ThinLoggerFinder extends LoggerFinder { public ThinLoggerFinder() { if (logging != null) throw new IllegalStateException("Only one logging can be initialised."); - init(); +// init(); } @Override public Logger getLogger(String name, Module module) { + lazyInit(); return logging.getLogger(name, module); } diff --git a/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java b/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java index e21899394..05fdfef1a 100644 --- a/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java +++ b/org.argeo.init/src/org/argeo/init/logging/ThinLogging.java @@ -16,11 +16,9 @@ import java.util.ResourceBundle; import java.util.SortedMap; import java.util.StringTokenizer; import java.util.TreeMap; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.Flow; import java.util.concurrent.Flow.Subscription; +import java.util.concurrent.ForkJoinPool; import java.util.concurrent.SubmissionPublisher; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; @@ -51,24 +49,33 @@ class ThinLogging implements Consumer> { private NavigableMap levels = new TreeMap<>(); private volatile boolean updatingConfiguration = false; - private final ExecutorService executor; +// private final ExecutorService executor; private final LogEntryPublisher publisher; + private PrintStreamSubscriber synchronousSubscriber; private final boolean journald; private final Level callLocationLevel; - ThinLogging() { - executor = Executors.newCachedThreadPool((r) -> { - Thread t = new Thread(r); - t.setDaemon(true); - return t; - }); - publisher = new LogEntryPublisher(executor, Flow.defaultBufferSize()); + private boolean synchronous = true; - PrintStreamSubscriber subscriber = new PrintStreamSubscriber(); - publisher.subscribe(subscriber); + ThinLogging() { +// executor = Executors.newCachedThreadPool((r) -> { +// Thread t = new Thread(r); +// t.setDaemon(true); +// return t; +// }); + if (synchronous) { + publisher = new LogEntryPublisher(); + synchronousSubscriber = new PrintStreamSubscriber(); + } else { + publisher = new LogEntryPublisher(); + + PrintStreamSubscriber subscriber = new PrintStreamSubscriber(); + publisher.subscribe(subscriber); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> close(), "Log shutdown")); - Runtime.getRuntime().addShutdownHook(new Thread(() -> close(), "Log shutdown")); + } // initial default level levels.put("", Level.WARNING); @@ -131,7 +138,8 @@ class ThinLogging implements Consumer> { try { // we ait a bit in order to make sure all messages are flushed // TODO synchronize more efficiently - executor.awaitTermination(300, TimeUnit.MILLISECONDS); + // executor.awaitTermination(300, TimeUnit.MILLISECONDS); + ForkJoinPool.commonPool().awaitTermination(300, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { // silent } @@ -342,8 +350,8 @@ class ThinLogging implements Consumer> { private class LogEntryPublisher extends SubmissionPublisher> { - private LogEntryPublisher(Executor executor, int maxBufferCapacity) { - super(executor, maxBufferCapacity); + private LogEntryPublisher() { + super(); } private void log(ThinLogger logger, Level level, ResourceBundle bundle, String msg, Instant instant, @@ -372,8 +380,13 @@ class ThinLogging implements Consumer> { logEntry.put(KEY_THREAD, thread.getName()); // should be unmodifiable for security reasons - if (!isClosed()) - submit(Collections.unmodifiableMap(logEntry)); + if (synchronous) { + assert synchronousSubscriber != null; + synchronousSubscriber.onNext(logEntry); + } else { + if (!isClosed()) + submit(Collections.unmodifiableMap(logEntry)); + } } } @@ -559,6 +572,16 @@ class ThinLogging implements Consumer> { logger.log(Logger.Level.INFO, "Log info"); logger.log(Logger.Level.WARNING, "Log warning"); logger.log(Logger.Level.ERROR, "Log exception", new Throwable()); + + try { + // we ait a bit in order to make sure all messages are flushed + // TODO synchronize more efficiently + // executor.awaitTermination(300, TimeUnit.MILLISECONDS); + ForkJoinPool.commonPool().awaitTermination(300, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + // silent + } + } } -- 2.30.2