diff --git a/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/Appender.java b/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/Appender.java index d2783a405ed..7ccb02bd6d7 100644 --- a/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/Appender.java +++ b/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/Appender.java @@ -22,6 +22,10 @@ import java.io.IOException; */ public interface Appender { + void setId(String id); + + String getId(); + void append(String date, int ms, Severity severity, String name, String message, Throwable t) throws IOException; void setProperty(String key, String value) throws Exception; diff --git a/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/CentralLoggerConfig.java b/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/CentralLoggerConfig.java index b1494f4b0d4..cac0b32cfb4 100644 --- a/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/CentralLoggerConfig.java +++ b/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/CentralLoggerConfig.java @@ -23,6 +23,7 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -48,6 +49,8 @@ public class CentralLoggerConfig private static void configureAppender(Properties props, String id, Appender appender) { + appender.setId(id); + // Collect configuration fields for appender id Pattern appenderIdRegex = Pattern.compile("^appender\\." + id + "\\.([^\\.]*)$"); Matcher match; @@ -88,7 +91,9 @@ public class CentralLoggerConfig out.printf("%sAppenders: ",prefix); for (Iterator it = cl.getAppenders().iterator(); it.hasNext();) { - out.print(it.next().getClass().getSimpleName()); + Appender ap = it.next(); + // out.printf("(%s) %s",ap.getClass().getSimpleName(),ap); + out.print(ap); if (it.hasNext()) { out.print(", "); @@ -111,26 +116,38 @@ public class CentralLoggerConfig } } - private static List getAppenders(Properties props, String key, Map declaredAppenders) + private static Set getAppenderIds(Properties props, String key) { + Set ids = new TreeSet(); + String value = props.getProperty(key); if (value == null) { - return null; + return ids; } - String ids[] = value.split(","); - List appenders = new ArrayList(); - // ensure ids exist as declared as well. - for (int i = 0, n = ids.length; i < n; i++) + String parts[] = value.split(","); + for (int i = 0, n = parts.length; i < n; i++) { - if (declaredAppenders.containsKey(ids[i])) + ids.add(parts[i].trim()); + } + + return ids; + } + + private static List getAppenders(Properties props, String key, Map declaredAppenders) + { + Set ids = getAppenderIds(props,key); + List appenders = new ArrayList(); + for (String id : ids) + { + if (declaredAppenders.containsKey(id)) { - appenders.add(declaredAppenders.get(ids[i])); + appenders.add(declaredAppenders.get(id)); } else { - System.err.println("No such Appender: " + ids[i]); + System.err.println("No such Appender: " + id); } } @@ -230,9 +247,8 @@ public class CentralLoggerConfig Map declaredAppenders = getDeclaredAppenders(props); root.appenders = getAppenders(props,"root.appenders",declaredAppenders); - if (root.appenders == null) + if (root.appenders.isEmpty()) { - root.appenders = new ArrayList(); // Default (if not specified for root) root.appenders.add(new ConsoleAppender()); } @@ -265,10 +281,29 @@ public class CentralLoggerConfig // Set loggers & levels of OTHER nodes for (String id : ids) { - System.out.println("Processing child id: " + id); CentralLoggerConfig childlog = root.getConfiguredLogger(id); childlog.level = Severity.valueOf(props.getProperty("logger." + id + ".level","INFO")); - childlog.addAppenders(getAppenders(props,"logger." + id + ".appenders",declaredAppenders)); + Set appenderIds = getAppenderIds(props,"logger." + id + ".appenders"); + for (String appenderId : appenderIds) + { + if (appenderId.startsWith("-")) + { + // Remove an appender + childlog.removeAppenderById(appenderId.substring(1)); + } + else + { + // Add an appender + if (declaredAppenders.containsKey(appenderId)) + { + childlog.addAppender(declaredAppenders.get(appenderId)); + } + else + { + System.err.println("No such Appender: " + appenderId); + } + } + } } return root; @@ -293,7 +328,7 @@ public class CentralLoggerConfig this.appenders.addAll(copyLogger.appenders); this.level = copyLogger.level; - this.logger = new CentralLogger(name,appenders.toArray(new Appender[] {}),level); + this.logger = new CentralLogger(this.name,appenders.toArray(new Appender[] {}),level); } private CentralLoggerConfig(String name) @@ -301,14 +336,22 @@ public class CentralLoggerConfig this.name = name; } - private void addAppenders(List moreAppenders) + private void addAppender(Appender appender) { - if (moreAppenders == null) + getAppenders().add(appender); + } + + private void removeAppenderById(String id) + { + ListIterator it = appenders.listIterator(); + while (it.hasNext()) { - return; + Appender appender = it.next(); + if (id.equals(appender.getId())) + { + it.remove(); + } } - getAppenders().addAll(moreAppenders); - this.logger = new CentralLogger(name,appenders.toArray(new Appender[] {}),level); } public void dumpTree(PrintStream out) diff --git a/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/ConsoleAppender.java b/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/ConsoleAppender.java index 386f82f7ca7..42fe4faedd4 100644 --- a/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/ConsoleAppender.java +++ b/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/ConsoleAppender.java @@ -22,6 +22,18 @@ import java.io.IOException; */ public class ConsoleAppender implements Appender { + private String id; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + public void append(String date, int ms, Severity severity, String name, String message, Throwable t) { StringBuffer buf = new StringBuffer(); @@ -65,4 +77,10 @@ public class ConsoleAppender implements Appender { /* nothing to do here */ } + + @Override + public String toString() + { + return "ConsoleAppender[" + id + "]"; + } } diff --git a/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/RollingFileAppender.java b/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/RollingFileAppender.java index 74af571f3c6..a21ff6c35a3 100644 --- a/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/RollingFileAppender.java +++ b/jetty-centralized-logging/src/main/java/org/eclipse/jetty/logging/impl/RollingFileAppender.java @@ -29,6 +29,7 @@ import org.eclipse.jetty.util.RolloverFileOutputStream; */ public class RollingFileAppender implements Appender { + private static final byte[] LN = System.getProperty("line.separator","\n").getBytes(); private RolloverFileOutputStream out; private String filename; private File file; @@ -37,6 +38,17 @@ public class RollingFileAppender implements Appender private TimeZone zone = TimeZone.getDefault(); private String dateFormat = "yyyy_MM_dd"; private String backupFormat = "HHmmssSSS"; + private String id; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } public void append(String date, int ms, Severity severity, String name, String message, Throwable t) throws IOException { @@ -60,9 +72,11 @@ public class RollingFileAppender implements Appender buf.append(':').append(message); out.write(buf.toString().getBytes()); + out.write(LN); if (t != null) { t.printStackTrace(new PrintStream(out)); + out.write(LN); } out.flush(); } @@ -195,4 +209,10 @@ public class RollingFileAppender implements Appender { this.zone = zone; } + + @Override + public String toString() + { + return "RollingFileAppender[" + id + "|" + filename + "]"; + } } diff --git a/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/CentralizedLoggingTest.java b/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/CentralizedLoggingTest.java index 722e2a5c4b9..ccffbcc438d 100644 --- a/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/CentralizedLoggingTest.java +++ b/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/CentralizedLoggingTest.java @@ -26,6 +26,7 @@ import org.eclipse.jetty.logging.impl.TestAppender.LogEvent; public class CentralizedLoggingTest extends TestCase { + private static final String LOGGING_SERVLET_ID = "org.eclipse.jetty.tests.webapp.LoggingServlet"; private XmlConfiguredJetty jetty; private void assertContainsLogEvents(TestAppender capturedEvents, LogEvent[] expectedLogs) @@ -74,14 +75,14 @@ public class CentralizedLoggingTest extends TestCase SimpleRequest.get(jetty,"/dummy-webapp-logging-java/logging"); TestAppender.LogEvent expectedLogs[] = - { new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(log4j) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(log4j) GET requested",null), - new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(slf4j) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(slf4j) GET requested",null), - new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(commons-logging) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(commons-logging) GET requested",null), - new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(java) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(java) GET requested",null) }; + { new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(log4j) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(log4j) GET requested",null), + new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(slf4j) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(slf4j) GET requested",null), + new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(commons-logging) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(commons-logging) GET requested",null), + new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(java) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(java) GET requested",null) }; assertContainsLogEvents(testAppender,expectedLogs); } diff --git a/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/EmbeddedCentralizedLoggingTest.java b/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/EmbeddedCentralizedLoggingTest.java index 0f473ff247c..66746b9818a 100644 --- a/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/EmbeddedCentralizedLoggingTest.java +++ b/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/EmbeddedCentralizedLoggingTest.java @@ -38,6 +38,7 @@ import org.eclipse.jetty.webapp.WebAppContext; */ public class EmbeddedCentralizedLoggingTest extends TestCase { + private static final String LOGGING_SERVLET_ID = "org.eclipse.jetty.tests.webapp.LoggingServlet"; private TestAppender testAppender; private void assertContainsLogEvents(TestAppender capturedEvents, LogEvent[] expectedLogs) @@ -146,14 +147,14 @@ public class EmbeddedCentralizedLoggingTest extends TestCase server.stop(); TestAppender.LogEvent expectedLogs[] = - { new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(log4j) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(log4j) GET requested",null), - new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(slf4j) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(slf4j) GET requested",null), - new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(commons-logging) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(commons-logging) GET requested",null), - new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(java) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(java) GET requested",null) }; + { new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(log4j) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(log4j) GET requested",null), + new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(slf4j) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(slf4j) GET requested",null), + new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(commons-logging) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(commons-logging) GET requested",null), + new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(java) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(java) GET requested",null) }; assertContainsLogEvents(testAppender,expectedLogs); } @@ -169,8 +170,8 @@ public class EmbeddedCentralizedLoggingTest extends TestCase server.stop(); TestAppender.LogEvent expectedLogs[] = - { new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(commons-logging) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(commons-logging) GET requested",null) }; + { new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(commons-logging) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(commons-logging) GET requested",null) }; assertContainsLogEvents(testAppender,expectedLogs); } @@ -186,8 +187,8 @@ public class EmbeddedCentralizedLoggingTest extends TestCase server.stop(); TestAppender.LogEvent expectedLogs[] = - { new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(java) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(java) GET requested",null) }; + { new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(java) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(java) GET requested",null) }; assertContainsLogEvents(testAppender,expectedLogs); } @@ -203,8 +204,8 @@ public class EmbeddedCentralizedLoggingTest extends TestCase server.stop(); TestAppender.LogEvent expectedLogs[] = - { new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(log4j) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(log4j) GET requested",null) }; + { new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(log4j) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(log4j) GET requested",null) }; assertContainsLogEvents(testAppender,expectedLogs); } @@ -220,8 +221,8 @@ public class EmbeddedCentralizedLoggingTest extends TestCase server.stop(); TestAppender.LogEvent expectedLogs[] = - { new LogEvent(null,-1,Severity.DEBUG,"LoggingServlet","LoggingServlet(slf4j) initialized",null), - new LogEvent(null,-1,Severity.INFO,"LoggingServlet","LoggingServlet(slf4j) GET requested",null) }; + { new LogEvent(null,-1,Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(slf4j) initialized",null), + new LogEvent(null,-1,Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(slf4j) GET requested",null) }; assertContainsLogEvents(testAppender,expectedLogs); } diff --git a/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/impl/ConfiguredLoggerTest.java b/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/impl/ConfiguredLoggerTest.java index 3fdc9907248..ea79ac7a267 100644 --- a/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/impl/ConfiguredLoggerTest.java +++ b/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/impl/ConfiguredLoggerTest.java @@ -59,6 +59,63 @@ public class ConfiguredLoggerTest extends TestCase } } + private void assertAppendersById(CentralLoggerConfig logger, String... ids) + { + assertNotNull("Appenders should not be null",logger.getAppenders()); + assertTrue("Should have appenders",logger.getAppenders().size() >= 1); + + List expectedAppenders = new ArrayList(); + List actualAppenders = new ArrayList(); + + for (String id : ids) + { + expectedAppenders.add(id); + } + + for (Appender appender : logger.getAppenders()) + { + actualAppenders.add(appender.getId()); + } + + // Sort + Collections.sort(expectedAppenders); + Collections.sort(actualAppenders); + + boolean same = true; + + // Same Size? + if (expectedAppenders.size() != actualAppenders.size()) + { + same = false; + } + + // Same Content? + for (int i = 0, n = expectedAppenders.size(); i < n; i++) + { + if (!expectedAppenders.get(i).equals(actualAppenders.get(i))) + { + same = false; + break; + } + } + + if (!same) + { + System.out.println("/* Actual */"); + for (String id : actualAppenders) + { + System.out.println(id); + } + System.out.println("/* Expected */"); + for (String id : expectedAppenders) + { + System.out.println(id); + } + fail("Not the same appender id list."); + } + + } + private void assertSeverityLevel(CentralLoggerConfig logger, Severity severity) { assertEquals("Severity",severity,logger.getLevel()); @@ -184,4 +241,42 @@ public class ConfiguredLoggerTest extends TestCase assertSeverityLevel(implLogger,Severity.WARN); assertAppenders(implLogger,ConsoleAppender.class,TestAppender.class); } + + public void testGetConfiguredLoggerNegativeAppender() throws IOException + { + File testLoggingDir = new File(MavenTestingUtils.getTargetTestingDir(this),"logs"); + testLoggingDir.mkdirs(); + + System.setProperty("test.dir",testLoggingDir.getAbsolutePath()); + + Properties props = new Properties(); + props.setProperty("root.level","DEBUG"); + props.setProperty("root.appenders","console,rollLog"); + props.setProperty("logger.AUDIT.level","INFO"); + props.setProperty("logger.AUDIT.appenders","-rollLog,auditLog"); + + props.setProperty("appender.console.class",ConsoleAppender.class.getName()); + props.setProperty("appender.rollLog.class",RollingFileAppender.class.getName()); + props.setProperty("appender.rollLog.filename","${test.dir}/rolling.log"); + props.setProperty("appender.auditLog.class",RollingFileAppender.class.getName()); + props.setProperty("appender.auditLog.filename","${test.dir}/audit.log"); + + CentralLoggerConfig root = CentralLoggerConfig.load(props); + assertNotNull("Root Logger should not be null",root); + assertEquals("Root Logger.name",Logger.ROOT_LOGGER_NAME,root.getName()); + assertSeverityLevel(root,Severity.DEBUG); + assertAppendersById(root,"console","rollLog"); + + CentralLoggerConfig jettyLogger = root.getConfiguredLogger("AUDIT"); + assertNotNull("Jetty Logger should not be null",jettyLogger); + assertEquals("Jetty Logger.name","AUDIT",jettyLogger.getName()); + assertSeverityLevel(jettyLogger,Severity.INFO); + assertAppendersById(jettyLogger,"console","auditLog"); + + CentralLoggerConfig implLogger = root.getConfiguredLogger("AUDIT.some.thing.else"); + assertNotNull("Jetty Logging Impl Logger should not be null",implLogger); + assertEquals("Jetty Logging Impl Logger.name","AUDIT.some.thing.else",implLogger.getName()); + assertSeverityLevel(implLogger,Severity.INFO); + assertAppendersById(implLogger,"console","auditLog"); + } } diff --git a/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/impl/TestAppender.java b/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/impl/TestAppender.java index f6148d63114..f61fd022ce8 100644 --- a/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/impl/TestAppender.java +++ b/jetty-centralized-logging/src/test/java/org/eclipse/jetty/logging/impl/TestAppender.java @@ -56,13 +56,25 @@ public class TestAppender implements Appender } private List events = new ArrayList(); + private String id; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } public void append(String date, int ms, Severity severity, String name, String message, Throwable t) { - if (name.equals("log")) // standard jetty logger + if (name.equals("org.eclipse.jetty.util.log")) // standard jetty logger { if (t != null) { + // Still interested in seeing throwables (HACK) t.printStackTrace(System.err); } return; // skip storing it.