logback-dev
Threads by month
- ----- 2025 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
August 2009
- 13 participants
- 104 discussions

svn commit: r2430 - logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling
by noreply.ceki@qos.ch 09 Aug '09
by noreply.ceki@qos.ch 09 Aug '09
09 Aug '09
Author: ceki
Date: Sun Aug 9 20:15:34 2009
New Revision: 2430
Modified:
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java
Log:
- rewording
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java Sun Aug 9 20:15:34 2009
@@ -109,7 +109,7 @@
doRollover(randomOutputDir + "/%d{" + DAILY_CROLOLOG_DATE_PATTERN
+ "}/clean.txt.zip", MILLIS_IN_DAY, 8, 8 * 3);
int expectedDirMin = 9 + slashCount;
- int expectDirMax = expectedDirMin + 1 + 1; // plus 1 of overllaping into a
+ int expectDirMax = expectedDirMin + 1 + 1; // plus 1 of stepping into a
// new month, and another 1 into
// a new year
expectedFileAndDirCount(9, expectedDirMin, expectDirMax);
1
0

svn commit: r2429 - logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling
by noreply.ceki@qos.ch 09 Aug '09
by noreply.ceki@qos.ch 09 Aug '09
09 Aug '09
Author: ceki
Date: Sun Aug 9 20:15:08 2009
New Revision: 2429
Modified:
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java
Log:
take into account stepping into a new month or a new year
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java Sun Aug 9 20:15:08 2009
@@ -104,10 +104,15 @@
@Test
public void dailyCronologRollover() throws Exception {
+ System.out.println(randomOutputDir);
slashCount = computeSlashCount(DAILY_CROLOLOG_DATE_PATTERN);
doRollover(randomOutputDir + "/%d{" + DAILY_CROLOLOG_DATE_PATTERN
+ "}/clean.txt.zip", MILLIS_IN_DAY, 8, 8 * 3);
- check(expectedCountWithDirs(8));
+ int expectedDirMin = 9 + slashCount;
+ int expectDirMax = expectedDirMin + 1 + 1; // plus 1 of overllaping into a
+ // new month, and another 1 into
+ // a new year
+ expectedFileAndDirCount(9, expectedDirMin, expectDirMax);
}
@Test
@@ -174,8 +179,22 @@
rfa.stop();
}
- void findAllInFolderRecursivelyByStringContains(File dir, List<File> fileList,
- final String pattern) {
+ void findAllFoldersRecursively(File dir, List<File> fileList) {
+ if (dir.isDirectory()) {
+ File[] match = dir.listFiles(new FileFilter() {
+ public boolean accept(File f) {
+ return (f.isDirectory());
+ }
+ });
+ for (File f : match) {
+ fileList.add(f);
+ findAllFoldersRecursively(f, fileList);
+ }
+ }
+ }
+
+ void findAllInFolderRecursivelyByStringContains(File dir,
+ List<File> fileList, final String pattern) {
if (dir.isDirectory()) {
File[] match = dir.listFiles(new FileFilter() {
public boolean accept(File f) {
@@ -241,12 +260,26 @@
assertEquals(expectedCount, fileList.size());
}
+ void expectedFileAndDirCount(int expectedFileAndDirCount,
+ int expectedDirCountMin, int expectedDirCountMax) {
+ File dir = new File(randomOutputDir);
+ List<File> fileList = new ArrayList<File>();
+ findFilesInFolderRecursivelyByPatterMatch(dir, fileList, "clean");
+
+ List<File> dirList = new ArrayList<File>();
+ findAllFoldersRecursively(dir, dirList);
+ assertTrue("expectedDirCountMin=" + expectedDirCountMin
+ + ", expectedDirCountMax=" + expectedDirCountMax + " actual value="
+ + dirList.size(), expectedDirCountMin <= dirList.size()
+ && dirList.size() <= expectedDirCountMax);
+ }
+
void checkPatternCompliance(int expectedClassCount, String regex) {
File dir = new File(randomOutputDir);
List<File> fileList = new ArrayList<File>();
findFilesInFolderRecursivelyByPatterMatch(dir, fileList, regex);
- System.out.println("regex="+regex);
- System.out.println("fileList="+fileList);
+ System.out.println("regex=" + regex);
+ System.out.println("fileList=" + fileList);
Set<String> set = groupByClass(fileList, regex);
assertEquals(expectedClassCount, set.size());
}
@@ -255,13 +288,12 @@
File dir = new File(randomOutputDir);
List<File> fileList = new ArrayList<File>();
findFoldersInFolderRecursively(dir, fileList);
- for(File f: fileList) {
+ for (File f : fileList) {
assertTrue(f.list().length >= 1);
}
assertEquals(expectedClassCount, fileList.size());
}
-
Set<String> groupByClass(List<File> fileList, String regex) {
Pattern p = Pattern.compile(regex);
Set<String> set = new HashSet<String>();
1
0

svn commit: r2428 - logback/trunk/logback-examples/src/main/java/chapter4/conf
by noreply.ceki@qos.ch 09 Aug '09
by noreply.ceki@qos.ch 09 Aug '09
09 Aug '09
Author: ceki
Date: Sun Aug 9 19:54:56 2009
New Revision: 2428
Added:
logback/trunk/logback-examples/src/main/java/chapter4/conf/logback-timestamp.xml
Modified:
logback/trunk/logback-examples/src/main/java/chapter4/conf/logback-fileAppender.xml
Log:
- added a new config file
Modified: logback/trunk/logback-examples/src/main/java/chapter4/conf/logback-fileAppender.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter4/conf/logback-fileAppender.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter4/conf/logback-fileAppender.xml Sun Aug 9 19:54:56 2009
@@ -4,7 +4,7 @@
<File>testFile.log</File>
<Append>true</Append>
- <layout class="ch.qos.logback.classic.PatternLayout">
+ <layout>
<Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
</layout>
</appender>
Added: logback/trunk/logback-examples/src/main/java/chapter4/conf/logback-timestamp.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter4/conf/logback-timestamp.xml Sun Aug 9 19:54:56 2009
@@ -0,0 +1,20 @@
+<configuration>
+
+ <!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under
+ the key "bySecond" into the logger context. This value will be
+ available to all subsequent configuration elements. -->
+ <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>
+
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <!-- use the previously created timestamp to create a uniquely
+ named log file -->
+ <File>log-${bySecond}.txt</File>
+ <layout>
+ <Pattern>%logger{35} - %msg%n</Pattern>
+ </layout>
+ </appender>
+
+ <root level="debug">
+ <appender-ref ref="FILE" />
+ </root>
+</configuration>
1
0

[JIRA] Created: (LBCORE-91) Add new TriggeringPolicy class to cause one rollover at the start of each run
by Rick Beton (JIRA) 09 Aug '09
by Rick Beton (JIRA) 09 Aug '09
09 Aug '09
Add new TriggeringPolicy class to cause one rollover at the start of each run
-----------------------------------------------------------------------------
Key: LBCORE-91
URL: http://jira.qos.ch/browse/LBCORE-91
Project: logback-core
Issue Type: New Feature
Components: Appender
Affects Versions: 0.9.15
Environment: -
Reporter: Rick Beton
Assignee: Logback dev list
Priority: Minor
A new TriggeringPolicy will cause the logfile to rollover once at startup when used with FixedWindowRollingPolicy. This is useful during development so that the logfiles of recent runs are still available. Here is a candidate implementation. Note that
* <append>true</append> is required - otherwise the previous file is overwritten before rollover happens, so rollover results in a useless list of empty files.
* the documentation would need to warn users of the effect of running multiple applications concurrently (i.e. concurrent operating system processes) with the same logfiles. This applies even without the suggested feature.
package ch.qos.logback.core.rolling;
import java.io.File;
import ch.qos.logback.core.rolling.TriggeringPolicyBase;
/**
* SimpleStartupTriggeringPolicy triggers a rollover once at startup only. This
* is useful for preserving older logfiles during development.
*
* @author Rick Beton
*/
public final class SimpleStartupTriggeringPolicy<E> extends TriggeringPolicyBase<E> {
private boolean fired = false;
public SimpleStartupTriggeringPolicy () {
// does nothing
}
public boolean isTriggeringEvent( final File activeFile, final E event ) {
final boolean result = !fired && (activeFile.length() > 0);
fired = true;
if (result) {
addInfo( "Triggering rollover for " + activeFile );
}
return result;
}
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
3
4

09 Aug '09
Author: ceki
Date: Sun Aug 9 19:51:56 2009
New Revision: 2427
Added:
logback/trunk/logback-classic/src/test/input/joran/timestamp.xml
logback/trunk/logback-classic/src/test/input/joran/unique.xml
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/rolling/UniqueFileTest.java
Modified:
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java
logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/rolling/PackageTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java
logback/trunk/logback-site/src/site/pages/manual/appenders.html
logback/trunk/logback-site/src/site/pages/manual/configuration.html
logback/trunk/logback-site/src/site/pages/news.html
Log:
- document and test the <timestamp> action. This fixes LBCORE-91.
Added: logback/trunk/logback-classic/src/test/input/joran/timestamp.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/input/joran/timestamp.xml Sun Aug 9 19:51:56 2009
@@ -0,0 +1,4 @@
+<configuration>
+ <timestamp key="testTimestamp" datePattern="yyyy-MM"/>
+</configuration>
+
\ No newline at end of file
Added: logback/trunk/logback-classic/src/test/input/joran/unique.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/input/joran/unique.xml Sun Aug 9 19:51:56 2009
@@ -0,0 +1,15 @@
+<configuration>
+ <timestamp key="dayTimestamp" datePattern="yyyyMMdd'T'HHmmss" />
+
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <File>target/test-output/TS_${dayTimestamp}log.txt</File>
+ <Append>false</Append>
+ <layout>
+ <Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
+ </layout>
+ </appender>
+
+ <root level="debug">
+ <appender-ref ref="FILE" />
+ </root>
+</configuration>
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java Sun Aug 9 19:51:56 2009
@@ -15,6 +15,8 @@
import java.io.File;
import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import org.junit.Test;
import org.slf4j.MDC;
@@ -46,7 +48,7 @@
}
@Test
- public void testSimpleList() throws JoranException {
+ public void simpleList() throws JoranException {
configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/simpleList.xml");
Logger logger = loggerContext.getLogger(this.getClass().getName());
@@ -61,7 +63,7 @@
}
@Test
- public void testLevel() throws JoranException {
+ public void level() throws JoranException {
configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/simpleLevel.xml");
ListAppender listAppender = (ListAppender) root.getAppender("LIST");
assertEquals(0, listAppender.list.size());
@@ -71,7 +73,7 @@
}
@Test
- public void testRootLoggerLevelSettingBySystemProperty()
+ public void rootLoggerLevelSettingBySystemProperty()
throws JoranException {
String propertyName = "logback.level";
@@ -88,7 +90,7 @@
}
@Test
- public void testLoggerLevelSettingBySystemProperty() throws JoranException {
+ public void loggerLevelSettingBySystemProperty() throws JoranException {
String propertyName = "logback.level";
System.setProperty(propertyName, "DEBUG");
@@ -104,7 +106,7 @@
}
@Test
- public void testStatusListener() throws JoranException {
+ public void statusListener() throws JoranException {
configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/statusListener.xml");
// StatusPrinter.print(loggerContext);
}
@@ -117,7 +119,7 @@
}
@Test
- public void testEval() throws JoranException {
+ public void eval() throws JoranException {
configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/callerData.xml");
String msg = "hello world";
@@ -136,7 +138,7 @@
}
@Test
- public void testTurboFilter() throws JoranException {
+ public void turboFilter() throws JoranException {
// Although this test uses turbo filters, it only checks
// that Joran can see the xml element and create
// and place the relevant object correctly.
@@ -269,4 +271,19 @@
assertTrue(checker.isErrorFree());
assertTrue(checker.containsMatch("Resetting and reconfiguring context"));
}
+
+ @Test
+ public void timestamp() throws JoranException, IOException, InterruptedException {
+
+ String configFileAsStr = TeztConstants.TEST_DIR_PREFIX
+ + "input/joran/timestamp.xml";
+ configure(configFileAsStr);
+
+ String r = loggerContext.getProperty("testTimestamp");
+ assertNotNull(r);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
+ String expected = sdf.format(new Date());
+ assertEquals("expected \""+expected+"\" but got "+r, expected, r);
+ }
+
}
Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/rolling/PackageTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/rolling/PackageTest.java (original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/rolling/PackageTest.java Sun Aug 9 19:51:56 2009
@@ -13,8 +13,7 @@
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
-
@RunWith(Suite.class)
-@SuiteClasses( { TimeBasedRollingWithConfigFileTest.class})
+@SuiteClasses( { UniqueFileTest.class, TimeBasedRollingWithConfigFileTest.class })
public class PackageTest {
}
\ No newline at end of file
Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/rolling/UniqueFileTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/rolling/UniqueFileTest.java Sun Aug 9 19:51:56 2009
@@ -0,0 +1,61 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2009, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.classic.rolling;
+
+import static org.junit.Assert.assertTrue;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.junit.Test;
+
+import ch.qos.logback.classic.ClassicTestConstants;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.joran.JoranConfigurator;
+import ch.qos.logback.core.joran.spi.JoranException;
+import ch.qos.logback.core.rolling.ScaffoldingForRollingTests;
+import ch.qos.logback.core.status.StatusChecker;
+import ch.qos.logback.core.util.CoreTestConstants;
+
+/**
+ * Test that we can create time-stamped log files with the help of
+ * the <timestamp> element in configuration files.
+ *
+ * @author Ceki Gülcü
+ *
+ */
+public class UniqueFileTest {
+
+ LoggerContext lc = new LoggerContext();
+ Logger logger = lc.getLogger(this.getClass());
+
+
+ void loadConfig(String confifFile) throws JoranException {
+ JoranConfigurator jc = new JoranConfigurator();
+ jc.setContext(lc);
+ jc.doConfigure(confifFile);
+ }
+
+ @Test
+ public void basic() throws Exception {
+ loadConfig(ClassicTestConstants.JORAN_INPUT_PREFIX + "/unique.xml");
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
+ String timestamp = sdf.format(new Date());
+
+ StatusChecker sc = new StatusChecker(lc);
+ assertTrue(sc.isErrorFree());
+
+ Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME);
+ root.info("hello");
+
+ ScaffoldingForRollingTests.existenceCheck(CoreTestConstants.OUTPUT_DIR_PREFIX+"TS_"+timestamp+"log.txt");
+ }
+}
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java Sun Aug 9 19:51:56 2009
@@ -43,12 +43,12 @@
public void doTest(String filename) throws Exception {
// rule store is case insensitve
- rulesMap.put(new Pattern("x/INC"), new IncAction());
+ rulesMap.put(new Pattern("x/inc"), new IncAction());
- TrivialConfigurator gc = new TrivialConfigurator(rulesMap);
+ TrivialConfigurator trivialConfigurator = new TrivialConfigurator(rulesMap);
- gc.setContext(context);
- gc.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + "input/joran/"
+ trivialConfigurator.setContext(context);
+ trivialConfigurator.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + "input/joran/"
+ filename);
}
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/action/PropertyActionTest.java Sun Aug 9 19:51:56 2009
@@ -1,3 +1,12 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2009, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
package ch.qos.logback.core.joran.action;
import static org.junit.Assert.assertEquals;
@@ -16,25 +25,29 @@
import ch.qos.logback.core.util.CoreTestConstants;
import ch.qos.logback.core.util.StatusPrinter;
+/**
+ * Test {@link PropertyAction}.
+ * @author Ceki Gülcü
+ */
public class PropertyActionTest {
Context context;
InterpretationContext ec;
- PropertyAction spAction;
+ PropertyAction propertyAction;
DummyAttributes atts = new DummyAttributes();
@Before
public void setUp() throws Exception {
context = new ContextBase();
ec = new InterpretationContext(context, null);
- spAction = new PropertyAction();
- spAction.setContext(context);
+ propertyAction = new PropertyAction();
+ propertyAction.setContext(context);
}
@After
public void tearDown() throws Exception {
context = null;
- spAction = null;
+ propertyAction = null;
atts = null;
}
@@ -42,7 +55,7 @@
public void nameValuePair() {
atts.setValue("name", "v1");
atts.setValue("value", "work");
- spAction.begin(ec, null, atts);
+ propertyAction.begin(ec, null, atts);
assertEquals("work", ec.getProperty("v1"));
}
@@ -51,14 +64,14 @@
context.putProperty("w", "wor");
atts.setValue("name", "v1");
atts.setValue("value", "${w}k");
- spAction.begin(ec, null, atts);
+ propertyAction.begin(ec, null, atts);
assertEquals("work", ec.getProperty("v1"));
}
@Test
public void noValue() {
atts.setValue("name", "v1");
- spAction.begin(ec, null, atts);
+ propertyAction.begin(ec, null, atts);
assertEquals(1, context.getStatusManager().getCount());
assertTrue(checkError());
}
@@ -66,14 +79,14 @@
@Test
public void noName() {
atts.setValue("value", "v1");
- spAction.begin(ec, null, atts);
+ propertyAction.begin(ec, null, atts);
assertEquals(1, context.getStatusManager().getCount());
assertTrue(checkError());
}
@Test
public void noAttributes() {
- spAction.begin(ec, null, atts);
+ propertyAction.begin(ec, null, atts);
assertEquals(1, context.getStatusManager().getCount());
assertTrue(checkError());
StatusPrinter.print(context);
@@ -83,7 +96,7 @@
public void testFileNotLoaded() {
atts.setValue("file", "toto");
atts.setValue("value", "work");
- spAction.begin(ec, null, atts);
+ propertyAction.begin(ec, null, atts);
assertEquals(1, context.getStatusManager().getCount());
assertTrue(checkError());
}
@@ -92,7 +105,7 @@
public void testLoadFileWithPrerequisiteSubsitution() {
context.putProperty("STEM", CoreTestConstants.TEST_DIR_PREFIX + "input/joran");
atts.setValue("file", "${STEM}/propertyActionTest.properties");
- spAction.begin(ec, null, atts);
+ propertyAction.begin(ec, null, atts);
assertEquals("tata", ec.getProperty("v1"));
assertEquals("toto", ec.getProperty("v2"));
}
@@ -100,7 +113,7 @@
@Test
public void testLoadFile() {
atts.setValue("file", CoreTestConstants.TEST_DIR_PREFIX + "input/joran/propertyActionTest.properties");
- spAction.begin(ec, null, atts);
+ propertyAction.begin(ec, null, atts);
assertEquals("tata", ec.getProperty("v1"));
assertEquals("toto", ec.getProperty("v2"));
}
@@ -108,7 +121,7 @@
@Test
public void testLoadResource() {
atts.setValue("resource", "asResource/joran/propertyActionTest.properties");
- spAction.begin(ec, null, atts);
+ propertyAction.begin(ec, null, atts);
assertEquals("tata", ec.getProperty("r1"));
assertEquals("toto", ec.getProperty("r2"));
}
@@ -117,7 +130,7 @@
public void testLoadResourceWithPrerequisiteSubsitution() {
context.putProperty("STEM", "asResource/joran");
atts.setValue("resource", "${STEM}/propertyActionTest.properties");
- spAction.begin(ec, null, atts);
+ propertyAction.begin(ec, null, atts);
assertEquals("tata", ec.getProperty("r1"));
assertEquals("toto", ec.getProperty("r2"));
}
@@ -125,7 +138,7 @@
@Test
public void testLoadNotPossible() {
atts.setValue("file", "toto");
- spAction.begin(ec, null, atts);
+ propertyAction.begin(ec, null, atts);
assertEquals(1, context.getStatusManager().getCount());
assertTrue(checkFileErrors());
}
Modified: logback/trunk/logback-site/src/site/pages/manual/appenders.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/appenders.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/appenders.html Sun Aug 9 19:51:56 2009
@@ -601,10 +601,57 @@
<p class="source">java chapter4.ConfigurationTester src/main/java/chapter4/conf/logback-fileAppender.xml</p>
-
<h3>
- <a name="RollingFileAppender"
- href="#RollingFileAppender">RollingFileAppender</a></h3>
+ <a name="uniquelyNamed" href="#uniquelyNamed">Uniquely named
+ files (by timestamp)</a>
+ </h3>
+
+ <p>During the application development phase or in the case of
+ short-lived applications, e.g. batch applications, it is desriable
+ to create a new log file at each new application launch. This is
+ fairly easy to do with the help of the <code><timestamp></code>
+ element. Here's an example.</p>
+
+
+ <em>Example 4.<span class="autoEx"/>: Uniquely named FileAppender configuration by timestamp (logback-examples/src/main/java/chapter4/conf/logback-timestamp.xml)</em>
+ <pre class="prettyprint source"><configuration>
+
+ <!-- Insert the current time formatted as "yyyyMMdd'T'HHmmss" under
+ the key "bySecond" into the logger context. This value will be
+ available to all subsequent configuration elements. -->
+ <b><timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/></b>
+
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <!-- use the previously created timestamp to create a uniquely
+ named log file -->
+ <File><b>log-${bySecond}.txt</b></File>
+ <layout>
+ <Pattern>%logger{35} - %msg%n</Pattern>
+ </layout>
+ </appender>
+
+ <root level="debug">
+ <appender-ref ref="FILE" />
+ </root>
+</configuration></pre>
+
+
+ <p>The timestamp element takes two attributes <span
+ class="attr">key</span> and <span
+ class="attr">datePattern</span>. The <span class="attr">key</span>
+ attribute is the name of the key under which the timestamp will be
+ available to subsequent configuration elements <a
+ href="configuration.html#variableSubstitution">as a
+ variable</a>. The <span class="attr">datePattern</span> attribute
+ denoted the date pattern used to convert the current time (at which
+ the configuration file is parsed) into a string. The date pattern
+ should follow the conventions defined in <a
+ href="http://java.sun.com/j2se/1.4.2/docs/api/java/text/SimpleDateFormat.html">SimpleDateFormat</a>.
+ </p>
+
+ <h3>
+ <a name="RollingFileAppender" href="#RollingFileAppender">RollingFileAppender</a>
+ </h3>
<p><a
href="../xref/ch/qos/logback/core/rolling/RollingFileAppender.html"><code>RollingFileAppender</code></a>
Modified: logback/trunk/logback-site/src/site/pages/manual/configuration.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/configuration.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/configuration.html Sun Aug 9 19:51:56 2009
@@ -111,7 +111,8 @@
</p>
- <p>Assuming the <em>logback-test.xml</em> file is placed under
+ <p>If you are using Maven and assuming the
+ <em>logback-test.xml</em> file is placed under
<em>src/test/resources</em> folder, Maven will ensure that it
won't be included in the artifact produced. Thus, you can use a
different configuration file, namely <em>logback-test.xml</em>
@@ -176,13 +177,16 @@
refer to the <a href="../setup.html">setup page</a> for further
details.
</p>
-
+
+
<p>Assuming the configuration files <em>logback-test.xml</em> or
- <em>logback.xml</em> could not be found, logback will default to a
- minimal configuration mentioned earlier. This configuration is
- hardwired to attaching a <code>ConsoleAppender</code> to the root
- logger. The output is formatted using a
+ <em>logback.xml</em> are not present, logback will default to
+ invoking <a
+ href="../xref/ch/qos/logback/classic/BasicConfigurator.html"><code>BasicConfigurator</code></a>
+ which will set up a minimal configuration. This minimal
+ configuration consists of a <code>ConsoleAppender</code> attached
+ to the root logger. The output is formatted using a
<code>PatternLayout</code> set to the pattern <em>%d{HH:mm:ss.SSS}
[%thread] %-5level %logger{36} - %msg%n</em>. Moreover, by default
the root logger is assigned to the <code>DEBUG</code> level.
@@ -192,22 +196,31 @@
should be similar to:
</p>
-<div class="source"><pre>16:06:09.031 [main] INFO chapter3.MyApp1 - Entering application.
+ <p class="source">16:06:09.031 [main] INFO chapter3.MyApp1 - Entering application.
16:06:09.046 [main] DEBUG chapter3.Foo - Did it again!
-16:06:09.046 [main] INFO chapter3.MyApp1 - Exiting application.</pre></div>
+16:06:09.046 [main] INFO chapter3.MyApp1 - Exiting application.</p>
- <p>The <code>MyApp1</code> application links to logback via
- calls <code>org.slf4j.LoggerFactory</code> and
+ <div class="highlight">
+ <p>
+ Except code that configures logback (if such code exists)
+ client code does not need to depend on logback. Applications
+ that use logback as their logging framework will have a
+ compile-time dependency on SLF4J but not logback.
+ </p>
+ </div>
+
+ <p>The <code>MyApp1</code> application links to logback via calls
+ <code>org.slf4j.LoggerFactory</code> and
<code>org.slf4j.Logger</code> classes, retrieve the loggers it
wishes to use, and chugs on. Note that the only dependence of the
<code>Foo</code> class on logback are through
<code>org.slf4j.LoggerFactory</code> and
<code>org.slf4j.Logger</code> imports. Except code that configures
logback (if such code exists) client code does not need to depend
- on logback. Given that SLF4J permits the use of any implementation
- under its abstraction layer, it is rather easy to migrate large
- bodies of code from one logging system to another.
+ on logback. Given that SLF4J permits the use of any logging
+ framework under its abstraction layer, it is rather easy to migrate
+ large bodies of code from one logging framework to another.
</p>
<h3>Automatic configuration with <em>logback-test.xml</em> or
@@ -242,15 +255,24 @@
directory accessible from the class path. Running the <em>MyApp1</em>
application should give identical results to its previous run.</p>
- <p>If and only if there are warnings or errors during the parsing
- of the configuration file, logback will automatically print status
- data on the console. In the absence of warnings or errors, if you
- still wish to inspect logback's internal status, then you can
- instruct logback to print status data by invoking the
- <code>print()</code> of the <code>StatusPrinter</code> class. The
- <em>MyApp2</em> application shown below is identical to
- <em>MyApp1</em> except the addition of two lines of code for
- printing internal status data.</p>
+ <h4>Automatic printing of status messages in case of warning or errors</h4>
+
+ <div class="highlight">
+ <p>If warning or errors occur during the parsing of the
+ configuration file, logback will automatically print its internal
+ status messages on the console.
+ </p>
+ </div>
+
+ <p>If warnings or errors occur during the parsing of the
+ configuration file, logback will automatically print status data on
+ the console. In the absence of warnings or errors, if you still
+ wish to inspect logback's internal status, then you can instruct
+ logback to print status data by invoking the <code>print()</code>
+ of the <code>StatusPrinter</code> class. The <em>MyApp2</em>
+ application shown below is identical to <em>MyApp1</em> except the
+ addition of two lines of code for printing internal status
+ data.</p>
<em>Example 3.<span class="autoEx"/>: Print logback's internal status information
<a
@@ -295,8 +317,8 @@
configuration file, as shown below. Please note that this <span
class="attr">debug</span> attribute relates only to the status
data. It does <em>not</em> affect logback's configuration
- otherwise, in particular with respect to logger levels. (Put
- differently, no, the root logger will <em>not</em> be set to
+ otherwise, in particular with respect to logger levels. (If you are
+ asking, no, the root logger will <em>not</em> be set to
<code>DEBUG</code>.)
</p>
@@ -357,6 +379,13 @@
<h3><a name="autoScan" href="#autoScan">Automatically reloading
configuration file upon modification</a></h3>
+ <div class="highlight">
+ <p>Logback-classic can scan for changes in its configuration file
+ and automatically reconfigure itself when the said configuration
+ file changes.
+ </p>
+ </div>
+
<p>If instructed to do so, logback-classic will scan for changes in
its configuration file and automatically reconfigure itself when
the said configuration file changes. In order to instruct
@@ -622,6 +651,34 @@
alt="basic Syntax" title="Basic configuration file structure"/>
</p>
+
+ <div class="highlight">
+ <p>If you are unsure which case to use for a given tag name, just
+ follow the camelCase convention which should usually be
+ corrrect.</p>
+ </div>
+
+ <p>As of logback version 0.9.17, tag names pertaining to explicit
+ rules are case insensitive. For example, both
+ <code><logger></code>, <code><Logger></code> and
+ <code><LOGGER></code> are valid configuration elements and will
+ be interpreted in the same way. Note that XML well-formedness rules
+ still apply, if you open a tag as <code><xyz></code> you must
+ close it as <code></xyz></code>, <code></XyZ></code> will not
+ work. As for <a href="onJoran.html#implicit">implicit rules</a>, tag
+ names are case sensitive except for the first letter. Thus,
+ <code><xyz></code> and <code><Xyz></code> are equivalent but
+ not <code><xYz></code>. Implicit rules usually follow the <a
+ href="http://en.wikipedia.org/wiki/CamelCase">camel case</a>
+ convention, common in the Java world. Since it is not trivially easy
+ tell when a tag is associated with an explicit action and when it is
+ associated with an implicit action, it is not trivial to say whether
+ an XML tag is totally case-insensitive or case-insensitive with
+ respect to the first letter. If you are unsure which case to use for
+ a given tag name, just follow the camelCase convention which should
+ usually be correct.
+ </p>
+
<h4>Configuring Loggers, or the <code><logger></code> element</h4>
<p>A logger is configured using the <code>logger</code> element. A
Modified: logback/trunk/logback-site/src/site/pages/news.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/news.html (original)
+++ logback/trunk/logback-site/src/site/pages/news.html Sun Aug 9 19:51:56 2009
@@ -38,6 +38,24 @@
reported by Roland Klein and independently by Didier Besset.
</p>
+ <p>In configuration files, all tags names associated with explicit
+ actions are now case-insensitive. This should diminish
+ case-related errors users may make when writing configuration
+ files. Tag names associated with implicit actions which are
+ closely linked to the actual Java class being configured, still
+ need to follow the camelCase convention. If you are unsure which
+ case to use for a given tag name, just follow the camelCase
+ convention for tag names which should be correct in most
+ cases. </p>
+
+ <p>It is now possible to create <a
+ href="manual/appenders.html#uniquelyNamed">uniquely named files by
+ timestamp</a>. Such files are appropriate for log files associated
+ with batch applications. This enhancement fulfills <a
+ href="http://jira.qos.ch/browse/LBCORE-91">LBCORE-91</a> as
+ requested by Rick Beton and Szel Zoltan.
+ </p>
+
<p>Append mode is now mandatory in
<code>RollingFileAppender</code>. This was already the default and
truncation mode is unreasonable in most cases. For example, in
@@ -50,10 +68,10 @@
reported by Valery Shorin.</p>
- <p>The TimeBasedTriggeringPolicy has been heavily refactored. It
- is now possible to trigger rolling by <a
- href="">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXtime as well as by
- size</a>, fixing <a
+ <p>The <code>TimeBasedTriggeringPolicy</code> has been heavily
+ refactored. It is now possible to trigger rolling simultaenously
+ by <a href="manual/appenders.html#SizeAndTimeBasedFNATP">time and
+ by size</a>, fixing <a
href="http://jira.qos.ch/browse/LBCORE-61">LBCORE-61</a>.
</p>
1
0

09 Aug '09
Support for crolonog type rolling
---------------------------------
Key: LBCORE-111
URL: http://jira.qos.ch/browse/LBCORE-111
Project: logback-core
Issue Type: Improvement
Components: Appender
Reporter: Ceki Gulcu
Assignee: Ceki Gulcu
Add support for cronolog type logging file separation. For example:
TransferLog "|/usr/sbin/cronolog /web/logs/%Y/%m/%d/access.log"
ErrorLog "|/usr/sbin/cronolog /web/logs/%Y/%m/%d/errors.log"
This allows each log file to be separated by year, month, etc.
See http://cronolog.org/features.html for details.
Interestingly enough, TimeBasedRollingPolicy already supports this feature. It's just not tested nor documented.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
2

[JIRA] Created: (LBCORE-76) Joran patterns should be case insensitive
by Ceki Gulcu (JIRA) 09 Aug '09
by Ceki Gulcu (JIRA) 09 Aug '09
09 Aug '09
Joran patterns should be case insensitive
-----------------------------------------
Key: LBCORE-76
URL: http://jira.qos.ch/browse/LBCORE-76
Project: logback-core
Issue Type: Improvement
Components: Joran
Affects Versions: 0.9.12
Reporter: Ceki Gulcu
Assignee: Logback dev list
At present time, joran patterns are case sensitive. However, implicit actions are case insensitive. For coherence, joran patterns should be case insensitive.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.qos.ch/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
1
3

svn commit: r2426 - in logback/trunk/logback-core/src: main/java/ch/qos/logback/core/joran main/java/ch/qos/logback/core/joran/action main/java/ch/qos/logback/core/joran/spi test/java/ch/qos/logback/core/joran test/java/ch/qos/logback/core/joran/spi
by noreply.ceki@qos.ch 09 Aug '09
by noreply.ceki@qos.ch 09 Aug '09
09 Aug '09
Author: ceki
Date: Sun Aug 9 13:54:23 2009
New Revision: 2426
Added:
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinator.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinatorTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleRuleStoreTest.java
- copied, changed from r2425, /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleStoreTest.java
Removed:
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleStoreTest.java
Modified:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/TimestampAction.java
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Pattern.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java
logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java
Log:
- Explicit patterns in Joran are now case insensitive.
The following config files will be interpreted identically:
First config file:
<configuration>
<logger>...</logger>
</configuration>
Second config file:
<CONFIGURAtion>
<loGGer>...</loGGer>
</CONFIGURAtion>
This addresses http://jira.qos.ch/browse/LBCORE-76
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConfiguratorBase.java Sun Aug 9 13:54:23 2009
@@ -25,6 +25,7 @@
import ch.qos.logback.core.joran.action.ParamAction;
import ch.qos.logback.core.joran.action.PropertyAction;
import ch.qos.logback.core.joran.action.StatusListenerAction;
+import ch.qos.logback.core.joran.action.TimestampAction;
import ch.qos.logback.core.joran.spi.InterpretationContext;
import ch.qos.logback.core.joran.spi.Interpreter;
import ch.qos.logback.core.joran.spi.Pattern;
@@ -59,6 +60,9 @@
rs.addRule(new Pattern("configuration/substitutionProperty"),
new PropertyAction());
+ rs.addRule(new Pattern("configuration/timestamp"),
+ new TimestampAction());
+
// the contextProperty pattern is deprecated. It is undocumented
// and will be dropped in future versions of logback
rs.addRule(new Pattern("configuration/contextProperty"),
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/Action.java Sun Aug 9 13:54:23 2009
@@ -35,6 +35,7 @@
public abstract class Action extends ContextAwareBase {
public static final String NAME_ATTRIBUTE = "name";
+ public static final String KEY_ATTRIBUTE = "key";
public static final String VALUE_ATTRIBUTE = "value";
public static final String FILE_ATTRIBUTE = "file";
public static final String CLASS_ATTRIBUTE = "class";
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/TimestampAction.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/TimestampAction.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/TimestampAction.java Sun Aug 9 13:54:23 2009
@@ -1,3 +1,12 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2009, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
package ch.qos.logback.core.joran.action;
import java.text.SimpleDateFormat;
@@ -9,32 +18,43 @@
import ch.qos.logback.core.joran.spi.InterpretationContext;
import ch.qos.logback.core.util.OptionHelper;
+/**
+ * Given a key and a date-and-time pattern, puts a property to the context, with
+ * the specified key and value equal to the current time in the format
+ * corresponding to the specified date-and-time pattern.
+ *
+ * @author Ceki Gülcü
+ *
+ */
public class TimestampAction extends Action {
static String DATE_PATTERN_ATTRIBUTE = "datePattern";
-
+
boolean inError = false;
-
+
@Override
- public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException {
- String nameStr = attributes.getValue(NAME_ATTRIBUTE);
- if(OptionHelper.isEmpty(nameStr)) {
- addError("["+NAME_ATTRIBUTE+"] attribute cannot be empty");
+ public void begin(InterpretationContext ec, String name, Attributes attributes)
+ throws ActionException {
+ String keyStr = attributes.getValue(KEY_ATTRIBUTE);
+ if (OptionHelper.isEmpty(keyStr)) {
+ addError("Attrubute named [" + KEY_ATTRIBUTE + "] cannot be empty");
inError = true;
}
String datePatternStr = attributes.getValue(DATE_PATTERN_ATTRIBUTE);
- if(OptionHelper.isEmpty(datePatternStr)) {
- addError("["+DATE_PATTERN_ATTRIBUTE+"] attribute cannot be empty");
+ if (OptionHelper.isEmpty(datePatternStr)) {
+ addError("Attribute named [" + DATE_PATTERN_ATTRIBUTE
+ + "] cannot be empty");
inError = true;
}
-
- if(inError)
+
+ if (inError)
return;
-
+
SimpleDateFormat sdf = new SimpleDateFormat(datePatternStr);
String val = sdf.format(new Date());
- addInfo("Adding property ["+nameStr+"] with value ["+val+"] to the context");
- context.putProperty(nameStr, val);
+ addInfo("Adding property to the context with key=\"" + keyStr
+ + "\" and value=\"" + val + "\" to the context");
+ context.putProperty(keyStr, val);
}
@Override
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Pattern.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Pattern.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/spi/Pattern.java Sun Aug 9 13:54:23 2009
@@ -15,8 +15,8 @@
/**
* A pattern is used to designate XML elements in a document.
*
- * <p>For more information see
- * http://logback.qos.ch/manual/onJoran.html#pattern
+ * <p>For more information see
+ * http://logback.qos.ch/manual/onJoran.html#pattern
*
* @author Ceki Gülcü
*/
@@ -127,7 +127,7 @@
String l = (String) this.partList.get(lSize - i);
String r = (String) p.partList.get(rSize - i);
- if (l.equals(r)) {
+ if (equalityCheck(l, r)) {
match++;
} else {
break;
@@ -162,8 +162,7 @@
String l = (String) this.partList.get(i);
String r = (String) p.partList.get(i);
- // if (l.equals(r) || "*".equals(l) || "*".equals(r)) {
- if (l.equals(r)) {
+ if (equalityCheck(l, r)) {
match++;
} else {
break;
@@ -173,30 +172,31 @@
return match;
}
+ private boolean equalityCheck(String x, String y) {
+ return x.equalsIgnoreCase(y);
+ }
+
@Override
public boolean equals(Object o) {
- // System.out.println("in equals:" +this+ " vs. " + o);
if ((o == null) || !(o instanceof Pattern)) {
return false;
}
- // System.out.println("both are Patterns");
Pattern r = (Pattern) o;
if (r.size() != size()) {
return false;
}
- // System.out.println("both are size compatible");
int len = size();
for (int i = 0; i < len; i++) {
- if (!(get(i).equals(r.get(i)))) {
+ if (!equalityCheck(get(i), r.get(i))) {
return false;
}
}
- // if everything matches, then the twp patterns are equal
+ // if everything matches, then the two patterns are equal
return true;
}
@@ -206,9 +206,9 @@
int len = size();
for (int i = 0; i < len; i++) {
- hc ^= get(i).hashCode();
-
- // System.out.println("i = "+i+", hc="+hc);
+ // make Pattern comparisons case insensitive
+ // http://jira.qos.ch/browse/LBCORE-76
+ hc ^= get(i).toLowerCase().hashCode();
}
return hc;
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/TrivialConfiguratorTest.java Sun Aug 9 13:54:23 2009
@@ -42,7 +42,8 @@
public void doTest(String filename) throws Exception {
- rulesMap.put(new Pattern("x/inc"), new IncAction());
+ // rule store is case insensitve
+ rulesMap.put(new Pattern("x/INC"), new IncAction());
TrivialConfigurator gc = new TrivialConfigurator(rulesMap);
@@ -50,7 +51,7 @@
gc.doConfigure(CoreTestConstants.TEST_DIR_PREFIX + "input/joran/"
+ filename);
}
-
+
@Test
public void smoke() throws Exception {
int oldBeginCount = IncAction.beginCount;
Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinator.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinator.java Sun Aug 9 13:54:23 2009
@@ -0,0 +1,99 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2009, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.core.joran.spi;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CaseCombinator {
+
+
+ List<String> combinations(String in) {
+ int length = in.length();
+ List<String> permutationsList = new ArrayList<String>();
+
+ int totalCombinations = computeTotalNumerOfCombinations(in, length);
+
+ for (int j = 0; j < totalCombinations; j++) {
+ StringBuilder newCombination = new StringBuilder();
+ int pos = 0;
+ for (int i = 0; i < length; i++) {
+ char c = in.charAt(i);
+ if (isEnglishLetter(c)) {
+ c = permute(c, j, pos);
+ pos++;
+ }
+ newCombination.append(c);
+ }
+ permutationsList.add(newCombination.toString());
+ }
+ return permutationsList;
+
+ }
+
+ private char permute(char c, int permutation, int position) {
+ int mask = 1 << position;
+ boolean shouldBeInUpperCase = (permutation & mask) != 0;
+ boolean isEffectivelyUpperCase = isUpperCase(c);
+ if (shouldBeInUpperCase && !isEffectivelyUpperCase)
+ return toUpperCase(c);
+ if (!shouldBeInUpperCase && isEffectivelyUpperCase)
+ return toLowerCase(c);
+ return c;
+ }
+
+ private int computeTotalNumerOfCombinations(String in, int length) {
+ int count = 0;
+ for (int i = 0; i < length; i++) {
+ char c = in.charAt(i);
+ if (isEnglishLetter(c))
+ count++;
+ }
+ // return 2^count (2 to the power of count)
+ return (1 << count);
+ }
+
+ private char toUpperCase(char c) {
+ if ('A' <= c && c <= 'Z') {
+ return c;
+ }
+ if ('a' <= c && c <= 'z') {
+ int ci = c;
+ return (char) (ci + 'A' - 'a');
+ }
+ // code should never reach this point
+ return c;
+ }
+
+ private char toLowerCase(char c) {
+ if ('a' <= c && c <= 'z') {
+ return c;
+ }
+ if ('A' <= c && c <= 'Z') {
+ int ci = c;
+ return (char) (ci + 'a' - 'A');
+ }
+ // code should never reach this point
+ return c;
+ }
+
+ private boolean isEnglishLetter(char c) {
+ if ('a' <= c && c <= 'z')
+ return true;
+
+ if ('A' <= c && c <= 'Z')
+ return true;
+ return false;
+ }
+
+ private boolean isUpperCase(char c) {
+ return ('A' <= c && c <= 'Z');
+ }
+}
Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinatorTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/CaseCombinatorTest.java Sun Aug 9 13:54:23 2009
@@ -0,0 +1,49 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ *
+ * Copyright (C) 2000-2009, QOS.ch
+ *
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.core.joran.spi;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Test;
+
+
+public class CaseCombinatorTest {
+
+ CaseCombinator p = new CaseCombinator();
+
+
+ @Test
+ public void smoke() {
+ CaseCombinator p = new CaseCombinator();
+
+ List<String> result = p.combinations("a-B=");
+
+ List<String> witness = new ArrayList<String>();
+ witness.add("a-b=");
+ witness.add("A-b=");
+ witness.add("a-B=");
+ witness.add("A-B=");
+ assertEquals(witness, result);
+ }
+
+ @Test
+ public void other() {
+ List<String> result = p.combinations("aBCd");
+ assertEquals(16, result.size());
+ Set<String> witness = new HashSet<String>(result);
+ // check that there are no duplicates
+ assertEquals(16, witness.size());
+ }
+}
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PackageTest.java Sun Aug 9 13:54:23 2009
@@ -14,8 +14,8 @@
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
-@SuiteClasses( { PatternTest.class, SimpleStoreTest.class,
+@SuiteClasses( { PatternTest.class, SimpleRuleStoreTest.class,
PropertySetterTest.class, NoAutoStartUtilTest.class,
- DefaultNestedComponentRegistryTest.class })
+ DefaultNestedComponentRegistryTest.class, CaseCombinatorTest.class })
public class PackageTest {
}
Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/PatternTest.java Sun Aug 9 13:54:23 2009
@@ -94,6 +94,19 @@
Pattern rulePattern = new Pattern("*/a");
assertEquals(1, p.getTailMatchLength(rulePattern));
}
+
+ {
+ Pattern p = new Pattern("/A");
+ Pattern rulePattern = new Pattern("*/a");
+ assertEquals(1, p.getTailMatchLength(rulePattern));
+ }
+
+ {
+ Pattern p = new Pattern("/a");
+ Pattern rulePattern = new Pattern("*/A");
+ assertEquals(1, p.getTailMatchLength(rulePattern));
+ }
+
{
Pattern p = new Pattern("/a/b");
@@ -101,6 +114,11 @@
assertEquals(1, p.getTailMatchLength(rulePattern));
}
+ {
+ Pattern p = new Pattern("/a/B");
+ Pattern rulePattern = new Pattern("*/b");
+ assertEquals(1, p.getTailMatchLength(rulePattern));
+ }
{
Pattern p = new Pattern("/a/b/c");
@@ -129,6 +147,18 @@
Pattern rulePattern = new Pattern("/a/*");
assertEquals(1, p.getPrefixMatchLength(rulePattern));
}
+
+ {
+ Pattern p = new Pattern("/a/b");
+ Pattern rulePattern = new Pattern("/A/*");
+ assertEquals(1, p.getPrefixMatchLength(rulePattern));
+ }
+
+ {
+ Pattern p = new Pattern("/A/b");
+ Pattern rulePattern = new Pattern("/a/*");
+ assertEquals(1, p.getPrefixMatchLength(rulePattern));
+ }
{
Pattern p = new Pattern("/a/b");
Copied: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleRuleStoreTest.java (from r2425, /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleStoreTest.java)
==============================================================================
--- /logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleStoreTest.java (original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/joran/spi/SimpleRuleStoreTest.java Sun Aug 9 13:54:23 2009
@@ -1,7 +1,7 @@
/**
* Logback: the generic, reliable, fast and flexible logging framework.
*
- * Copyright (C) 2000-2008, QOS.ch
+ * Copyright (C) 2000-2009, QOS.ch
*
* This library is free software, you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
@@ -24,186 +24,203 @@
import ch.qos.logback.core.joran.action.Action;
/**
+ * Test SimpleRuleStore for various explicit rule combinations.
*
- * @author Ceki Gulcu
+ * We also test that explicit patterns are case sensitive.
+ *
+ * @author Ceki Gülcü
*/
-public class SimpleStoreTest {
+public class SimpleRuleStoreTest {
+ SimpleRuleStore srs = new SimpleRuleStore(new ContextBase());
+ CaseCombinator cc = new CaseCombinator();
+
@Test
- public void test1() throws Exception {
- // Document doc = getW3Document("file:input/joran/parser1.xml");
- SimpleRuleStore srs = new SimpleRuleStore(new ContextBase());
+ public void smoke() throws Exception {
srs.addRule(new Pattern("a/b"), new XAction());
- List r = srs.matchActions(new Pattern("a/b"));
- assertNotNull(r);
- assertEquals(1, r.size());
-
- if (!(r.get(0) instanceof XAction)) {
- fail("Wrong type");
+ // test for all possible case combinations of "a/b"
+ for (String s : cc.combinations("a/b")) {
+ List r = srs.matchActions(new Pattern(s));
+ assertNotNull(r);
+ assertEquals(1, r.size());
+
+ if (!(r.get(0) instanceof XAction)) {
+ fail("Wrong type");
+ }
}
+ }
- srs = new SimpleRuleStore(new ContextBase());
+ @Test
+ public void smokeII() throws Exception {
srs.addRule(new Pattern("a/b"), new XAction());
srs.addRule(new Pattern("a/b"), new YAction());
- r = srs.matchActions(new Pattern("a/b"));
- assertNotNull(r);
- assertEquals(2, r.size());
-
- if (!(r.get(0) instanceof XAction)) {
- fail("Wrong type");
- }
-
- if (!(r.get(1) instanceof YAction)) {
- fail("Wrong type");
+ for (String s : cc.combinations("a/b")) {
+ List r = srs.matchActions(new Pattern(s));
+ assertNotNull(r);
+ assertEquals(2, r.size());
+
+ if (!(r.get(0) instanceof XAction)) {
+ fail("Wrong type");
+ }
+
+ if (!(r.get(1) instanceof YAction)) {
+ fail("Wrong type");
+ }
}
-
}
@Test
public void testSlashSuffix() throws Exception {
- SimpleRuleStore srs = new SimpleRuleStore(new ContextBase());
Pattern pa = new Pattern("a/");
srs.addRule(pa, new XAction());
-
- List r = srs.matchActions(new Pattern("a"));
- assertNotNull(r);
- assertEquals(1, r.size());
- if (!(r.get(0) instanceof XAction)) {
- fail("Wrong type");
+ for (String s : cc.combinations("a")) {
+ List r = srs.matchActions(new Pattern(s));
+ assertNotNull(r);
+ assertEquals(1, r.size());
+
+ if (!(r.get(0) instanceof XAction)) {
+ fail("Wrong type");
+ }
}
-
}
-
+
@Test
public void testTail1() throws Exception {
- SimpleRuleStore srs = new SimpleRuleStore(new ContextBase());
srs.addRule(new Pattern("*/b"), new XAction());
- List r = srs.matchActions(new Pattern("a/b"));
- assertNotNull(r);
-
- assertEquals(1, r.size());
-
- if (!(r.get(0) instanceof XAction)) {
- fail("Wrong type");
+ for (String s : cc.combinations("a/b")) {
+ List r = srs.matchActions(new Pattern(s));
+ assertNotNull(r);
+
+ assertEquals(1, r.size());
+
+ if (!(r.get(0) instanceof XAction)) {
+ fail("Wrong type");
+ }
}
}
-
@Test
public void testTail2() throws Exception {
SimpleRuleStore srs = new SimpleRuleStore(new ContextBase());
srs.addRule(new Pattern("*/c"), new XAction());
- List r = srs.matchActions(new Pattern("a/b/c"));
- assertNotNull(r);
-
- assertEquals(1, r.size());
-
- if (!(r.get(0) instanceof XAction)) {
- fail("Wrong type");
+ for (String s : cc.combinations("a/b/c")) {
+ List r = srs.matchActions(new Pattern(s));
+ assertNotNull(r);
+
+ assertEquals(1, r.size());
+
+ if (!(r.get(0) instanceof XAction)) {
+ fail("Wrong type");
+ }
}
}
-
+
@Test
public void testTail3() throws Exception {
- SimpleRuleStore srs = new SimpleRuleStore(new ContextBase());
srs.addRule(new Pattern("*/b"), new XAction());
srs.addRule(new Pattern("*/a/b"), new YAction());
- List r = srs.matchActions(new Pattern("a/b"));
- assertNotNull(r);
-
- // System.out.println("restulg list is: "+r);
- assertEquals(1, r.size());
-
- if (!(r.get(0) instanceof YAction)) {
- fail("Wrong type");
+ for (String s : cc.combinations("a/b")) {
+ List r = srs.matchActions(new Pattern(s));
+ assertNotNull(r);
+ assertEquals(1, r.size());
+
+ if (!(r.get(0) instanceof YAction)) {
+ fail("Wrong type");
+ }
}
}
@Test
public void testTail4() throws Exception {
- SimpleRuleStore srs = new SimpleRuleStore(new ContextBase());
srs.addRule(new Pattern("*/b"), new XAction());
srs.addRule(new Pattern("*/a/b"), new YAction());
srs.addRule(new Pattern("a/b"), new ZAction());
- List r = srs.matchActions(new Pattern("a/b"));
- assertNotNull(r);
-
- // System.out.println("result list is: "+r);
- assertEquals(1, r.size());
-
- if (!(r.get(0) instanceof ZAction)) {
- fail("Wrong type");
+ for (String s : cc.combinations("a/b")) {
+ List r = srs.matchActions(new Pattern(s));
+ assertNotNull(r);
+ assertEquals(1, r.size());
+
+ if (!(r.get(0) instanceof ZAction)) {
+ fail("Wrong type");
+ }
}
}
-
+
@Test
public void testSuffix() throws Exception {
- SimpleRuleStore srs = new SimpleRuleStore(new ContextBase());
srs.addRule(new Pattern("a"), new XAction());
srs.addRule(new Pattern("a/*"), new YAction());
- List r = srs.matchActions(new Pattern("a/b"));
- assertNotNull(r);
- assertEquals(1, r.size());
- assertTrue(r.get(0) instanceof YAction);
+ for (String s : cc.combinations("a/b")) {
+ List r = srs.matchActions(new Pattern(s));
+ assertNotNull(r);
+ assertEquals(1, r.size());
+ assertTrue(r.get(0) instanceof YAction);
+ }
}
-
+
@Test
public void testDeepSuffix() throws Exception {
- SimpleRuleStore srs = new SimpleRuleStore(new ContextBase());
srs.addRule(new Pattern("a"), new XAction(1));
srs.addRule(new Pattern("a/b/*"), new XAction(2));
- List r = srs.matchActions(new Pattern("a/other"));
- assertNull(r);
+ for (String s : cc.combinations("a/other")) {
+ List r = srs.matchActions(new Pattern(s));
+ assertNull(r);
+ }
}
@Test
public void testPrefixSuffixInteraction1() throws Exception {
- SimpleRuleStore srs = new SimpleRuleStore(new ContextBase());
srs.addRule(new Pattern("a"), new ZAction());
srs.addRule(new Pattern("a/*"), new YAction());
srs.addRule(new Pattern("*/a/b"), new XAction(3));
- List r = srs.matchActions(new Pattern("a/b"));
- assertNotNull(r);
-
- assertEquals(1, r.size());
-
- assertTrue(r.get(0) instanceof XAction);
- XAction xaction = (XAction) r.get(0);
- assertEquals(3, xaction.id);
+ for (String s : cc.combinations("a/b")) {
+ List r = srs.matchActions(new Pattern(s));
+ assertNotNull(r);
+
+ assertEquals(1, r.size());
+
+ assertTrue(r.get(0) instanceof XAction);
+ XAction xaction = (XAction) r.get(0);
+ assertEquals(3, xaction.id);
+ }
}
@Test
public void testPrefixSuffixInteraction2() throws Exception {
- SimpleRuleStore srs = new SimpleRuleStore(new ContextBase());
- srs.addRule(new Pattern("testGroup"), new XAction());
- srs.addRule(new Pattern("testGroup/testShell"), new YAction());
- srs.addRule(new Pattern("testGroup/testShell/test"), new ZAction());
- srs.addRule(new Pattern("testGroup/testShell/test/*"), new XAction(9));
-
- List r = srs.matchActions(new Pattern("testGroup/testShell/toto"));
- assertNull(r);
+ srs.addRule(new Pattern("tG"), new XAction());
+ srs.addRule(new Pattern("tG/tS"), new YAction());
+ srs.addRule(new Pattern("tG/tS/test"), new ZAction());
+ srs.addRule(new Pattern("tG/tS/test/*"), new XAction(9));
+
+ for (String s : cc.combinations("tG/tS/toto")) {
+ List r = srs.matchActions(new Pattern(s));
+ assertNull(r);
+ }
}
-
+
class XAction extends Action {
int id = 0;
+
XAction() {
}
+
XAction(int id) {
this.id = id;
}
- public void begin(InterpretationContext ec, String name, Attributes attributes) {
+ public void begin(InterpretationContext ec, String name,
+ Attributes attributes) {
}
public void end(InterpretationContext ec, String name) {
@@ -211,14 +228,15 @@
public void finish(InterpretationContext ec) {
}
-
+
public String toString() {
- return "XAction("+id+")";
- }
+ return "XAction(" + id + ")";
+ }
}
class YAction extends Action {
- public void begin(InterpretationContext ec, String name, Attributes attributes) {
+ public void begin(InterpretationContext ec, String name,
+ Attributes attributes) {
}
public void end(InterpretationContext ec, String name) {
@@ -229,7 +247,8 @@
}
class ZAction extends Action {
- public void begin(InterpretationContext ec, String name, Attributes attributes) {
+ public void begin(InterpretationContext ec, String name,
+ Attributes attributes) {
}
public void end(InterpretationContext ec, String name) {
1
0

svn commit: r2425 - in logback/trunk: logback-core/src/main/java/ch/qos/logback/core/joran/action logback-site/src/site/pages/manual
by noreply.ceki@qos.ch 08 Aug '09
by noreply.ceki@qos.ch 08 Aug '09
08 Aug '09
Author: ceki
Date: Sun Aug 9 00:55:28 2009
New Revision: 2425
Added:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/TimestampAction.java
Modified:
logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ParamAction.java
logback/trunk/logback-site/src/site/pages/manual/appenders.html
Log:
- Started working on LBCORE-91 with TimestampAction
- improved docs on TimeBasedRollingPolicy
Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ParamAction.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ParamAction.java (original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/ParamAction.java Sun Aug 9 00:55:28 2009
@@ -1,13 +1,14 @@
/**
- * LOGBack: the generic, reliable, fast and flexible logging framework.
+ * Logback: the generic, reliable, fast and flexible logging framework.
*
- * Copyright (C) 1999-2006, QOS.ch
+ * Copyright (C) 2000-2009, QOS.ch
*
* This library is free software, you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation.
*/
+
package ch.qos.logback.core.joran.action;
Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/TimestampAction.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/joran/action/TimestampAction.java Sun Aug 9 00:55:28 2009
@@ -0,0 +1,44 @@
+package ch.qos.logback.core.joran.action;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.xml.sax.Attributes;
+
+import ch.qos.logback.core.joran.spi.ActionException;
+import ch.qos.logback.core.joran.spi.InterpretationContext;
+import ch.qos.logback.core.util.OptionHelper;
+
+public class TimestampAction extends Action {
+ static String DATE_PATTERN_ATTRIBUTE = "datePattern";
+
+ boolean inError = false;
+
+ @Override
+ public void begin(InterpretationContext ec, String name, Attributes attributes) throws ActionException {
+ String nameStr = attributes.getValue(NAME_ATTRIBUTE);
+ if(OptionHelper.isEmpty(nameStr)) {
+ addError("["+NAME_ATTRIBUTE+"] attribute cannot be empty");
+ inError = true;
+ }
+ String datePatternStr = attributes.getValue(DATE_PATTERN_ATTRIBUTE);
+ if(OptionHelper.isEmpty(datePatternStr)) {
+ addError("["+DATE_PATTERN_ATTRIBUTE+"] attribute cannot be empty");
+ inError = true;
+ }
+
+ if(inError)
+ return;
+
+ SimpleDateFormat sdf = new SimpleDateFormat(datePatternStr);
+ String val = sdf.format(new Date());
+
+ addInfo("Adding property ["+nameStr+"] with value ["+val+"] to the context");
+ context.putProperty(nameStr, val);
+ }
+
+ @Override
+ public void end(InterpretationContext ec, String name) throws ActionException {
+ }
+
+}
Modified: logback/trunk/logback-site/src/site/pages/manual/appenders.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/appenders.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/appenders.html Sun Aug 9 00:55:28 2009
@@ -927,7 +927,7 @@
href="../xref/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.html">
<code>TimeBasedRollingPolicy</code></a> is possibly the most
popular rolling policy. It defines a rollover policy based on time,
- say by day or by month.
+ for example by day or by month.
</p>
<p><code>TimeBasedRollingPolicy</code>'s admits two properties, the
@@ -935,15 +935,30 @@
the optional <span class="option">MaxHistory</span> property.
</p>
- <p><span class="option">FileNamePattern</span> option defines the
+ <p><span class="option">FileNamePattern</span> property defines the
name of the rolled (archived) log files. Its value should consist
of the name of the file, plus a suitably placed <em>%d</em>
conversion specifier. The <em>%d</em> conversion specifier may
contain a date-and-time pattern as specified by the
<code>java.text.SimpleDateFormat</code> class. If the
date-and-time pattern is omitted, then the default pattern
- <em>yyyy-MM-dd</em> is assumed. The following examples should
- clarify the point.
+ <em>yyyy-MM-dd</em> is assumed. The <span
+ class="option">File</span> property in
+ <code>RollingFileAppender</code> (the parent of
+ <code>TimeBasedRollingPolicy</code>) can be either set or omitted.
+
+ </p>
+
+ <p>By setting the <span class="option">File</span> property you can
+ decouple the location of the active log file and the location of
+ the archived log files. The current logs will be always targeted at
+ the file specified by the <span class="option">File</span>
+ property. It follows that the name of the currently active log file
+ will not change over time. However, if you choose to omit the <span
+ class="option">File</span> property, then the active file will be
+ computed anew for each period based on the value of <span
+ class="option">FileNamePattern</span>. The following examples
+ should clarify the point.
</p>
<table class="bodyTable">
@@ -951,7 +966,7 @@
<th>
<span class="option">FileNamePattern</span>
</th>
- <th>Roll-over schedule</th>
+ <th>Rollover schedule</th>
<th>Example</th>
</tr>
<tr class="b">
@@ -963,34 +978,52 @@
specifier, the default pattern of <em>yyyy-MM-dd</em> is
assumed, which corresponds to daily rollover.
</td>
+
<td>
- <p>Assuming the <span class="option">File</span> property is
- not set, during November 23rd, 2006, logging output will go
- to the file <em>/wombat/foo.2006-11-23</em>. At midnight and
- for the rest of the 24th, logging output will be directed to
+ <p><span class="option">File</span> property not set: During November
+ 23rd, 2006, logging output will go to the file
+ <em>/wombat/foo.2006-11-23</em>. At midnight and for the
+ rest of the 24th, logging output will be directed to
<em>/wombat/foo.2006-11-24</em>.
</p>
+
+ <p><span class="option">File</span> property set to
+ <em>/wombat/foo.txt</em>: During November 23rd, 2006, logging
+ output will go to the file <em>/wombat/foo.txt</em>. At
+ midnight, <em>foo.txt</em> will be renamed as
+ <em>/wombat/foo.2006-11-23</em>. A new
+ <em>/wombat/foo.txt</em> file will be created and for the
+ rest of November 24th logging output will be directed to
+ <em>foo.txt</em>.
+ </p>
+
</td>
</tr>
<tr class="a">
<td class="small">
- <em>/wombat/%d{yyyy/MM}/log.txt</em>
+ <em>/wombat/%d{yyyy/MM}/foo.txt</em>
</td>
<td>Rollover at the beginning of each month.</td>
<td>
- <p>During the month of October 2006, logging output will go
- to <em>/wombat/2006/10/log.txt</em>. After midnight of
- October 31st and for the rest of November, logging output
- will be directed to <em>/wombat/2006/11/log.txt</em>.
+ <p><span class="option">File</span> property not set: During the
+ month of October 2006, logging output will go to
+ <em>/wombat/2006/10/foo.txt</em>. After midnight of October
+ 31st and for the rest of November, logging output will be
+ directed to <em>/wombat/2006/11/foo.txt</em>.
</p>
- <p>However, if the <span class="option">File</span> property is
- set, for example to <em>log.txt</em>, then logging will always
- written to <em>log.txt</em>. At midnight and
- for the rest of the 24th, logging output will be directed to
- <em>/wombat/foo.2006-11-24</em>
+ <p><span class="option">File</span> property set to
+ <em>/wombat/foo.txt</em>: The active log file will always be
+ <em>/wombat/foo.txt</em>. During the month of October 2006,
+ logging output will go to <em>/wombat/foo.txt</em>. At
+ midnight of October 31st, <em>/wombat/foo.txt</em> will be
+ renamed as <em>/wombat/2006/10/foo.txt</em>. A new
+ <em>/wombat/foo.txt</em> file will be created where logging
+ output will go for the rest of November. At midnight of
+ November 30th, <em>/wombat/foo.txt</em> will be renamed as
+ <em>/wombat/2006/11/foo.txt</em> and so on.
</p>
</td>
</tr>
@@ -1002,23 +1035,17 @@
<td>Rollover at the first day of each week. Note that the first
day of the week depends on the locale.</td>
- <td>During the 23rd week of 2006, the file
- <em>/wombat/foo.2006-23.log</em> will contain the actual logging
- output. Logging for the 24th week of 2006 will be output to
- <em>/wombat/foo.2006-24.log</em> until it is rolled over at the
- beginning of the next week.
- </td>
+ <td>Similar to previous cases, except that rollover will occur
+ at the beginning of every new week.
+ </td>
</tr>
<tr class="a">
<td class="small">
<em>/wombat/foo. /<br/>%d{yyyy-MM-dd_HH}.log</em>
</td>
<td>Rollover at the top of each hour.</td>
- <td>Between 11.00,001 and 11.59,999, on November 3rd, 2006, the
- logging will be output to
- <em>/wombat/foo.2006-11-03_11.log</em>. After that, and until
- 12.59,999, the logging will be output to
- <em>/wombat/foo.2006-11-03_12.log</em>.
+ <td>Similar to previous cases, except that rollover will occur
+ at the top of every hour.
</td>
</tr>
<tr class="b">
@@ -1026,16 +1053,21 @@
<em>/wombat/foo. /<br/>%d{yyyy-MM-dd_HH-mm}.log</em>
</td>
<td>Rollover at the beginning of every minute.</td>
- <td>Between 11.32,001 and 11.32,999, on November 3rd, 2006, the
- logging will be output to
- <em>/wombat/foo.2006-11-03_11-32.log</em>. After that, and
- until 12.33,999, the logging will be output to
- <em>/wombat/foo.2006-11_12-33.log</em>.
- </td>
+ <td>Similar to previous cases, except that rollover will occur
+ at the beginning of every minute.
+ </td>
</tr>
</table>
- <p>Any characters in the pattern outside the ranges
+ <p>Any forward or backward slash characters are interpreted as
+ folder (directory) separators. Any required folder will be created
+ as necessary. You can thus easily place your log files in separate
+ folders.
+ </p>
+
+ <p>The date-and-time pattern, as found within accolades in %d{}
+ follow java.text.SimpleDateFormat conventions. This any characters
+ within the date-and-time pattern outside the ranges
<em>['a'..'z']</em> and <em>['A'..'Z']</em> will be treated as
quoted text. For instance, characters like <em>'.'</em>, <em>'
'</em>, <em>'#'</em> and <em>'@'</em> will appear in the resulting
@@ -1044,13 +1076,15 @@
<em>":"</em> character anywhere within the <span
class="option">FileNamePattern</span> option. The text before the
colon is interpreted as the protocol specification of a URL, which
- is most probably not what you intend. The slash <em>"/"</em>
- character, a common date field separator, must also be avoided. It
- is taken as a file separator causing the rollover operation to fail
- because the target file cannot be created. Although less common,
- the backslash character <em>"\"</em> is equally troublesome.
+ is most probably not what you intend. The forward-slash
+ <em>"/"</em> or backward slash <em>"\"</em> characters anywhere
+ within the <span class="option">FileNamePattern</span> property or
+ within the date-and-time pattern will be interpreted as directory
+ separators and any missing directories will be created as
+ necessary.
</p>
+
<p>Just like <code>FixedWindowRollingPolicy</code>,
<code>TimeBasedRollingPolicy</code> supports automatic file
compression. This feature is enabled if the value of the <span
@@ -1067,12 +1101,27 @@
<td><em>/wombat/foo.%d.gz</em></td>
<td>Daily rollover (at midnight) with automatic GZIP compression of the
archived files.</td>
- <td>During November 23rd, 2004, logging output will go to
- the file <em>/wombat/foo.2004-11-23</em>. However, at midnight that
- file will be compressed to become <em>/wombat/foo.2004-11-23.gz</em>.
- For the 24th of November, logging output will be directed to
- <em>/wombat/folder/foo.2004-11-24</em> until its rolled over at the
- beginning of the next day.
+ <td>
+ <p><span class="option">File</span> property not set: During
+ November 23rd, 2009, logging output will go to the file
+ <em>/wombat/foo.2009-11-23</em>. However, at midnight that
+ file will be compressed to become
+ <em>/wombat/foo.2009-11-23.gz</em>. For the 24th of November,
+ logging output will be directed to
+ <em>/wombat/folder/foo.2009-11-24</em> until its rolled over
+ at the beginning of the next day.
+ </p>
+
+ <p><span class="option">File</span> property set to
+ /wombat/foo.txt: During November 23rd, 2009, logging output
+ will go to the file <em>/wombat/foo.txt</em>. At midnight that
+ file will be compressed and renamed as
+ <em>/wombat/foo.2009-11-23.gz</em>. A new
+ <em>/wombat/foo.txt</em> file will be created where logging
+ output will go for the rest of November 24rd. At midnight
+ November 24th, <em>/wombat/foo.txt</em> will be compressed and
+ renamed as <em>/wombat/foo.2009-11-24.gz</em>. and so on.
+ </p>
</td>
</tr>
</table>
@@ -1086,10 +1135,10 @@
resulting archive files will carry different names.
</p>
- <p>Thus, <code>TimeBasedRollingPolicy</code> assumes the
- responsibility for rollover as well as for the triggering of said
- rollover. Indeed, <code>TimeBasedTriggeringPolicy</code> implements
- both <code>RollingPolicy</code> and <code>TriggeringPolicy</code>
+ <p><code>TimeBasedRollingPolicy</code> assumes the responsibility
+ for rollover as well as for the triggering of said rollover. Indeed,
+ <code>TimeBasedTriggeringPolicy</code> implements both
+ <code>RollingPolicy</code> and <code>TriggeringPolicy</code>
interfaces.
</p>
@@ -1108,22 +1157,25 @@
maximum number of archive files to keep, deleting older files. For
example, if you specify monthly rollover, and set <span
class="option">MaxHistory</span> to 6, then 6 months worth of
- archives files will be kept with files older than 6 months deleted.
+ archives files will be kept with files older than 6 months
+ deleted. Note as old archived log files are removed, any folders
+ which were created for the purpose of log file archiving will be
+ removed as appropriate.
</p>
- <p>For various reasons, rollovers are not clock-driven but depend on
- the arrival of logging events. For example, on 8th of March 2002,
- assuming the <span class="option">FileNamePattern</span> is set to
- <em>yyyy-MM-dd</em> (daily rollover), the arrival of the first event
- after midnight will trigger a rollover. If there are no logging
- events during, say 23 minutes and 47 seconds after midnight, then
- rollover will actually occur at 00:23'47 AM on March 9th and not at
- 0:00 AM. Thus, depending on the arrival rate of events, rollovers
- might be triggered with some latency. However, regardless of the
- delay, the rollover algorithm is known to be correct, in the sense
- that all logging events generated during a certain period will be
- output in the correct file delimiting that period.
+ <p>For various technical reasons, rollovers are not clock-driven but
+ depend on the arrival of logging events. For example, on 8th of
+ March 2002, assuming the <span class="option">FileNamePattern</span>
+ is set to <em>yyyy-MM-dd</em> (daily rollover), the arrival of the
+ first event after midnight will trigger a rollover. If there are no
+ logging events during, say 23 minutes and 47 seconds after midnight,
+ then rollover will actually occur at 00:23'47 AM on March 9th and
+ not at 0:00 AM. Thus, depending on the arrival rate of events,
+ rollovers might be triggered with some latency. However, regardless
+ of the delay, the rollover algorithm is known to be correct, in the
+ sense that all logging events generated during a certain period will
+ be output in the correct file delimiting that period.
</p>
<p>Here is a sample configuration for
1
0

svn commit: r2424 - in logback/trunk: logback-examples/src/main/java/chapter4/conf logback-site/src/site/pages/manual
by noreply.ceki@qos.ch 08 Aug '09
by noreply.ceki@qos.ch 08 Aug '09
08 Aug '09
Author: ceki
Date: Sat Aug 8 18:55:57 2009
New Revision: 2424
Added:
logback/trunk/logback-examples/src/main/java/chapter4/conf/logbback-sizeAndTime.xml
Modified:
logback/trunk/logback-examples/src/main/java/chapter4/conf/logback-RollingTimeBased.xml
logback/trunk/logback-site/src/site/pages/manual/appenders.html
Log:
- working on the documentation
Modified: logback/trunk/logback-examples/src/main/java/chapter4/conf/logback-RollingTimeBased.xml
==============================================================================
--- logback/trunk/logback-examples/src/main/java/chapter4/conf/logback-RollingTimeBased.xml (original)
+++ logback/trunk/logback-examples/src/main/java/chapter4/conf/logback-RollingTimeBased.xml Sat Aug 8 18:55:57 2009
@@ -7,7 +7,7 @@
<MaxHistory>30</MaxHistory>
</rollingPolicy>
- <layout class="ch.qos.logback.classic.PatternLayout">
+ <layout>
<Pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</Pattern>
</layout>
</appender>
Added: logback/trunk/logback-examples/src/main/java/chapter4/conf/logbback-sizeAndTime.xml
==============================================================================
--- (empty file)
+++ logback/trunk/logback-examples/src/main/java/chapter4/conf/logbback-sizeAndTime.xml Sat Aug 8 18:55:57 2009
@@ -0,0 +1,26 @@
+<configuration>
+
+ <appender name="ROLLING"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <File>${randomOutputDir}z${testId}</File>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <FileNamePattern>
+ ${randomOutputDir}${testId}-%d{yyyy-MM-dd_HH_mm_ss}.%i
+ </FileNamePattern>
+ <TimeBasedFileNamingAndTriggeringPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+ <MaxFileSize>${sizeThreshold}</MaxFileSize>
+ </TimeBasedFileNamingAndTriggeringPolicy>
+ </rollingPolicy>
+ <layout>
+ <Pattern>%msg%n</Pattern>
+ </layout>
+ </appender>
+
+
+ <root level="debug">
+ <appender-ref ref="ROLLING" />
+ </root>
+
+</configuration>
Modified: logback/trunk/logback-site/src/site/pages/manual/appenders.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/appenders.html (original)
+++ logback/trunk/logback-site/src/site/pages/manual/appenders.html Sat Aug 8 18:55:57 2009
@@ -927,12 +927,7 @@
href="../xref/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.html">
<code>TimeBasedRollingPolicy</code></a> is possibly the most
popular rolling policy. It defines a rollover policy based on time,
- say by day or by month. <code>TimeBasedRollingPolicy</code> is
- particular in the sense that it simultaneously implements both the
- <code>RollingPolicy</code> as well as the
- <code>TriggeringPolicy</code> interfaces. The
- <code>TriggeringPolicy</code> interface will be presented in the
- next sub-section.
+ say by day or by month.
</p>
<p><code>TimeBasedRollingPolicy</code>'s admits two properties, the
@@ -961,28 +956,42 @@
</tr>
<tr class="b">
<td class="small">
- <em>/wombat/folder/foo.%d</em>
+ <em>/wombat/foo.%d</em>
</td>
<td>Daily rollover (at midnight). Due to the omission of the
optional time and date pattern for the <em>%d</em> token
specifier, the default pattern of <em>yyyy-MM-dd</em> is
assumed, which corresponds to daily rollover.
</td>
- <td>During November 23rd, 2006, logging output will go to the
- file <em>/wombat/foo.2006-11-23</em>. At midnight and for the
- rest of the 24th, logging output will be directed to
- <em>/wombat/foo.2006-11-24</em>.
+ <td>
+ <p>Assuming the <span class="option">File</span> property is
+ not set, during November 23rd, 2006, logging output will go
+ to the file <em>/wombat/foo.2006-11-23</em>. At midnight and
+ for the rest of the 24th, logging output will be directed to
+ <em>/wombat/foo.2006-11-24</em>.
+ </p>
</td>
</tr>
+
+
<tr class="a">
<td class="small">
- <em>/wombat/foo.%d{yyyy-MM}.log</em>
+ <em>/wombat/%d{yyyy/MM}/log.txt</em>
</td>
<td>Rollover at the beginning of each month.</td>
- <td>During the month of October 2006, logging output will go to
- <em>/wombat/foo.2006-10.log</em>. After midnight of October
- 31st and for the rest of November, logging output will be
- directed to <em>/wombat/foo.2006-11.log</em>.
+ <td>
+ <p>During the month of October 2006, logging output will go
+ to <em>/wombat/2006/10/log.txt</em>. After midnight of
+ October 31st and for the rest of November, logging output
+ will be directed to <em>/wombat/2006/11/log.txt</em>.
+ </p>
+
+ <p>However, if the <span class="option">File</span> property is
+ set, for example to <em>log.txt</em>, then logging will always
+ written to <em>log.txt</em>. At midnight and
+ for the rest of the 24th, logging output will be directed to
+ <em>/wombat/foo.2006-11-24</em>
+ </p>
</td>
</tr>
<tr class="b">
@@ -1178,23 +1187,30 @@
<p>You may sometimes wish to archive files essentialy by date but
at the same time limit the size of each log file, in particular if
- post-processing tools impose size limits.</p>
+ post-processing tools impose size limits on the log files. In
+ order to address this requirement, logback ships with a
+ sub-component for <code>TimeBasedRollingPolicy</code> called
+ <code>SizeAndTimeBasedFNATP</code>, where FNATP stands for File
+ Naming And Triggering Policy.</p>
+
- <em>Example 4.<span class="autoEx"/>: Sample configuration of a <code>RollingFileAppender</code> using a
- <code>TimeBasedRollingPolicy</code> (logback-examples/src/main/java/chapter4/conf/logback-PrudentTimeBasedRolling.xml)</em>
+
+ <em>Example 4.<span class="autoEx"/>: Sample configuration for
+ <code>SizeAndTimeBasedFNATP</code>
+ (logback-examples/src/main/java/chapter4/conf/logback-sizeAndTime.xml)</em>
<pre class="prettyprint source"><configuration>
<appender name="ROLLING"
class="ch.qos.logback.core.rolling.RollingFileAppender">
- <File>${randomOutputDir}z${testId}</File>
+ <File>mylog.txt</File>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
- ${randomOutputDir}${testId}-%d{yyyy-MM-dd_HH_mm_ss}.%i
+ <b>mylog-%d{yyyy-MM-dd_HH_mm_ss}.<span class="big red">%i</span>.txt</b>
</FileNamePattern>
- <TimeBasedFileNamingAndTriggeringPolicy
- class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
- <MaxFileSize>${sizeThreshold}</MaxFileSize>
- </TimeBasedFileNamingAndTriggeringPolicy>
+ <b><TimeBasedFileNamingAndTriggeringPolicy</b>
+ <b>class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"></b>
+ <b><MaxFileSize>${sizeThreshold}</MaxFileSize></b>
+ <b></TimeBasedFileNamingAndTriggeringPolicy></b>
</rollingPolicy>
<layout>
<Pattern>%msg%n</Pattern>
@@ -1208,7 +1224,18 @@
</configuration></pre>
-
+ <p>Note the "%i" conversion token in addition to "%d{}". Each time
+ the current log file reaches <code>MaxFileSize</code> before the
+ current time period end, it will be archived with an increasing
+ index, starting at 0.</p>
+
+ <p>Size and time based archiving supports cleaning of old archive
+ files. You just need to specify the number of periods to preserve
+ with the <code><MaxHistory></code> element. When your
+ application is stopped and restarted, logging will continue at
+ correct location, i.e. at the largest index number for the current
+ period.
+ </p>
<h3>
<a name="TriggeringPolicy" href="#TriggeringPolicy">Triggering policy interface</a>
1
0