Author: cziegeler Date: Mon Mar 30 11:11:34 2015 New Revision: 1670052 URL: http://svn.apache.org/r1670052 Log: SLING-4510 : Sling LogService could provide more usable output. Apply patch from David Bosschaert
Added: sling/trunk/bundles/commons/logservice/src/test/java/org/ sling/trunk/bundles/commons/logservice/src/test/java/org/apache/ sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/ sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/commons/ sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/commons/logservice/ sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/commons/logservice/internal/ sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/commons/logservice/internal/LogSupportTest.java (with props) Modified: sling/trunk/bundles/commons/logservice/pom.xml sling/trunk/bundles/commons/logservice/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java Modified: sling/trunk/bundles/commons/logservice/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/logservice/pom.xml?rev=1670052&r1=1670051&r2=1670052&view=diff ============================================================================== --- sling/trunk/bundles/commons/logservice/pom.xml (original) +++ sling/trunk/bundles/commons/logservice/pom.xml Mon Mar 30 11:11:34 2015 @@ -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> Modified: sling/trunk/bundles/commons/logservice/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/logservice/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java?rev=1670052&r1=1670051&r2=1670052&view=diff ============================================================================== --- sling/trunk/bundles/commons/logservice/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java (original) +++ sling/trunk/bundles/commons/logservice/src/main/java/org/apache/sling/commons/logservice/internal/LogSupport.java Mon Mar 30 11:11:34 2015 @@ -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 Synch 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 Synch 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 Synch 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 Synch * 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 Synch 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 Synch } } + 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 ----------------------------------------------- /** Added: sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/commons/logservice/internal/LogSupportTest.java URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/commons/logservice/internal/LogSupportTest.java?rev=1670052&view=auto ============================================================================== --- sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/commons/logservice/internal/LogSupportTest.java (added) +++ sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/commons/logservice/internal/LogSupportTest.java Mon Mar 30 11:11:34 2015 @@ -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; + } +} Propchange: sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/commons/logservice/internal/LogSupportTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/commons/logservice/internal/LogSupportTest.java ------------------------------------------------------------------------------ svn:keywords = author date id revision rev url Propchange: sling/trunk/bundles/commons/logservice/src/test/java/org/apache/sling/commons/logservice/internal/LogSupportTest.java ------------------------------------------------------------------------------ svn:mime-type = text/plain