diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTask.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTask.java index e677f2ca99..5202331cb9 100755 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTask.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTask.java @@ -31,8 +31,7 @@ import ch.qos.logback.core.status.StatusUtil; import static ch.qos.logback.core.CoreConstants.PROPERTIES_FILE_EXTENSION; -import static ch.qos.logback.core.spi.ConfigurationEvent.newConfigurationChangeDetectorRunningEvent; -import static ch.qos.logback.core.spi.ConfigurationEvent.newConfigurationEndedSuccessfullyEvent; +import static ch.qos.logback.core.spi.ConfigurationEvent.*; public class ReconfigureOnChangeTask extends ContextAwareBase implements Runnable { @@ -75,7 +74,7 @@ public void run() { return; } - // ======== + // ======== fuller processing below cancelFutureInvocationsOfThisTaskInstance(); URL mainConfigurationURL = configurationWatchList.getMainURL(); @@ -95,6 +94,7 @@ private void runPropertiesConfigurator(File changedFile) { propertyConfigurator.setContext(context); try { propertyConfigurator.doConfigure(changedFile); + context.fireConfigurationEvent(newPartialConfigurationEndedSuccessfullyEvent(this)); } catch (JoranException e) { addError("Failed to reload "+ changedFile); } diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/PartialConfigurationEndedSuccessfullyEventListener.java b/logback-classic/src/test/java/ch/qos/logback/classic/joran/PartialConfigurationEndedSuccessfullyEventListener.java new file mode 100644 index 0000000000..19f7e5c230 --- /dev/null +++ b/logback-classic/src/test/java/ch/qos/logback/classic/joran/PartialConfigurationEndedSuccessfullyEventListener.java @@ -0,0 +1,41 @@ +/* + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2024, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ + +package ch.qos.logback.classic.joran; + +import ch.qos.logback.core.spi.ConfigurationEvent; +import ch.qos.logback.core.spi.ConfigurationEventListener; + +import java.util.concurrent.CountDownLatch; + +class PartialConfigurationEndedSuccessfullyEventListener implements ConfigurationEventListener { + + CountDownLatch countDownLatch; + + PartialConfigurationEndedSuccessfullyEventListener(CountDownLatch countDownLatch) { + this.countDownLatch = countDownLatch; + } + + @Override + public void listen(ConfigurationEvent configurationEvent) { + switch (configurationEvent.getEventType()) { + case PARTIAL_CONFIGURATION_ENDED_SUCCESSFULLY: + System.out.println(this.toString() + "#listen PARTIAL_CONFIGURATION_ENDED_SUCCESSFULLY detected " + configurationEvent +" count="+countDownLatch.getCount()); + + countDownLatch.countDown(); + break; + default: + } + } +} diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTaskTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTaskTest.java index d214171e2a..bef279e3a4 100755 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTaskTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/joran/ReconfigureOnChangeTaskTest.java @@ -159,6 +159,7 @@ public void scanWithResourceInclusion() throws JoranException, IOException, Inte assertThatListContainsFile(fileList, innerFile); } + @Timeout(value = TIMEOUT, unit = TimeUnit.SECONDS) @Test public void propertiesConfigurationTest() throws IOException, JoranException, InterruptedException { String loggerName = "abc"; @@ -169,14 +170,21 @@ public void propertiesConfigurationTest() throws IOException, JoranException, In configure(asBAIS(configurationStr)); Logger abcLogger = loggerContext.getLogger(loggerName); assertEquals(Level.INFO, abcLogger.getLevel()); - Thread.sleep(100); + + CountDownLatch changeDetectedLatch0 = registerChangeDetectedListener(); + CountDownLatch configurationDoneLatch0 = registerPartialConfigurationEndedSuccessfullyEventListener(); + writeToFile(propertiesFile, PropertyConfigurator.LOGBACK_LOGGER_PREFIX + loggerName+"=WARN"); - Thread.sleep(200); + changeDetectedLatch0.await(); + configurationDoneLatch0.await(); assertEquals(Level.WARN, abcLogger.getLevel()); - Thread.sleep(100); + + CountDownLatch changeDetectedLatch1 = registerChangeDetectedListener(); + CountDownLatch configurationDoneLatch1 = registerPartialConfigurationEndedSuccessfullyEventListener(); writeToFile(propertiesFile, PropertyConfigurator.LOGBACK_LOGGER_PREFIX + loggerName+"=ERROR"); - Thread.sleep(200); + changeDetectedLatch1.await(); + configurationDoneLatch1.await(); assertEquals(Level.ERROR, abcLogger.getLevel()); @@ -318,6 +326,13 @@ CountDownLatch registerNewReconfigurationDoneSuccessfullyListener(ReconfigureOnC return latch; } + CountDownLatch registerPartialConfigurationEndedSuccessfullyEventListener() { + CountDownLatch latch = new CountDownLatch(1); + PartialConfigurationEndedSuccessfullyEventListener listener = new PartialConfigurationEndedSuccessfullyEventListener(latch); + loggerContext.addConfigurationEventListener(listener); + return latch; + } + CountDownLatch registerChangeDetectedListener() { CountDownLatch latch = new CountDownLatch(1); ChangeDetectedListener changeDetectedListener = new ChangeDetectedListener(latch); diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/ConfigurationEvent.java b/logback-core/src/main/java/ch/qos/logback/core/spi/ConfigurationEvent.java index 17a3504db1..704bd68c05 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/ConfigurationEvent.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/ConfigurationEvent.java @@ -32,6 +32,7 @@ public enum EventType { CHANGE_DETECTOR_RUNNING, CHANGE_DETECTED, CONFIGURATION_STARTED, + PARTIAL_CONFIGURATION_ENDED_SUCCESSFULLY, CONFIGURATION_ENDED_SUCCESSFULLY, CONFIGURATION_ENDED_WITH_XML_PARSING_ERRORS; } @@ -62,6 +63,11 @@ static public ConfigurationEvent newConfigurationChangeDetectedEvent(Object data static public ConfigurationEvent newConfigurationStartedEvent(Object data) { return new ConfigurationEvent(EventType.CONFIGURATION_STARTED, data); } + static public ConfigurationEvent newPartialConfigurationEndedSuccessfullyEvent(Object data) { + return new ConfigurationEvent(EventType.PARTIAL_CONFIGURATION_ENDED_SUCCESSFULLY, data); + } + + static public ConfigurationEvent newConfigurationEndedSuccessfullyEvent(Object data) { return new ConfigurationEvent(EventType.CONFIGURATION_ENDED_SUCCESSFULLY, data); }