You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 09:22:25 UTC

[sling-org-apache-sling-commons-logservice] 10/12: SLING-4510 : Sling LogService could provide more usable output. Apply patch from David Bosschaert

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.commons.logservice-1.0.4
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-logservice.git

commit 8ac93b8538919283f716d3bd193e1434158d6976
Author: Carsten Ziegeler <cz...@apache.org>
AuthorDate: Mon Mar 30 11:11:34 2015 +0000

    SLING-4510 : Sling LogService could provide more usable output. Apply patch from David Bosschaert
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/logservice@1670052 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  11 ++
 .../commons/logservice/internal/LogSupport.java    |  36 +++--
 .../logservice/internal/LogSupportTest.java        | 155 +++++++++++++++++++++
 3 files changed, 188 insertions(+), 14 deletions(-)

diff --git a/pom.xml b/pom.xml
index 978c77d..b887eed 100644
--- a/pom.xml
+++ b/pom.xml
@@ -111,5 +111,16 @@
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-all</artifactId>
+            <version>1.10.19</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java b/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java
index 4a703ea..78bf2b6 100644
--- a/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java
+++ b/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sling.commons.logservice.internal;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.LinkedHashMap;
@@ -72,6 +73,7 @@ public class LogSupport implements SynchronousBundleListener, ServiceListener,
         0.75f, true) {
         private static final int MAX_SIZE = 50;
 
+        @Override
         protected boolean removeEldestEntry(Map.Entry<Long, Logger> eldest) {
             return size() > MAX_SIZE;
         }
@@ -290,11 +292,6 @@ public class LogSupport implements SynchronousBundleListener, ServiceListener,
                 message = "ServiceEvent " + event.getType();
         }
 
-        String s = (event.getServiceReference().getBundle() == null)
-                ? null
-                : "Bundle " + event.getServiceReference().getBundle();
-        s = (s == null) ? message : s + " " + message;
-
         LogEntry entry = new LogEntryImpl(
             event.getServiceReference().getBundle(),
             event.getServiceReference(), level, message, null);
@@ -362,10 +359,6 @@ public class LogSupport implements SynchronousBundleListener, ServiceListener,
                 message = "FrameworkEvent " + event.getType();
         }
 
-        String s = (event.getBundle() == null) ? null : "Bundle "
-            + event.getBundle();
-        s = (s == null) ? message : s + " " + message;
-
         LogEntry entry = new LogEntryImpl(event.getBundle(), null, level,
             message, exception);
         fireLogEvent(entry);
@@ -434,13 +427,13 @@ public class LogSupport implements SynchronousBundleListener, ServiceListener,
      * in the log entry.
      */
     private void logOut(LogEntry logEntry) {
-        // /* package */ void logOut(Bundle bundle, ServiceReference sr, int
-        // level, String message, Throwable exception) {
-
         // get the logger for the bundle
         Logger log = getLogger(logEntry.getBundle());
+        if (logEntry.getLevel() > getLevel(log))
+            // early Exit, this message will not be logged, don't do any work...
+            return;
 
-        StringBuffer msg = new StringBuffer();
+        final StringBuilder msg = new StringBuilder();
 
         ServiceReference sr = logEntry.getServiceReference();
         if (sr != null) {
@@ -453,7 +446,10 @@ public class LogSupport implements SynchronousBundleListener, ServiceListener,
                 msg.append(sr.getProperty(Constants.SERVICE_DESCRIPTION)).append(
                     ',');
             }
-            msg.append(sr.getProperty(Constants.SERVICE_ID)).append("] ");
+            msg.append(sr.getProperty(Constants.SERVICE_ID))
+                .append(", ")
+                .append(Arrays.toString((String[]) sr.getProperty(Constants.OBJECTCLASS)))
+                .append("] ");
         }
 
         if (logEntry.getMessage() != null) {
@@ -489,6 +485,18 @@ public class LogSupport implements SynchronousBundleListener, ServiceListener,
         }
     }
 
