This is an automated email from the ASF dual-hosted git repository. royteeuwen pushed a commit to branch SLING-13224 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-log.git
commit e80b2d12a878801f8887c8a4416b517f8b185359 Author: Roy Teeuwen <[email protected]> AuthorDate: Thu May 28 21:09:21 2026 +0200 SLING-13224 - Allow configuring which loggers the LogStore captures LogStoreRegistrar hard-coded the LogStoreAppender's "loggers" service property to "ROOT", so the in-memory store only captured events that propagate to ROOT. Loggers configured with additivity=false (log.request, log.access, audit logs, etc.) never reached it. Add an optional "loggers" property on the existing org.apache.sling.commons.log.LogStore PID (default ["ROOT"], preserving today's behaviour). LogStoreRegistrar parses it via the OSGi Converter and uses it as the appender service property, so AppenderTracker attaches the store to each named logger. Reconfiguration is hot: changing the property invokes setProperties on the existing registration and AppenderTracker.modifiedService re-attaches. Example org.apache.sling.commons.log.LogStore.cfg.json: { "maxEntries:Integer": 10000, "loggers": ["ROOT", "log.request", "log.access"] } Additive change: configurations that don't set "loggers" get the historical ["ROOT"] default. No public API change. --- .../logback/internal/store/LogStoreRegistrar.java | 44 ++++++++++++++++++++-- .../integration/ITLogStoreRegistrarLifecycle.java | 39 +++++++++++++++++++ 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/apache/sling/commons/log/logback/internal/store/LogStoreRegistrar.java b/src/main/java/org/apache/sling/commons/log/logback/internal/store/LogStoreRegistrar.java index eb87229..b63c858 100644 --- a/src/main/java/org/apache/sling/commons/log/logback/internal/store/LogStoreRegistrar.java +++ b/src/main/java/org/apache/sling/commons/log/logback/internal/store/LogStoreRegistrar.java @@ -35,6 +35,8 @@ public class LogStoreRegistrar { static final String PID = "org.apache.sling.commons.log.LogStore"; static final String PROP_MAX_ENTRIES = "maxEntries"; + static final String PROP_LOGGERS = "loggers"; + static final String[] DEFAULT_LOGGERS = {"ROOT"}; private ServiceRegistration<LogStore> storeRegistration; private ServiceRegistration<Appender> appenderRegistration; @@ -42,6 +44,7 @@ public class LogStoreRegistrar { private BundleContext bundleContext; private LogStoreImpl store; private LogStoreAppender appender; + private String[] activeLoggers; public void start(BundleContext context) { this.bundleContext = context; @@ -74,14 +77,23 @@ public class LogStoreRegistrar { .defaultValue(LogStoreImpl.DEFAULT_MAX_ENTRIES) .to(Integer.class); + String[] loggers = Converters.standardConverter() + .convert(properties.get(PROP_LOGGERS)) + .defaultValue(DEFAULT_LOGGERS) + .to(String[].class); + if (loggers == null || loggers.length == 0) { + loggers = DEFAULT_LOGGERS; + } + if (store == null) { - activate(maxEntries); + activate(maxEntries, loggers); } else { store.setMaxEntries(maxEntries); + applyLoggerConfig(loggers); } } - private void activate(int maxEntries) { + private void activate(int maxEntries, String[] loggers) { if (bundleContext == null || store != null) { return; } @@ -97,8 +109,33 @@ public class LogStoreRegistrar { Dictionary<String, Object> appenderProps = new Hashtable<>(); appenderProps.put(Constants.SERVICE_VENDOR, LogConstants.ASF_SERVICE_VENDOR); appenderProps.put(Constants.SERVICE_DESCRIPTION, "Log Store Appender"); - appenderProps.put("loggers", "ROOT"); + appenderProps.put(PROP_LOGGERS, loggers); appenderRegistration = bundleContext.registerService(Appender.class, appender, appenderProps); + activeLoggers = loggers; + } + + private void applyLoggerConfig(String[] loggers) { + if (appenderRegistration == null || equalLoggers(activeLoggers, loggers)) { + return; + } + Dictionary<String, Object> appenderProps = new Hashtable<>(); + appenderProps.put(Constants.SERVICE_VENDOR, LogConstants.ASF_SERVICE_VENDOR); + appenderProps.put(Constants.SERVICE_DESCRIPTION, "Log Store Appender"); + appenderProps.put(PROP_LOGGERS, loggers); + appenderRegistration.setProperties(appenderProps); + activeLoggers = loggers; + } + + private boolean equalLoggers(String[] a, String[] b) { + if (a == null || b == null || a.length != b.length) { + return false; + } + for (int i = 0; i < a.length; i++) { + if (!a[i].equals(b[i])) { + return false; + } + } + return true; } private void deactivate() { @@ -113,5 +150,6 @@ public class LogStoreRegistrar { appender = null; store = null; + activeLoggers = null; } } diff --git a/src/test/java/org/apache/sling/commons/log/logback/integration/ITLogStoreRegistrarLifecycle.java b/src/test/java/org/apache/sling/commons/log/logback/integration/ITLogStoreRegistrarLifecycle.java index 2e1a123..e7b4373 100644 --- a/src/test/java/org/apache/sling/commons/log/logback/integration/ITLogStoreRegistrarLifecycle.java +++ b/src/test/java/org/apache/sling/commons/log/logback/integration/ITLogStoreRegistrarLifecycle.java @@ -20,8 +20,11 @@ package org.apache.sling.commons.log.logback.integration; import javax.inject.Inject; +import java.util.Arrays; import java.util.Dictionary; +import java.util.HashSet; import java.util.Hashtable; +import java.util.Set; import ch.qos.logback.core.Appender; import org.apache.sling.commons.log.logback.store.LogStore; @@ -31,10 +34,13 @@ import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.junit.PaxExam; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerClass; +import org.osgi.framework.ServiceReference; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.util.converter.Converters; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.ops4j.pax.exam.CoreOptions.composite; import static org.ops4j.pax.exam.CoreOptions.mavenBundle; @@ -44,6 +50,7 @@ public class ITLogStoreRegistrarLifecycle extends LogTestBase { private static final String LOG_STORE_PID = "org.apache.sling.commons.log.LogStore"; private static final String MAX_ENTRIES = "maxEntries"; + private static final String LOGGERS = "loggers"; @Inject private ConfigurationAdmin ca; @@ -88,4 +95,36 @@ public class ITLogStoreRegistrarLifecycle extends LogTestBase { assertEquals(0, bundleContext.getServiceReferences(LogStore.class, null).size()); assertEquals(0, bundleContext.getServiceReferences(Appender.class, null).size()); } + + @Test + public void testLoggersConfiguration() throws Exception { + Configuration config = ca.getConfiguration(LOG_STORE_PID, null); + try { + Dictionary<String, Object> properties = new Hashtable<>(); + properties.put(MAX_ENTRIES, 5); + properties.put(LOGGERS, new String[] {"ROOT", "test.other"}); + config.update(properties); + delay(); + + assertEquals(Set.of("ROOT", "test.other"), readLoggersProperty()); + + properties.put(LOGGERS, new String[] {"ROOT"}); + config.update(properties); + delay(); + + assertEquals(Set.of("ROOT"), readLoggersProperty()); + } finally { + config.delete(); + delay(); + } + } + + private Set<String> readLoggersProperty() throws Exception { + ServiceReference<?>[] refs = bundleContext.getServiceReferences(Appender.class.getName(), null); + assertNotNull("expected an Appender registration", refs); + assertEquals(1, refs.length); + Object property = refs[0].getProperty(LOGGERS); + return new HashSet<>( + Arrays.asList(Converters.standardConverter().convert(property).to(String[].class))); + } }
