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)));
+    }
 }

Reply via email to