+    static int getLevel(Logger log) {
+        if (log.isTraceEnabled())
+            return LogService.LOG_DEBUG + 1; // No constant for trace in LogService
+        else if (log.isDebugEnabled())
+            return LogService.LOG_DEBUG;
+        else if (log.isInfoEnabled())
+            return LogService.LOG_INFO;
+        else if (log.isWarnEnabled())
+            return LogService.LOG_WARNING;
+        return LogService.LOG_ERROR;
+    }
+
     // ---------- internal class -----------------------------------------------
 
     /**
diff --git a/src/test/java/org/apache/sling/commons/logservice/internal/LogSupportTest.java b/src/test/java/org/apache/sling/commons/logservice/internal/LogSupportTest.java
new file mode 100644
index 0000000..8c19d32
--- /dev/null
+++ b/src/test/java/org/apache/sling/commons/logservice/internal/LogSupportTest.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.commons.logservice.internal;
+
+import static org.junit.Assert.assertEquals;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogService;
+import org.slf4j.Logger;
+
+public class LogSupportTest {
+    @Test @SuppressWarnings("unchecked")
+    public void testServiceEvent() throws Exception {
+        LogSupport ls = new LogSupport();
+        Field lf = LogSupport.class.getDeclaredField("loggers");
+        lf.setAccessible(true);
+        Map<Long, Logger> loggers = (Map<Long, Logger>) lf.get(ls);
+
+        Bundle b = Mockito.mock(Bundle.class);
+        Mockito.when(b.getSymbolicName()).thenReturn("foo.bundle");
+        Mockito.when(b.getBundleId()).thenReturn(42L);
+
+        final Map<String, Object> props = new HashMap<String, Object>();
+        props.put(Constants.OBJECTCLASS, new String [] {"some.class.Name"});
+        props.put(Constants.SERVICE_ID, 999L);
+
+        ServiceReference sr = Mockito.mock(ServiceReference.class);
+        Mockito.when(sr.getBundle()).thenReturn(b);
+        Mockito.when(sr.getProperty(Mockito.anyString())).then(new Answer<Object>() {
+            public Object answer(InvocationOnMock invocation) throws Throwable {
+                return props.get(invocation.getArguments()[0]);
+            }
+        });
+        Mockito.when(sr.getPropertyKeys()).thenReturn(props.keySet().toArray(new String[] {}));
+        ServiceEvent se = new ServiceEvent(ServiceEvent.REGISTERED, sr);
+
+        Logger testLogger = getMockInfoLogger();
+        loggers.put(42L, testLogger);
+
+        ls.serviceChanged(se);
+
+        Mockito.verify(testLogger).info("Service [999, [some.class.Name]] ServiceEvent REGISTERED", (Throwable) null);
+    }
+
+    @Test @SuppressWarnings("unchecked")
+    public void testEarlyExit() throws Exception {
+        Bundle b = Mockito.mock(Bundle.class);
+        Mockito.when(b.getSymbolicName()).thenReturn("bar.bundle");
+        Mockito.when(b.getBundleId()).thenReturn(1L);
+
+        ServiceReference sr = Mockito.mock(ServiceReference.class);
+        LogEntry le = new LogEntryImpl(b, sr, LogService.LOG_DEBUG, "test", null);
+
+        LogSupport ls = new LogSupport();
+        Field lf = LogSupport.class.getDeclaredField("loggers");
+        lf.setAccessible(true);
+        Map<Long, Logger> loggers = (Map<Long, Logger>) lf.get(ls);
+
+        Logger testLogger = getMockInfoLogger();
+        loggers.put(1L, testLogger);
+
+        ls.fireLogEvent(le);
+
+        // The log message is on DEBUG level while the logger is set to INFO level
+        // we don't want the actual log.info() call to be made, neither do we want
+        // any preparatory work on the log message being made (which involves
+        // inspecting the service reference).
+        Mockito.verify(testLogger).isTraceEnabled();
+        Mockito.verify(testLogger).isDebugEnabled();
+        Mockito.verify(testLogger).isInfoEnabled();
+        Mockito.verifyNoMoreInteractions(testLogger);
+        Mockito.verifyZeroInteractions(sr);
+    }
+
+    @Test @SuppressWarnings("unchecked")
+    public void testErrorLogger() throws Exception {
+        Bundle b = Mockito.mock(Bundle.class);
+        Mockito.when(b.getSymbolicName()).thenReturn("bar.bundle");
+        Mockito.when(b.getBundleId()).thenReturn(1L);
+
+        Exception e = new Exception();
+        LogEntry le = new LogEntryImpl(b, null, LogService.LOG_ERROR, "my-error-msg", e);
+
+        LogSupport ls = new LogSupport();
+        Field lf = LogSupport.class.getDeclaredField("loggers");
+        lf.setAccessible(true);
+        Map<Long, Logger> loggers = (Map<Long, Logger>) lf.get(ls);
+
+        Logger testLogger = getMockInfoLogger();
+        loggers.put(1L, testLogger);
+
+        ls.fireLogEvent(le);
+
+        Mockito.verify(testLogger).error("my-error-msg (java.lang.Exception)", e);
+    }
+
+    @Test
+    public void testGetLevels() {
+        Logger traceLogger = Mockito.mock(Logger.class);
+        Mockito.when(traceLogger.isTraceEnabled()).thenReturn(true);
+        assertEquals(5, LogSupport.getLevel(traceLogger));
+
+        Logger debugLogger = Mockito.mock(Logger.class);
+        Mockito.when(debugLogger.isDebugEnabled()).thenReturn(true);
+        assertEquals(LogService.LOG_DEBUG, LogSupport.getLevel(debugLogger));
+
+        Logger infoLogger = Mockito.mock(Logger.class);
+        Mockito.when(infoLogger.isInfoEnabled()).thenReturn(true);
+        assertEquals(LogService.LOG_INFO, LogSupport.getLevel(infoLogger));
+
+        Logger warnLogger = Mockito.mock(Logger.class);
+        Mockito.when(warnLogger.isWarnEnabled()).thenReturn(true);
+        assertEquals(LogService.LOG_WARNING, LogSupport.getLevel(warnLogger));
+
+        Logger errorLogger = Mockito.mock(Logger.class);
+        Mockito.when(errorLogger.isErrorEnabled()).thenReturn(true);
+        assertEquals(LogService.LOG_ERROR, LogSupport.getLevel(errorLogger));
+    }
+
+    private Logger getMockInfoLogger() {
+        Logger testLogger = Mockito.mock(Logger.class);
+        Mockito.when(testLogger.isTraceEnabled()).thenReturn(false);
+        Mockito.when(testLogger.isDebugEnabled()).thenReturn(false);
+        Mockito.when(testLogger.isInfoEnabled()).thenReturn(true);
+        Mockito.when(testLogger.isWarnEnabled()).thenReturn(true);
+        Mockito.when(testLogger.isErrorEnabled()).thenReturn(true);
+        return testLogger;
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.