diff --git a/solr/core/src/java/org/apache/solr/security/AuditLoggerPlugin.java b/solr/core/src/java/org/apache/solr/security/AuditLoggerPlugin.java index 36affa148b9..80fe11e2cd7 100644 --- a/solr/core/src/java/org/apache/solr/security/AuditLoggerPlugin.java +++ b/solr/core/src/java/org/apache/solr/security/AuditLoggerPlugin.java @@ -150,7 +150,7 @@ public abstract class AuditLoggerPlugin implements Closeable, Runnable, SolrInfo audit(event); } catch(Exception e) { numErrors.mark(); - throw e; + log.error("Exception when attempting to audit log", e); } finally { totalTime.inc(timer.stop()); } @@ -209,7 +209,7 @@ public abstract class AuditLoggerPlugin implements Closeable, Runnable, SolrInfo log.warn("Interrupted while waiting for next audit log event"); Thread.currentThread().interrupt(); } catch (Exception ex) { - log.warn("Exception when attempting to audit log asynchronously", ex); + log.error("Exception when attempting to audit log asynchronously", ex); numErrors.mark(); } } @@ -309,20 +309,35 @@ public abstract class AuditLoggerPlugin implements Closeable, Runnable, SolrInfo } } + /** + * Waits 30s for async queue to drain, then closes executor threads. + * Subclasses should either call super.close() or {@link #waitForQueueToDrain(int)} + * before shutting itself down to make sure they can complete logging events in the queue. + */ @Override public void close() throws IOException { + if (async && executorService != null) { + waitForQueueToDrain(30); + closed = true; + log.info("Shutting down async Auditlogger background thread(s)"); + executorService.shutdownNow(); + } + } + + /** + * Blocks until the async event queue is drained + * @param timeoutSeconds number of seconds to wait for queue to drain + */ + protected void waitForQueueToDrain(int timeoutSeconds) { if (async && executorService != null) { int timeSlept = 0; - while (!queue.isEmpty() && timeSlept < 30) { + while (!queue.isEmpty() && timeSlept < timeoutSeconds) { try { log.info("Async auditlogger queue still has {} elements, sleeping to let it drain...", queue.size()); Thread.sleep(1000); timeSlept ++; } catch (InterruptedException ignored) {} } - closed = true; - log.info("Shutting down async Auditlogger background thread(s)"); - executorService.shutdownNow(); } } diff --git a/solr/core/src/java/org/apache/solr/security/MultiDestinationAuditLogger.java b/solr/core/src/java/org/apache/solr/security/MultiDestinationAuditLogger.java index 9aaae5c1403..7ad6b5bc167 100644 --- a/solr/core/src/java/org/apache/solr/security/MultiDestinationAuditLogger.java +++ b/solr/core/src/java/org/apache/solr/security/MultiDestinationAuditLogger.java @@ -126,6 +126,7 @@ public class MultiDestinationAuditLogger extends AuditLoggerPlugin implements Re @Override public void close() throws IOException { + super.close(); // Waiting for queue to drain before shutting down the loggers plugins.forEach(p -> { try { p.close(); @@ -133,6 +134,5 @@ public class MultiDestinationAuditLogger extends AuditLoggerPlugin implements Re log.error("Exception trying to close {}", p.getName()); } }); - super.close(); } }