From markward.schubert at gmail.com Thu Dec 2 17:17:46 2010 From: markward.schubert at gmail.com (Markward Schubert) Date: Thu, 2 Dec 2010 17:17:46 +0100 Subject: [logback-dev] GEventEvaluator not started Message-ID: Hi! I am experiencing a problem with the GEventEvaluator. After hours of trying around with different configurations, I could not get this to work. The Filter was simply ignored. I even tried 1 == 2 as an expression, but it was happily logging. Finally I started my project in debugmode and startet stepping around the logback code. Now my question: Is it possible, that GEventEvaluator misses a call to super.start() in it's start-method? EvaluatorFilter in my case returns FilterReply.NEUTRAL in the code-passage below, as evaluator.isStarted() returns false. if (!isStarted() || !evaluator.isStarted()) { return FilterReply.NEUTRAL; } Regards, Markward -------------- next part -------------- An HTML attachment was scrubbed... URL: From ceki at qos.ch Thu Dec 2 17:42:45 2010 From: ceki at qos.ch (Ceki Gulcu) Date: Thu, 02 Dec 2010 17:42:45 +0100 Subject: [logback-dev] GEventEvaluator not started In-Reply-To: References: Message-ID: <4CF7CC85.5020302@qos.ch> Hi Markward, The evaluator will refuse to start of it detects an error. Add the following to the top of your logback-groovy.xml file and check whether there are any reported errors. import ch.qos.logback.core.status.OnConsoleStatusListener // other imports.... statusListener(OnConsoleStatusListener) // rest of config file... On 02.12.2010 17:17, Markward Schubert wrote: > Hi! > > I am experiencing a problem with the GEventEvaluator. After hours of > trying around with different configurations, I could not get this to > work. The Filter was simply ignored. I even tried 1 == 2 as an > expression, but it was happily logging. > > Finally I started my project in debugmode and startet stepping around > the logback code. > Now my question: > > Is it possible, that GEventEvaluator misses a call to super.start() in > it's start-method? > > EvaluatorFilter in my case returns FilterReply.NEUTRAL in the > code-passage below, as evaluator.isStarted() returns false. > > if (!isStarted() || !evaluator.isStarted()) { > return FilterReply.NEUTRAL; > } > > > Regards, > Markward > > > > _______________________________________________ > logback-dev mailing list > logback-dev at qos.ch > http://qos.ch/mailman/listinfo/logback-dev From noreply-jira at qos.ch Mon Dec 6 09:33:51 2010 From: noreply-jira at qos.ch (Denis Bazhenov (JIRA)) Date: Mon, 6 Dec 2010 09:33:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBACCESS-18) NPE is case of desrialized AccessEvent Message-ID: <1017980597.1291624431265.JavaMail.ceki@pixie> NPE is case of desrialized AccessEvent -------------------------------------- Key: LBACCESS-18 URL: http://jira.qos.ch/browse/LBACCESS-18 Project: logback-access Issue Type: Bug Affects Versions: 0.9.26 Environment: Sun Java HotSpot(TM) 64-Bit Server VM (build 16.2-b04, mixed mode) CentOS Linux 2.6.18-164.el5 #1 SMP Thu Sep 3 03:28:30 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux Reporter: Denis Bazhenov Assignee: Logback dev list I'm trying to use SimpleSocketServer (from logback-access) for remote logging of AccessEvent's. The problem I faced is following. When object get deserialized in SocketNode on line 64 it has no httpRequest (it's simply null). There is debugger dump of event: event = instance of ch.qos.logback.access.spi.AccessEvent(id=932) Thread-1[1] dump event event = { serialVersionUID: 866718993618836343 NA: "-" NA_STRING_ARRAY: instance of java.lang.String[1] (id=914) EMPTY: "" SENTINEL: -1 httpRequest: null httpResponse: null requestURI: "/" requestURL: "GET / HTTP/1.1" remoteHost: "192.168.20.179" remoteUser: null remoteAddr: "192.168.20.179" protocol: "HTTP/1.1" method: "GET" serverName: "jetty-test" requestContent: "" responseContent: "" requestHeaderMap: instance of java.util.TreeMap(id=938) requestParameterMap: instance of java.util.HashMap(id=939) responseHeaderMap: instance of java.util.HashMap(id=940) contentLength: 1288 statusCode: 503 localPort: 8080 serverAdapter: null timeStamp: 1291621192027 } So later this gives me NPE in AccessEvent.buildRequestHeaderMap(). I have following logback-access.xml for client logs.vfarm.loc 6000 100 true /var/log/jetty/access.log access.%d{yyyy-MM-dd}.log.zip combined So logs are written locally (sucessfully) and sent over network to logs.vfarm.loc. On logs.vfarm.loc I have running SimpleSocketServer: java -cp jetty-6.1.24.jar:\ servlet-api-2.5.jar:\ logback-access-0.9.26.jar:\ slf4j-api-1.6.1.jar:\ logback-core-0.9.26.jar \ ch.qos.logback.access.net.SimpleSocketServer 6000 access.xml with following access.xml combined I think this issue is closely related to LBACCESS-6, but it's still reproducible. -- 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 From noreply-jira at qos.ch Mon Dec 6 15:35:51 2010 From: noreply-jira at qos.ch (Eric Estievenart (JIRA)) Date: Mon, 6 Dec 2010 15:35:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBACCESS-19) Cannot specify config file relative to catalina home Message-ID: <564216319.1291646151255.JavaMail.ceki@pixie> Cannot specify config file relative to catalina home ---------------------------------------------------- Key: LBACCESS-19 URL: http://jira.qos.ch/browse/LBACCESS-19 Project: logback-access Issue Type: Bug Affects Versions: 0.9.26 Environment: all Reporter: Eric Estievenart Assignee: Logback dev list Priority: Trivial There is no way to refer to catalina home when specifying the filename of a logback valve. What I would like to do is something like: The only way for now is to specify an absolute path, which is not very convenient. The system properties in the filename should be expanded in LogbackValve.start(). -- 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 From noreply-jira at qos.ch Mon Dec 6 15:40:51 2010 From: noreply-jira at qos.ch (Eric Estievenart (JIRA)) Date: Mon, 6 Dec 2010 15:40:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBACCESS-20) [DOC] logback-access.html example uses obsolete in (in access.html) Message-ID: <276117259.1291646451273.JavaMail.ceki@pixie> [DOC] logback-access.html example uses obsolete in (in access.html) --------------------------------------------------------------------------------------- Key: LBACCESS-20 URL: http://jira.qos.ch/browse/LBACCESS-20 Project: logback-access Issue Type: Bug Affects Versions: 0.9.26 Environment: - Reporter: Eric Estievenart Assignee: Logback dev list Priority: Trivial http://logback.qos.ch/access.html, in example 1: ------ should be ---------- Cheers. -- 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 From noreply-jira at qos.ch Mon Dec 6 16:01:51 2010 From: noreply-jira at qos.ch (Eric Estievenart (JIRA)) Date: Mon, 6 Dec 2010 16:01:51 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBACCESS-19) Cannot specify config file relative to catalina home In-Reply-To: <564216319.1291646151255.JavaMail.ceki@pixie> Message-ID: <481861944.1291647711341.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBACCESS-19?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11908#action_11908 ] Eric Estievenart commented on LBACCESS-19: ------------------------------------------ In fact it seems to work if specifying a file relative to catalina home (at least in 0.9.26/linux/tomcat 6.0.29): filename="conf/logback-access-test.xml". Maybe a small line in the doc could say that ? Thx. > Cannot specify config file relative to catalina home > ---------------------------------------------------- > > Key: LBACCESS-19 > URL: http://jira.qos.ch/browse/LBACCESS-19 > Project: logback-access > Issue Type: Bug > Affects Versions: 0.9.26 > Environment: all > Reporter: Eric Estievenart > Assignee: Logback dev list > Priority: Trivial > > There is no way to refer to catalina home when specifying the filename of a logback valve. > What I would like to do is something like: > filename="${catalina.home}/conf/logback-access-test.xml" > /> > The only way for now is to specify an absolute path, which is not very convenient. > The system properties in the filename should be expanded in LogbackValve.start(). -- 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 From noreply-jira at qos.ch Mon Dec 6 16:42:51 2010 From: noreply-jira at qos.ch (Eric Estievenart (JIRA)) Date: Mon, 6 Dec 2010 16:42:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBACCESS-21) Report the request duration in logback-access Message-ID: <651187727.1291650171252.JavaMail.ceki@pixie> Report the request duration in logback-access --------------------------------------------- Key: LBACCESS-21 URL: http://jira.qos.ch/browse/LBACCESS-21 Project: logback-access Issue Type: Improvement Affects Versions: 0.9.26 Environment: any Reporter: Eric Estievenart Assignee: Logback dev list It would be great if the access valve (and corresponding in jetty/other) also stored the processing duration of the request within the container. For example add a %d field which would return this time in ms. -- 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 From noreply-jira at qos.ch Tue Dec 7 07:59:52 2010 From: noreply-jira at qos.ch (Denis Bazhenov (JIRA)) Date: Tue, 7 Dec 2010 07:59:52 +0100 (CET) Subject: [logback-dev] [JIRA] Updated: (LBACCESS-18) NPE is case of desrialized AccessEvent In-Reply-To: <1017980597.1291624431265.JavaMail.ceki@pixie> Message-ID: <2109604416.1291705192521.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBACCESS-18?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Denis Bazhenov updated LBACCESS-18: ----------------------------------- Attachment: LBACCESS-18.patch I created a simple patch. It's check for httpRequest == null and returns early. This patch makes SocketAppeder works in my installation > NPE is case of desrialized AccessEvent > -------------------------------------- > > Key: LBACCESS-18 > URL: http://jira.qos.ch/browse/LBACCESS-18 > Project: logback-access > Issue Type: Bug > Affects Versions: 0.9.26 > Environment: Sun Java HotSpot(TM) 64-Bit Server VM (build 16.2-b04, mixed mode) > CentOS Linux 2.6.18-164.el5 #1 SMP Thu Sep 3 03:28:30 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux > Reporter: Denis Bazhenov > Assignee: Logback dev list > Attachments: LBACCESS-18.patch > > > I'm trying to use SimpleSocketServer (from logback-access) for remote logging of AccessEvent's. The problem I faced is following. When object get deserialized in SocketNode on line 64 it has no httpRequest (it's simply null). There is debugger dump of event: > event = instance of ch.qos.logback.access.spi.AccessEvent(id=932) > Thread-1[1] dump event > event = { > serialVersionUID: 866718993618836343 > NA: "-" > NA_STRING_ARRAY: instance of java.lang.String[1] (id=914) > EMPTY: "" > SENTINEL: -1 > httpRequest: null > httpResponse: null > requestURI: "/" > requestURL: "GET / HTTP/1.1" > remoteHost: "192.168.20.179" > remoteUser: null > remoteAddr: "192.168.20.179" > protocol: "HTTP/1.1" > method: "GET" > serverName: "jetty-test" > requestContent: "" > responseContent: "" > requestHeaderMap: instance of java.util.TreeMap(id=938) > requestParameterMap: instance of java.util.HashMap(id=939) > responseHeaderMap: instance of java.util.HashMap(id=940) > contentLength: 1288 > statusCode: 503 > localPort: 8080 > serverAdapter: null > timeStamp: 1291621192027 > } > So later this gives me NPE in AccessEvent.buildRequestHeaderMap(). > I have following logback-access.xml for client > > > logs.vfarm.loc > 6000 > 100 > true > > class="ch.qos.logback.core.rolling.RollingFileAppender"> > /var/log/jetty/access.log > class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> > access.%d{yyyy-MM-dd}.log.zip > > > combined > > > > > > So logs are written locally (sucessfully) and sent over network to logs.vfarm.loc. On logs.vfarm.loc I have running SimpleSocketServer: > java -cp jetty-6.1.24.jar:\ > servlet-api-2.5.jar:\ > logback-access-0.9.26.jar:\ > slf4j-api-1.6.1.jar:\ > logback-core-0.9.26.jar \ > ch.qos.logback.access.net.SimpleSocketServer 6000 access.xml > with following access.xml > > > class="ch.qos.logback.core.ConsoleAppender"> > > combined > > > > > > I think this issue is closely related to LBACCESS-6, but it's still reproducible. -- 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 From noreply-jira at qos.ch Wed Dec 8 01:43:51 2010 From: noreply-jira at qos.ch (Mats Henrikson (JIRA)) Date: Wed, 8 Dec 2010 01:43:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBCORE-183) race condition when creating log directory in multithreaded environment Message-ID: <1880974034.1291769031316.JavaMail.ceki@pixie> race condition when creating log directory in multithreaded environment ----------------------------------------------------------------------- Key: LBCORE-183 URL: http://jira.qos.ch/browse/LBCORE-183 Project: logback-core Issue Type: Bug Components: Other Affects Versions: 0.9.26 Reporter: Mats Henrikson Assignee: Logback dev list Attachments: parent_dirs.patch There is a race condition when multiple threads are trying to create the same parent log directory in logback: {noformat} java.lang.IllegalStateException: /path/to/log/dir/2010/2010_12/2010_12_08/file.log should not have existing parent directory at ch.qos.logback.core.util.FileUtil.createMissingParentDirectories(FileUtil.java:43) ~[logback-core-0.9.26.jar:na] at ch.qos.logback.core.FileAppender.openFile(FileAppender.java:156) ~[logback-core-0.9.26.jar:na] at ch.qos.logback.core.FileAppender.start(FileAppender.java:115) ~[logback-core-0.9.26.jar:na] [...] {noformat} It is completely ok for the check to start if the directory is there and then have the directory appear when we actually come around to creating it. This is because you may have multiple threads wanting to log to the same directory, and if they try to create the dir at the same time one will succeed and one will have it already created. This happens for instance in the case above where a new dir is created at midnight every day, and two threads log at the same time. Will attach a patch that fixes the problem. -- 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 From noreply-jira at qos.ch Wed Dec 8 01:43:51 2010 From: noreply-jira at qos.ch (Mats Henrikson (JIRA)) Date: Wed, 8 Dec 2010 01:43:51 +0100 (CET) Subject: [logback-dev] [JIRA] Updated: (LBCORE-183) race condition when creating log directory in multithreaded environment In-Reply-To: <1880974034.1291769031316.JavaMail.ceki@pixie> Message-ID: <799003850.1291769031532.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-183?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Mats Henrikson updated LBCORE-183: ---------------------------------- Attachment: parent_dirs.patch > race condition when creating log directory in multithreaded environment > ----------------------------------------------------------------------- > > Key: LBCORE-183 > URL: http://jira.qos.ch/browse/LBCORE-183 > Project: logback-core > Issue Type: Bug > Components: Other > Affects Versions: 0.9.26 > Reporter: Mats Henrikson > Assignee: Logback dev list > Attachments: parent_dirs.patch > > > There is a race condition when multiple threads are trying to create the same parent log directory in logback: > {noformat} > java.lang.IllegalStateException: /path/to/log/dir/2010/2010_12/2010_12_08/file.log should not have existing parent directory > at ch.qos.logback.core.util.FileUtil.createMissingParentDirectories(FileUtil.java:43) ~[logback-core-0.9.26.jar:na] > at ch.qos.logback.core.FileAppender.openFile(FileAppender.java:156) ~[logback-core-0.9.26.jar:na] > at ch.qos.logback.core.FileAppender.start(FileAppender.java:115) ~[logback-core-0.9.26.jar:na] > [...] > {noformat} > It is completely ok for the check to start if the directory is there and then have the directory appear when we actually come around to creating it. This is because you may have multiple threads wanting to log to the same directory, and if they try to create the dir at the same time one will succeed and one will have it already created. This happens for instance in the case above where a new dir is created at midnight every day, and two threads log at the same time. > Will attach a patch that fixes the problem. -- 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 From noreply-jira at qos.ch Wed Dec 8 02:01:51 2010 From: noreply-jira at qos.ch (Denis Bazhenov (JIRA)) Date: Wed, 8 Dec 2010 02:01:51 +0100 (CET) Subject: [logback-dev] [JIRA] Updated: (LBACCESS-18) NPE is case of desrialized AccessEvent In-Reply-To: <1017980597.1291624431265.JavaMail.ceki@pixie> Message-ID: <1737054732.1291770111299.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBACCESS-18?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Denis Bazhenov updated LBACCESS-18: ----------------------------------- Attachment: (was: LBACCESS-18.patch) > NPE is case of desrialized AccessEvent > -------------------------------------- > > Key: LBACCESS-18 > URL: http://jira.qos.ch/browse/LBACCESS-18 > Project: logback-access > Issue Type: Bug > Affects Versions: 0.9.26 > Environment: Sun Java HotSpot(TM) 64-Bit Server VM (build 16.2-b04, mixed mode) > CentOS Linux 2.6.18-164.el5 #1 SMP Thu Sep 3 03:28:30 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux > Reporter: Denis Bazhenov > Assignee: Logback dev list > Attachments: LBACCESS-18.patch > > > I'm trying to use SimpleSocketServer (from logback-access) for remote logging of AccessEvent's. The problem I faced is following. When object get deserialized in SocketNode on line 64 it has no httpRequest (it's simply null). There is debugger dump of event: > event = instance of ch.qos.logback.access.spi.AccessEvent(id=932) > Thread-1[1] dump event > event = { > serialVersionUID: 866718993618836343 > NA: "-" > NA_STRING_ARRAY: instance of java.lang.String[1] (id=914) > EMPTY: "" > SENTINEL: -1 > httpRequest: null > httpResponse: null > requestURI: "/" > requestURL: "GET / HTTP/1.1" > remoteHost: "192.168.20.179" > remoteUser: null > remoteAddr: "192.168.20.179" > protocol: "HTTP/1.1" > method: "GET" > serverName: "jetty-test" > requestContent: "" > responseContent: "" > requestHeaderMap: instance of java.util.TreeMap(id=938) > requestParameterMap: instance of java.util.HashMap(id=939) > responseHeaderMap: instance of java.util.HashMap(id=940) > contentLength: 1288 > statusCode: 503 > localPort: 8080 > serverAdapter: null > timeStamp: 1291621192027 > } > So later this gives me NPE in AccessEvent.buildRequestHeaderMap(). > I have following logback-access.xml for client > > > logs.vfarm.loc > 6000 > 100 > true > > class="ch.qos.logback.core.rolling.RollingFileAppender"> > /var/log/jetty/access.log > class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> > access.%d{yyyy-MM-dd}.log.zip > > > combined > > > > > > So logs are written locally (sucessfully) and sent over network to logs.vfarm.loc. On logs.vfarm.loc I have running SimpleSocketServer: > java -cp jetty-6.1.24.jar:\ > servlet-api-2.5.jar:\ > logback-access-0.9.26.jar:\ > slf4j-api-1.6.1.jar:\ > logback-core-0.9.26.jar \ > ch.qos.logback.access.net.SimpleSocketServer 6000 access.xml > with following access.xml > > > class="ch.qos.logback.core.ConsoleAppender"> > > combined > > > > > > I think this issue is closely related to LBACCESS-6, but it's still reproducible. -- 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 From noreply-jira at qos.ch Wed Dec 8 02:01:51 2010 From: noreply-jira at qos.ch (Denis Bazhenov (JIRA)) Date: Wed, 8 Dec 2010 02:01:51 +0100 (CET) Subject: [logback-dev] [JIRA] Updated: (LBACCESS-18) NPE is case of desrialized AccessEvent In-Reply-To: <1017980597.1291624431265.JavaMail.ceki@pixie> Message-ID: <288942942.1291770111458.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBACCESS-18?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Denis Bazhenov updated LBACCESS-18: ----------------------------------- Attachment: LBACCESS-18.patch update a patch. fix another similar issue > NPE is case of desrialized AccessEvent > -------------------------------------- > > Key: LBACCESS-18 > URL: http://jira.qos.ch/browse/LBACCESS-18 > Project: logback-access > Issue Type: Bug > Affects Versions: 0.9.26 > Environment: Sun Java HotSpot(TM) 64-Bit Server VM (build 16.2-b04, mixed mode) > CentOS Linux 2.6.18-164.el5 #1 SMP Thu Sep 3 03:28:30 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux > Reporter: Denis Bazhenov > Assignee: Logback dev list > Attachments: LBACCESS-18.patch > > > I'm trying to use SimpleSocketServer (from logback-access) for remote logging of AccessEvent's. The problem I faced is following. When object get deserialized in SocketNode on line 64 it has no httpRequest (it's simply null). There is debugger dump of event: > event = instance of ch.qos.logback.access.spi.AccessEvent(id=932) > Thread-1[1] dump event > event = { > serialVersionUID: 866718993618836343 > NA: "-" > NA_STRING_ARRAY: instance of java.lang.String[1] (id=914) > EMPTY: "" > SENTINEL: -1 > httpRequest: null > httpResponse: null > requestURI: "/" > requestURL: "GET / HTTP/1.1" > remoteHost: "192.168.20.179" > remoteUser: null > remoteAddr: "192.168.20.179" > protocol: "HTTP/1.1" > method: "GET" > serverName: "jetty-test" > requestContent: "" > responseContent: "" > requestHeaderMap: instance of java.util.TreeMap(id=938) > requestParameterMap: instance of java.util.HashMap(id=939) > responseHeaderMap: instance of java.util.HashMap(id=940) > contentLength: 1288 > statusCode: 503 > localPort: 8080 > serverAdapter: null > timeStamp: 1291621192027 > } > So later this gives me NPE in AccessEvent.buildRequestHeaderMap(). > I have following logback-access.xml for client > > > logs.vfarm.loc > 6000 > 100 > true > > class="ch.qos.logback.core.rolling.RollingFileAppender"> > /var/log/jetty/access.log > class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> > access.%d{yyyy-MM-dd}.log.zip > > > combined > > > > > > So logs are written locally (sucessfully) and sent over network to logs.vfarm.loc. On logs.vfarm.loc I have running SimpleSocketServer: > java -cp jetty-6.1.24.jar:\ > servlet-api-2.5.jar:\ > logback-access-0.9.26.jar:\ > slf4j-api-1.6.1.jar:\ > logback-core-0.9.26.jar \ > ch.qos.logback.access.net.SimpleSocketServer 6000 access.xml > with following access.xml > > > class="ch.qos.logback.core.ConsoleAppender"> > > combined > > > > > > I think this issue is closely related to LBACCESS-6, but it's still reproducible. -- 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 From noreply-jira at qos.ch Wed Dec 8 02:25:51 2010 From: noreply-jira at qos.ch (Ralph Goers (JIRA)) Date: Wed, 8 Dec 2010 02:25:51 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBCORE-183) race condition when creating log directory in multithreaded environment In-Reply-To: <1880974034.1291769031316.JavaMail.ceki@pixie> Message-ID: <774394791.1291771551284.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-183?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11911#action_11911 ] Ralph Goers commented on LBCORE-183: ------------------------------------ Not that your patch is bad, but your description has to be incorrect. FileAppender.openFile() synchronizes on a lock so there is no way you can have a race from the same appender calling createMissingParentDirectories. From what I can see, the only way this can occur is if two different appenders are creating files in the same directory. > race condition when creating log directory in multithreaded environment > ----------------------------------------------------------------------- > > Key: LBCORE-183 > URL: http://jira.qos.ch/browse/LBCORE-183 > Project: logback-core > Issue Type: Bug > Components: Other > Affects Versions: 0.9.26 > Reporter: Mats Henrikson > Assignee: Logback dev list > Attachments: parent_dirs.patch > > > There is a race condition when multiple threads are trying to create the same parent log directory in logback: > {noformat} > java.lang.IllegalStateException: /path/to/log/dir/2010/2010_12/2010_12_08/file.log should not have existing parent directory > at ch.qos.logback.core.util.FileUtil.createMissingParentDirectories(FileUtil.java:43) ~[logback-core-0.9.26.jar:na] > at ch.qos.logback.core.FileAppender.openFile(FileAppender.java:156) ~[logback-core-0.9.26.jar:na] > at ch.qos.logback.core.FileAppender.start(FileAppender.java:115) ~[logback-core-0.9.26.jar:na] > [...] > {noformat} > It is completely ok for the check to start if the directory is there and then have the directory appear when we actually come around to creating it. This is because you may have multiple threads wanting to log to the same directory, and if they try to create the dir at the same time one will succeed and one will have it already created. This happens for instance in the case above where a new dir is created at midnight every day, and two threads log at the same time. > Will attach a patch that fixes the problem. -- 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 From noreply-jira at qos.ch Wed Dec 8 02:39:51 2010 From: noreply-jira at qos.ch (Mats Henrikson (JIRA)) Date: Wed, 8 Dec 2010 02:39:51 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBCORE-183) race condition when creating log directory in multithreaded environment In-Reply-To: <1880974034.1291769031316.JavaMail.ceki@pixie> Message-ID: <773347310.1291772391266.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-183?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11912#action_11912 ] Mats Henrikson commented on LBCORE-183: --------------------------------------- I wouldn't go as far as calling it incorrect, but I guess I should indeed have included appenders. Yes, it is indeed multiple appenders being logged to by different threads. If the appenders are logging to different files in the same directory then this can occur if the directory needs to be created. We see this pretty regularly. > race condition when creating log directory in multithreaded environment > ----------------------------------------------------------------------- > > Key: LBCORE-183 > URL: http://jira.qos.ch/browse/LBCORE-183 > Project: logback-core > Issue Type: Bug > Components: Other > Affects Versions: 0.9.26 > Reporter: Mats Henrikson > Assignee: Logback dev list > Attachments: parent_dirs.patch > > > There is a race condition when multiple threads are trying to create the same parent log directory in logback: > {noformat} > java.lang.IllegalStateException: /path/to/log/dir/2010/2010_12/2010_12_08/file.log should not have existing parent directory > at ch.qos.logback.core.util.FileUtil.createMissingParentDirectories(FileUtil.java:43) ~[logback-core-0.9.26.jar:na] > at ch.qos.logback.core.FileAppender.openFile(FileAppender.java:156) ~[logback-core-0.9.26.jar:na] > at ch.qos.logback.core.FileAppender.start(FileAppender.java:115) ~[logback-core-0.9.26.jar:na] > [...] > {noformat} > It is completely ok for the check to start if the directory is there and then have the directory appear when we actually come around to creating it. This is because you may have multiple threads wanting to log to the same directory, and if they try to create the dir at the same time one will succeed and one will have it already created. This happens for instance in the case above where a new dir is created at midnight every day, and two threads log at the same time. > Will attach a patch that fixes the problem. -- 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 From noreply-jira at qos.ch Thu Dec 9 11:05:52 2010 From: noreply-jira at qos.ch (Dieter Mueller (JIRA)) Date: Thu, 9 Dec 2010 11:05:52 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBCORE-147) RollingPolicy MaxHistory not deleting old files In-Reply-To: <1427078273.1269441196428.JavaMail.ceki@pixie> Message-ID: <961942434.1291889152262.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-147?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11913#action_11913 ] Dieter Mueller commented on LBCORE-147: --------------------------------------- I just tested it with current version 0.9.26 and verified the bug. config: foo-%d{yyyy-MM-dd}.%i.log.zip 4 20MB But the main key is, that the application did not run for some days: e.g. Today (09.12.) I had logfiles from 1.12, 2.12., 3.12, 4.12. 5.12., 6.12. When I started the app, then the logfile from 4.12. (older than 4 days) was deleted, but the older ones (1.12. 2.12., 3.12) were not deleted. It seems, that logback calculates the ONE day to be deleted. It does not look back into the past, which is reasonable to me, because how far it should look back? regards, Dieter Mueller > RollingPolicy MaxHistory not deleting old files > ----------------------------------------------- > > Key: LBCORE-147 > URL: http://jira.qos.ch/browse/LBCORE-147 > Project: logback-core > Issue Type: Bug > Components: Rolling > Affects Versions: 0.9.18 > Environment: linux 2.6.18 64bits apache-tomcat-6.0.20 java/jre1.6.0_18 > Reporter: Rafael Diaz Maurin > Assignee: Ceki Gulcu > > The MaxHistory does not do the trick : the old files are not deleted at all : > cat logging.xml > > /shibboleth-idp/logs/idp-access.log > false > true > > /shibboleth-idp/logs/old/idp-access-%d{yyyy-MM-dd_HH-mm}.log.gz > 3 > > > %msg%n > > -- 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 From noreply-jira at qos.ch Thu Dec 9 11:24:51 2010 From: noreply-jira at qos.ch (Dieter Mueller (JIRA)) Date: Thu, 9 Dec 2010 11:24:51 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBCORE-147) RollingPolicy MaxHistory not deleting old files In-Reply-To: <1427078273.1269441196428.JavaMail.ceki@pixie> Message-ID: <935760003.1291890291285.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-147?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11914#action_11914 ] Dieter Mueller commented on LBCORE-147: --------------------------------------- I wrote: >It seems, that logback calculates the ONE day to be deleted. It does not look back into the past, which is reasonable to me, >because how far it should look back? Perhaps a simple but unorthodox way would be, if there is a list (e.g. property-file) of created log files is maintained and persisted by logback. On every rollover the list is loaded and checked for old, deleteable files. I assume, the list would not be that big, so that there should be no big performance impact. One additional sugar piece would be, that if the filename patten (e.g. directory structure) is changed between a run of the application, logback will still be able, to delete an old logfile, which does not follow the new (changed) file name pattern. On the other hand, concurent access to this file via threads or several VMs will have to be synchronized? Dieter Mueller > RollingPolicy MaxHistory not deleting old files > ----------------------------------------------- > > Key: LBCORE-147 > URL: http://jira.qos.ch/browse/LBCORE-147 > Project: logback-core > Issue Type: Bug > Components: Rolling > Affects Versions: 0.9.18 > Environment: linux 2.6.18 64bits apache-tomcat-6.0.20 java/jre1.6.0_18 > Reporter: Rafael Diaz Maurin > Assignee: Ceki Gulcu > > The MaxHistory does not do the trick : the old files are not deleted at all : > cat logging.xml > > /shibboleth-idp/logs/idp-access.log > false > true > > /shibboleth-idp/logs/old/idp-access-%d{yyyy-MM-dd_HH-mm}.log.gz > 3 > > > %msg%n > > -- 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 From noreply-jira at qos.ch Sat Dec 11 17:21:52 2010 From: noreply-jira at qos.ch (Eric Estievenart (JIRA)) Date: Sat, 11 Dec 2010 17:21:52 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBCLASSIC-235) Should log an error if -Dlogback.configurationFile but not found, and not attempt default config Message-ID: <1385607978.1292084512352.JavaMail.ceki@pixie> Should log an error if -Dlogback.configurationFile but not found, and not attempt default config ------------------------------------------------------------------------------------------------ Key: LBCLASSIC-235 URL: http://jira.qos.ch/browse/LBCLASSIC-235 Project: logback-classic Issue Type: Bug Affects Versions: 0.9.26 Reporter: Eric Estievenart Assignee: Logback dev list $ java -Dlogback.configurationFile=missingfile.xml -cp .... MyClass >> no output is generated A status dump says: 16:14:01,778 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [missingfile.xml] 16:14:01,779 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy] 16:14:01,779 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml] 16:14:01,780 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.xml] 16:14:01,786 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Setting up default configuration. First, logback should issue an error saying that the explicitely selected 'missingfile' was not found. Then I don't thing that it should try to load default config files, since one has been requested by the user. -- 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 From noreply-jira at qos.ch Sat Dec 11 17:23:51 2010 From: noreply-jira at qos.ch (Eric Estievenart (JIRA)) Date: Sat, 11 Dec 2010 17:23:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBCLASSIC-236) Provide a way to tell wether logback has defaulted to a default configuration. Message-ID: <433482092.1292084631247.JavaMail.ceki@pixie> Provide a way to tell wether logback has defaulted to a default configuration. ------------------------------------------------------------------------------ Key: LBCLASSIC-236 URL: http://jira.qos.ch/browse/LBCLASSIC-236 Project: logback-classic Issue Type: Improvement Affects Versions: 0.9.26 Reporter: Eric Estievenart Assignee: Logback dev list Priority: Minor There is no way to know if logback is using its default configuration or one supplied explicitly or found in resources. LoggerContext.getName() returns "default" for the default config or for one which has no name given. -- 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 From noreply-jira at qos.ch Sun Dec 12 18:54:52 2010 From: noreply-jira at qos.ch (Eric Estievenart (JIRA)) Date: Sun, 12 Dec 2010 18:54:52 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBCORE-184) FileAppender should permit lazy file creation Message-ID: <1668306216.1292176492303.JavaMail.ceki@pixie> FileAppender should permit lazy file creation --------------------------------------------- Key: LBCORE-184 URL: http://jira.qos.ch/browse/LBCORE-184 Project: logback-core Issue Type: New Feature Components: Appender Affects Versions: 0.9.26 Reporter: Eric Estievenart Assignee: Logback dev list There should be an option to allow lazy file creation, so that the files are created only when an event has to be logged into it, and not when the appender starts. The main idea behind that is that I dislike seeing files like ERROR.log (or even worse CRASH.log !) in the log folders, even if their size is zero. And these files are probably even rolled over (at least with time based policy), which can generate many (empty and useless) files with frightening names. I think that something like true ... would be very convenient, as well as a way to globally set all file based appenders lazy (or not) at once: (or whatever people may find more convenient, maybe ) (because you may not want to add that on a dozen or more file appenders). This applies to all file appenders, including rolling ones, and maybe others ? BTW, the more I use logback the more impressed I am. You deserve a gold medal for your good job guys ! (and I don't give so many) -- 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 From git-noreply at pixie.qos.ch Mon Dec 13 17:17:23 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Mon, 13 Dec 2010 17:17:23 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-41-gfc45086 Message-ID: <20101213161724.5E80A31702C@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via fc4508616906b773dd9d93d4e0d2c45628d3f7b5 (commit) from 1c9ce863a577cf5075088eb66ca5353f4de0e209 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=fc4508616906b773dd9d93d4e0d2c45628d3f7b5 http://github.com/ceki/logback/commit/fc4508616906b773dd9d93d4e0d2c45628d3f7b5 commit fc4508616906b773dd9d93d4e0d2c45628d3f7b5 Author: Ceki Gulcu Date: Mon Dec 13 17:17:28 2010 +0100 add support for dynamic destination address computation in SMTPAppender diff --git a/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java b/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java index 40917f3..43590ed 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java +++ b/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java @@ -182,5 +182,4 @@ public class PatternLayout extends PatternLayoutBase { } super.start(); } - } diff --git a/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java b/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java index 4d48cc8..4584e4f 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java +++ b/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java @@ -79,4 +79,12 @@ public class SMTPAppender extends SMTPAppenderBase { pl.start(); return pl; } + + protected PatternLayout makeNewToPatternLayout(String toPattern) { + PatternLayout pl = new PatternLayout(); + pl.setPattern(toPattern); + return pl; + } + + } diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java b/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java index a3fc208..3a6442d 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java @@ -139,5 +139,4 @@ public class PatternLayout extends PatternLayoutBase { } return writeLoopOnConverters(event); } - } diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java index c30e24c..262bd91 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java @@ -101,4 +101,10 @@ public class SMTPAppender extends SMTPAppenderBase { pl.start(); return pl; } + + protected PatternLayout makeNewToPatternLayout(String toPattern) { + PatternLayout pl = new PatternLayout(); + pl.setPattern(toPattern+"%nopex"); + return pl; + } } diff --git a/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegateTest.groovy b/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegateTest.groovy index ea94697..2e5d65f 100644 --- a/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegateTest.groovy +++ b/logback-classic/src/test/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegateTest.groovy @@ -189,7 +189,7 @@ class ConfigurationDelegateTest { PatternLayout layout = sa.layout assertEquals("%m%n", layout.pattern) - assertEquals(["a", "b"], sa.toList.sort()); + assertEquals(["a%nopex", "b%nopex"], sa.getToAsListOfString().sort()); } // test parent injection diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java index 5e3f912..53bbc0c 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java @@ -81,9 +81,7 @@ public class DilutedSMTPAppenderTest { addressArray = null; address = null; - addressArray = appender.getMessage().getAllRecipients(); - address = addressArray[0]; - assertEquals("sebastien.nospam at qos.ch", address.toString()); + assertEquals("sebastien.nospam at qos.ch%nopex", appender.getToAsListOfString().get(0)); assertEquals("logging report", appender.getSubject()); diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/PackageTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/PackageTest.java index 076d7ca..f97ea53 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/PackageTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/PackageTest.java @@ -19,6 +19,7 @@ import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) @SuiteClasses( { SyslogAppenderTest.class, DilutedSMTPAppenderTest.class, - SocketAppenderTest.class, JMSQueueAppenderTest.class, JMSTopicAppenderTest.class }) + SocketAppenderTest.class, JMSQueueAppenderTest.class, JMSTopicAppenderTest.class, + SMTPAppender_GreenTest.class, SMTPAppender_SubethaSMTPTest.class }) public class PackageTest { } \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java index 6d1ee31..01f9dbe 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java @@ -35,6 +35,7 @@ import ch.qos.logback.core.Layout; import ch.qos.logback.core.boolex.EvaluationException; import ch.qos.logback.core.boolex.EventEvaluator; import ch.qos.logback.core.helpers.CyclicBuffer; +import ch.qos.logback.core.pattern.PatternLayoutBase; import ch.qos.logback.core.sift.DefaultDiscriminator; import ch.qos.logback.core.sift.Discriminator; import ch.qos.logback.core.spi.CyclicBufferTracker; @@ -58,18 +59,21 @@ import ch.qos.logback.core.util.OptionHelper; */ public abstract class SMTPAppenderBase extends AppenderBase { - + static InternetAddress[] EMPTY_IA_ARRAY = new InternetAddress[0]; // ~ 14 days static final int MAX_DELAY_BETWEEN_STATUS_MESSAGES = 1228800 * CoreConstants.MILLIS_IN_ONE_SECOND; long lastTrackerStatusPrint = 0; int delayBetweenStatusMessages = 300 * CoreConstants.MILLIS_IN_ONE_SECOND; + + + protected Layout subjectLayout; protected Layout layout; - private List toList = new ArrayList(); + private List> toPatternLayoutList = new ArrayList>(); private String from; private String subjectStr = null; private String smtpHost; @@ -150,8 +154,6 @@ public abstract class SMTPAppenderBase extends AppenderBase { mimeMsg.setFrom(); } - mimeMsg.setRecipients(Message.RecipientType.TO, parseAddress(toList)); - subjectLayout = makeSubjectLayout(subjectStr); started = true; @@ -190,7 +192,7 @@ public abstract class SMTPAppenderBase extends AppenderBase { if (lastTrackerStatusPrint + delayBetweenStatusMessages < now) { addInfo("SMTPAppender [" + name + "] is tracking [" + cbTracker.size() + "] buffers"); lastTrackerStatusPrint = now; - // quadruple 'delay' assuming less than max delay + // quadruple 'delay' assuming less than max delay if (delayBetweenStatusMessages < MAX_DELAY_BETWEEN_STATUS_MESSAGES) { delayBetweenStatusMessages *= 4; } @@ -246,29 +248,35 @@ public abstract class SMTPAppenderBase extends AppenderBase { } } - InternetAddress[] parseAddress(List addressList) { + private List parseAddress(E event) { + int len = toPatternLayoutList.size(); - InternetAddress[] iaArray = new InternetAddress[addressList.size()]; + List iaList = new ArrayList(); - for (int i = 0; i < addressList.size(); i++) { + for (int i = 0; i < len; i++) { try { - InternetAddress[] tmp = InternetAddress.parse(addressList.get(i), true); + PatternLayoutBase emailPL = toPatternLayoutList.get(i); + String email = emailPL.doLayout(event); + if(email == null || email.length() == 0) { + continue; + } + InternetAddress[] tmp = InternetAddress.parse(email, true); // one element should contain one email address - iaArray[i] = tmp[0]; + iaList.add(tmp[0]); } catch (AddressException e) { - addError("Could not parse address [" + addressList.get(i) + "].", e); - return null; + addError("Could not parse email address for [" + toPatternLayoutList.get(i) + "] for event ["+event+"]", e); + return iaList; } } - return iaArray; + return iaList; } /** * Returns value of the toList option. */ - public List getToList() { - return toList; + public List> getToList() { + return toPatternLayoutList; } /** @@ -306,6 +314,13 @@ public abstract class SMTPAppenderBase extends AppenderBase { charsetEncoding); } + List destinationAddresses = parseAddress(lastEventObject); + if(destinationAddresses.isEmpty()) { + addInfo("Empty destination address. Aborting email transmission"); + return; + } + mimeMsg.setRecipients(Message.RecipientType.TO, destinationAddresses.toArray(EMPTY_IA_ARRAY)); + String contentType = layout.getContentType(); if (ContentTypeUtil.isTextual(contentType)) { @@ -326,6 +341,8 @@ public abstract class SMTPAppenderBase extends AppenderBase { } } + + abstract protected void fillBuffer(CyclicBuffer cb, StringBuffer sbuf); /** @@ -437,17 +454,28 @@ public abstract class SMTPAppenderBase extends AppenderBase { this.discriminator = discriminator; } - /** - * The To option takes a string value which should be an e-mail address - * of one of the recipients. - */ public void addTo(String to) { - this.toList.add(to); + if(to == null || to.length() == 0) { + throw new IllegalArgumentException("Null or empty property"); + } + PatternLayoutBase plb = makeNewToPatternLayout(to.trim()); + plb.setContext(context); + plb.start(); + this.toPatternLayoutList.add(plb); } - // for testing purpose only + abstract protected PatternLayoutBase makeNewToPatternLayout(String toPattern); + + public List getToAsListOfString() { + List toList = new ArrayList(); + for(PatternLayoutBase plb: toPatternLayoutList) { + toList.add(plb.getPattern()); + } + return toList; + } - public Message getMessage() { + // for testing purpose only + public Message getMessage() { return mimeMsg; } diff --git a/logback-site/src/site/pages/recipes/captureHttp.html b/logback-site/src/site/pages/recipes/captureHttp.html index 244478a..86488e6 100644 --- a/logback-site/src/site/pages/recipes/captureHttp.html +++ b/logback-site/src/site/pages/recipes/captureHttp.html @@ -200,11 +200,11 @@ Set-Cookie: JSESSIONID=bgebt99ce9om;path=/logback-demo probe made by the load-balancer.

-

We need to a way to filter-out these probes so that they are - no longer contaminate the log output. However, we need a way to +

We need to a way to filter-out these probes so that they no + longer contaminate the log output. In other words, we need to distinguish probes emanating from the load-balancer from other - requests that we deem desirable. The contents of the requests - can give you clues about possible criteria.

+ requests. The contents of the probes can give us clues about + possible distinguishing criteria.

Here is a sample probe as logged by logback-access:

@@ -218,16 +218,17 @@ X-Powered-By: Servlet 2.4; Cache-Control: no-cache Pragma: No-cache -

From the above, we can see that the load-blancer probes use - the From the above, we can see that the load-blancer probes + employ the HTTP HEAD method instead of the usual GET or POST. We can also see that the request URI for the probes contains the string "probe".

Here is a logback-access.xml configuration file - which will deny any access event which uses the HEAD - method. Note that it is based on Janino.

+ which will deny any AccessEvent where the method is + HEAD. Note that events are evaluated using + JaninoEventEvaluator which requires Janino.

<configuration>
   <!-- always a good idea to install OnConsoleStatusListener -->

-----------------------------------------------------------------------

Summary of changes:
 .../java/ch/qos/logback/access/PatternLayout.java  |    1 -
 .../ch/qos/logback/access/net/SMTPAppender.java    |    8 ++
 .../java/ch/qos/logback/classic/PatternLayout.java |    1 -
 .../ch/qos/logback/classic/net/SMTPAppender.java   |    6 ++
 .../gaffer/ConfigurationDelegateTest.groovy        |    2 +-
 .../classic/net/DilutedSMTPAppenderTest.java       |    4 +-
 .../ch/qos/logback/classic/net/PackageTest.java    |    3 +-
 .../ch/qos/logback/core/net/SMTPAppenderBase.java  |   72 ++++++++++++++------
 .../src/site/pages/recipes/captureHttp.html        |   17 +++--
 9 files changed, 77 insertions(+), 37 deletions(-)


hooks/post-receive
-- 
Logback: the generic, reliable, fast and flexible logging framework.

From noreply-jira at qos.ch  Mon Dec 13 19:08:51 2010
From: noreply-jira at qos.ch (subes (JIRA))
Date: Mon, 13 Dec 2010 19:08:51 +0100 (CET)
Subject: [logback-dev] [JIRA] Created: (LBCLASSIC-237) create a
 DelegateAppender which delegates all events to multiple child appenders
Message-ID: <32647700.1292263731278.JavaMail.ceki@pixie>

create a DelegateAppender which delegates all events to multiple child appenders
--------------------------------------------------------------------------------

                 Key: LBCLASSIC-237
                 URL: http://jira.qos.ch/browse/LBCLASSIC-237
             Project: logback-classic
          Issue Type: New Feature
          Components: appender
    Affects Versions: unspecified
            Reporter: subes
            Assignee: Logback dev list


Hi,

I'm using LogBack now since some time and got a config that suits me quite well, which i even modularized by merging multiple logback xml files to one and giving that as the configuration to logback. Thats needed because I am building a modular software productline with decentral configuration per module which have their own eclipse project.

I have two default console appenders. One for System.out (level<=INFO) called "stdout" and another one for System.err (level>=WARN) called "stderr". 
On top of that I got two default log files. One for all the stuff that goes to both console appenders called "default" and another one for detailed error stacktraces called "error". I do that because I filter stacktraces for console but still want to have access to the complete stacktraces in another log file specific for that purpose. And beside those loggers my modules can create other file appenders like sql.log or messages.log and stuff.

Now to my point: Because I have 4 appenders I almost always use together (2x console and 2x file), i have quite a lot of appender-refs I have to write on my logger definitions. To help with that, I would like to have an appender (called "common") which has the other 4 appenders as children like this:


    
    
    
    
    
    
        
    


With that I could either just put "common" on a logger to print to all 4 appenders or I would still have the flexibility to specify only one of those appers.
I tried to implement this on my own, Implementing the appender class itself wasn't a problem, but I don't get how to make joran to understand the appender-ref and insert the delegate appender class into my DelegatingAppender via some setter. It would be nice if you could either include this as a feature into logback-classic or help me out writing it on my own. :)


-- 
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

        

From noreply-jira at qos.ch  Mon Dec 13 19:11:51 2010
From: noreply-jira at qos.ch (subes (JIRA))
Date: Mon, 13 Dec 2010 19:11:51 +0100 (CET)
Subject: [logback-dev] [JIRA] Commented: (LBCLASSIC-237) create a
 DelegateAppender which delegates all events to multiple child appenders
In-Reply-To: <32647700.1292263731278.JavaMail.ceki@pixie>
Message-ID: <648011091.1292263911330.JavaMail.ceki@pixie>


    [ http://jira.qos.ch/browse/LBCLASSIC-237?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11915#action_11915 ] 

subes commented on LBCLASSIC-237:
---------------------------------

I also looked at the SiftingAppender, but that one creates appenders on demand via an AppenderFactory, which is not actually what I want to achieve.

> create a DelegateAppender which delegates all events to multiple child appenders
> --------------------------------------------------------------------------------
>
>                 Key: LBCLASSIC-237
>                 URL: http://jira.qos.ch/browse/LBCLASSIC-237
>             Project: logback-classic
>          Issue Type: New Feature
>          Components: appender
>    Affects Versions: unspecified
>            Reporter: subes
>            Assignee: Logback dev list
>
> Hi,
> I'm using LogBack now since some time and got a config that suits me quite well, which i even modularized by merging multiple logback xml files to one and giving that as the configuration to logback. Thats needed because I am building a modular software productline with decentral configuration per module which have their own eclipse project.
> I have two default console appenders. One for System.out (level<=INFO) called "stdout" and another one for System.err (level>=WARN) called "stderr". 
> On top of that I got two default log files. One for all the stuff that goes to both console appenders called "default" and another one for detailed error stacktraces called "error". I do that because I filter stacktraces for console but still want to have access to the complete stacktraces in another log file specific for that purpose. And beside those loggers my modules can create other file appenders like sql.log or messages.log and stuff.
> Now to my point: Because I have 4 appenders I almost always use together (2x console and 2x file), i have quite a lot of appender-refs I have to write on my logger definitions. To help with that, I would like to have an appender (called "common") which has the other 4 appenders as children like this:
> 
>     
>     
>     
>     
>     
>     
>         
>     
> 
> With that I could either just put "common" on a logger to print to all 4 appenders or I would still have the flexibility to specify only one of those appers.
> I tried to implement this on my own, Implementing the appender class itself wasn't a problem, but I don't get how to make joran to understand the appender-ref and insert the delegate appender class into my DelegatingAppender via some setter. It would be nice if you could either include this as a feature into logback-classic or help me out writing it on my own. :)

-- 
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

        

From noreply-jira at qos.ch  Mon Dec 13 19:13:51 2010
From: noreply-jira at qos.ch (subes (JIRA))
Date: Mon, 13 Dec 2010 19:13:51 +0100 (CET)
Subject: [logback-dev] [JIRA] Issue Comment Edited: (LBCLASSIC-237) create a
 DelegateAppender which delegates all events to multiple child appenders
In-Reply-To: <32647700.1292263731278.JavaMail.ceki@pixie>
Message-ID: <2120721631.1292264031271.JavaMail.ceki@pixie>


    [ http://jira.qos.ch/browse/LBCLASSIC-237?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11915#action_11915 ] 

subes edited comment on LBCLASSIC-237 at 12/13/10 7:12 PM:
-----------------------------------------------------------

I also looked at the SiftingAppender, but that one creates appenders on demand via an AppenderFactory, which is not actually what I want to achieve. And hacking that to acommodate my wishes seemed hard and quite naughty :)

      was (Author: subes):
    I also looked at the SiftingAppender, but that one creates appenders on demand via an AppenderFactory, which is not actually what I want to achieve.
  
> create a DelegateAppender which delegates all events to multiple child appenders
> --------------------------------------------------------------------------------
>
>                 Key: LBCLASSIC-237
>                 URL: http://jira.qos.ch/browse/LBCLASSIC-237
>             Project: logback-classic
>          Issue Type: New Feature
>          Components: appender
>    Affects Versions: unspecified
>            Reporter: subes
>            Assignee: Logback dev list
>
> Hi,
> I'm using LogBack now since some time and got a config that suits me quite well, which i even modularized by merging multiple logback xml files to one and giving that as the configuration to logback. Thats needed because I am building a modular software productline with decentral configuration per module which have their own eclipse project.
> I have two default console appenders. One for System.out (level<=INFO) called "stdout" and another one for System.err (level>=WARN) called "stderr". 
> On top of that I got two default log files. One for all the stuff that goes to both console appenders called "default" and another one for detailed error stacktraces called "error". I do that because I filter stacktraces for console but still want to have access to the complete stacktraces in another log file specific for that purpose. And beside those loggers my modules can create other file appenders like sql.log or messages.log and stuff.
> Now to my point: Because I have 4 appenders I almost always use together (2x console and 2x file), i have quite a lot of appender-refs I have to write on my logger definitions. To help with that, I would like to have an appender (called "common") which has the other 4 appenders as children like this:
> 
>     
>     
>     
>     
>     
>     
>         
>     
> 
> With that I could either just put "common" on a logger to print to all 4 appenders or I would still have the flexibility to specify only one of those appers.
> I tried to implement this on my own, Implementing the appender class itself wasn't a problem, but I don't get how to make joran to understand the appender-ref and insert the delegate appender class into my DelegatingAppender via some setter. It would be nice if you could either include this as a feature into logback-classic or help me out writing it on my own. :)

-- 
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

        

From git-noreply at pixie.qos.ch  Wed Dec 15 19:07:08 2010
From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo)
Date: Wed, 15 Dec 2010 19:07:08 +0100 (CET)
Subject: [logback-dev] [GIT] Logback: the generic, reliable,
	fast and flexible logging framework. branch, master,
	updated. v_0.9.25-42-g2742a97
Message-ID: <20101215180709.82F0A317077@pixie.qos.ch>

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Logback: the generic, reliable, fast and flexible logging framework.".

The branch, master has been updated
       via  2742a97de478cd3fc270223816eaa1c24d13cd82 (commit)
      from  fc4508616906b773dd9d93d4e0d2c45628d3f7b5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=2742a97de478cd3fc270223816eaa1c24d13cd82
http://github.com/ceki/logback/commit/2742a97de478cd3fc270223816eaa1c24d13cd82

commit 2742a97de478cd3fc270223816eaa1c24d13cd82
Author: Ceki Gulcu 
Date:   Wed Dec 15 19:07:04 2010 +0100

    adding support for composite keywords

diff --git a/goscp b/goscp
new file mode 100644
index 0000000..406a6ae
--- /dev/null
+++ b/goscp
@@ -0,0 +1,3 @@
+TARGET=cgulcu at hqchnesoa07:/srv/jboss-eap-4.3.0.GA_CP05/jboss-as/server/nesoa-04-esb-01/lib/
+
+scp logback-core/target/logback-core-0.9.27-SNAPSHOT.jar logback-classic/target/logback-classic-0.9.27-SNAPSHOT.jar logback-access/target/logback-access-0.9.27-SNAPSHOT.jar   $TARGET
\ No newline at end of file
diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/DateConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/DateConverter.java
index 84226b5..4f0a449 100644
--- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/DateConverter.java
+++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/DateConverter.java
@@ -29,6 +29,7 @@ public class DateConverter extends ClassicConverter {
 
   public void start() {
 
+
     String datePattern = getFirstOption();
     if (datePattern == null) {
       datePattern = CoreConstants.ISO8601_PATTERN;
diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java
index 4259f26..546a653 100644
--- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java
+++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java
@@ -179,7 +179,7 @@ public class ReconfigureOnChangeTest {
     // we can't have the test succeed under JDK 1.5, punt and require 1.6+
     if (Env.isJDK6OrHigher()) {
       assertTrue(failMsg,
-          (effectiveResets * 1.3) >= (expectedReconfigurations * 1.0));
+          (effectiveResets * 1.4) >= (expectedReconfigurations * 1.0));
     }
   }
 
diff --git a/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java b/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java
index 0ba51b4..05f1a7b 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/OutputStreamAppender.java
@@ -210,8 +210,9 @@ public class OutputStreamAppender extends UnsynchronizedAppenderBase {
       if (event instanceof DeferredProcessingAware) {
         ((DeferredProcessingAware) event).prepareForDeferredProcessing();
       }
-      // the synchronized prevents the OutputStream from being closed while we
-      // are writing
+      // the synchronization prevents the OutputStream from being closed while we
+      // are writing. It also prevents multiple thread from entering the same
+      // converter. Converters assume that they are in a synchronized block.
       synchronized (lock) {
         writeOut(event);
       }
diff --git a/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java b/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java
index 5ee84d0..af16edf 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java
@@ -83,7 +83,7 @@ public abstract class HTMLLayoutBase extends LayoutBase {
       Parser p = new Parser(pattern);
       p.setContext(getContext());
       Node t = p.parse();
-      this.head = p.compile(t, getEffectiveConverterMap());
+      this.head = p.compile(t, getEffectiveConverterMap(), Parser.DEFAULT_COMPOSITE_CONVERTER_MAP);
       ConverterUtil.startConverters(this.head);
     } catch (ScanException ex) {
       addError("Incorrect pattern found", ex);
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/CompositeConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/CompositeConverter.java
index 07e352e..bad3c8c 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/CompositeConverter.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/CompositeConverter.java
@@ -1,6 +1,6 @@
 /**
  * Logback: the reliable, generic, fast and flexible logging framework.
- * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
+ * Copyright (C) 1999-2010, QOS.ch. All rights reserved.
  *
  * This program and the accompanying materials are dual-licensed under
  * either the terms of the Eclipse Public License v1.0 as published by
@@ -13,24 +13,22 @@
  */
 package ch.qos.logback.core.pattern;
 
-public class CompositeConverter extends FormattingConverter {
+abstract public class CompositeConverter extends DynamicConverter {
 
-  StringBuilder buf = new StringBuilder();
   Converter childConverter;
 
   public String convert(E event) {
-    if (buf.capacity() > MAX_CAPACITY) {
-      buf = new StringBuilder(INITIAL_BUF_SIZE);
-    } else {
-      buf.setLength(0);
-    }
+    StringBuilder buf = new StringBuilder();
 
     for (Converter c = childConverter; c != null; c = c.next) {
       c.write(buf, event);
     }
-    return buf.toString();
+    String intermediary = buf.toString();
+    return transform(intermediary);
   }
 
+  abstract String transform(String in);
+
   public void setChildConverter(Converter child) {
     childConverter = child;
   }
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/ConverterUtil.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/ConverterUtil.java
index 03f65e8..1dc12b2 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/ConverterUtil.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/ConverterUtil.java
@@ -17,25 +17,28 @@ public class ConverterUtil {
 
   /**
    * Start converters in the chain of converters.
+   *
    * @param head
    */
   public static void startConverters(Converter head) {
     Converter c = head;
     while (c != null) {
-      if (c instanceof DynamicConverter) {
-        DynamicConverter dc = (DynamicConverter) c;
-        dc.start();
-      } else if(c instanceof CompositeConverter){
+      // CompositeConverter is a subclass of  DynamicConverter
+      if (c instanceof CompositeConverter) {
         CompositeConverter cc = (CompositeConverter) c;
         Converter childConverter = cc.childConverter;
         startConverters(childConverter);
+        cc.start();
+      } else if (c instanceof DynamicConverter) {
+        DynamicConverter dc = (DynamicConverter) c;
+        dc.start();
       }
       c = c.getNext();
     }
   }
 
-  
-  public static Converter findTail(Converter head) {
+
+  public static  Converter findTail(Converter head) {
     Converter p = head;
     while (p != null) {
       Converter next = p.getNext();
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java
index 53eb3b8..cdb0958 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java
@@ -21,7 +21,7 @@ abstract public class DynamicConverter extends FormattingConverter
     implements LifeCycle {
 
   // Contains a list of option Strings.
-  private List optionList;
+  private List optionList;
 
   /**
    * Is this component active?
@@ -46,7 +46,7 @@ abstract public class DynamicConverter extends FormattingConverter
     return started;
   }
 
-  public void setOptionList(List optionList) {
+  public void setOptionList(List optionList) {
     this.optionList = optionList;
   }
 
@@ -60,11 +60,11 @@ abstract public class DynamicConverter extends FormattingConverter
     if (optionList == null || optionList.size() == 0) {
       return null;
     } else {
-      return (String) optionList.get(0);
+      return optionList.get(0);
     }
   }
 
-  protected List getOptionList() {
+  protected List getOptionList() {
     return optionList;
   }
 }
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/IdentityCompositeConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/IdentityCompositeConverter.java
new file mode 100644
index 0000000..473ff6c
--- /dev/null
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/IdentityCompositeConverter.java
@@ -0,0 +1,22 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2010, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ *   or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package ch.qos.logback.core.pattern;
+
+public class IdentityCompositeConverter extends CompositeConverter {
+
+  @Override
+  String transform(String in) {
+    return in;
+  }
+}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java
index d507887..e60ee6f 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java
@@ -81,7 +81,7 @@ abstract public class PatternLayoutBase extends LayoutBase {
         p.setContext(getContext());
       }
       Node t = p.parse();
-      this.head = p.compile(t, getEffectiveConverterMap());
+      this.head = p.compile(t, getEffectiveConverterMap(), Parser.DEFAULT_COMPOSITE_CONVERTER_MAP);
       if (postCompileProcessor != null) {
         postCompileProcessor.process(head);
       }
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
new file mode 100644
index 0000000..c5e29ef
--- /dev/null
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
@@ -0,0 +1,31 @@
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2010, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ *   or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package ch.qos.logback.core.pattern;
+
+import java.util.List;
+
+public class ReplacingCompositeConverter extends CompositeConverter {
+
+  String regex;
+  String by;
+
+  public void start() {
+     final List optionList = getOptionList();
+     regex = optionList.get(0);
+  }
+  @Override
+  String transform(String in) {
+    return null;  //To change body of implemented methods use File | Settings | File Templates.
+  }
+}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java
index bc94153..9bcb1a6 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java
@@ -15,10 +15,7 @@ package ch.qos.logback.core.pattern.parser;
 
 import java.util.Map;
 
-import ch.qos.logback.core.pattern.CompositeConverter;
-import ch.qos.logback.core.pattern.Converter;
-import ch.qos.logback.core.pattern.DynamicConverter;
-import ch.qos.logback.core.pattern.LiteralConverter;
+import ch.qos.logback.core.pattern.*;
 import ch.qos.logback.core.spi.ContextAwareBase;
 import ch.qos.logback.core.status.ErrorStatus;
 import ch.qos.logback.core.util.OptionHelper;
@@ -29,46 +26,49 @@ class Compiler extends ContextAwareBase {
   Converter tail;
   final Node top;
   final Map converterMap;
+  final Map compositeConverterMap;
 
-  Compiler(final Node top, final Map converterMap) {
+  Compiler(final Node top, final Map converterMap, Map compositeConverterMap) {
     this.top = top;
     this.converterMap = converterMap;
+    this.compositeConverterMap = compositeConverterMap;
   }
 
   Converter compile() {
     head = tail = null;
     for (Node n = top; n != null; n = n.next) {
       switch (n.type) {
-      case Node.LITERAL:
-        addToList(new LiteralConverter((String) n.getValue()));
-        break;
-      case Node.COMPOSITE:
-        CompositeNode cn = (CompositeNode) n;
-        CompositeConverter compositeConverter = new CompositeConverter();
-        compositeConverter.setFormattingInfo(cn.getFormatInfo());
-        Compiler childCompiler = new Compiler(cn.getChildNode(),
-            converterMap);
-        childCompiler.setContext(context);
-        Converter childConverter = childCompiler.compile();
-        compositeConverter.setChildConverter(childConverter);
-        addToList(compositeConverter);
-        break;
-      case Node.KEYWORD:
-        KeywordNode kn = (KeywordNode) n;
-        DynamicConverter dynaConverter = createConverter(kn);
-        if (dynaConverter != null) {
-          dynaConverter.setFormattingInfo(kn.getFormatInfo());
-          dynaConverter.setOptionList(kn.getOptions());
-          addToList(dynaConverter);
-        } else {
-          // if the appropriate dynaconverter cannot be found, then replace
-          // it with a dummy LiteralConverter indicating an error.
-          Converter errConveter = new LiteralConverter("%PARSER_ERROR["
-              + kn.getValue()+"]");
-          addStatus(new ErrorStatus("[" + kn.getValue()
-              + "] is not a valid conversion word", this));
-          addToList(errConveter);
-        }
+        case Node.LITERAL:
+          addToList(new LiteralConverter((String) n.getValue()));
+          break;
+        case Node.COMPOSITE_KEYWORD:
+          CompositeNode cn = (CompositeNode) n;
+          CompositeConverter compositeConverter = createCompiteConverter(cn);
+          compositeConverter.setFormattingInfo(cn.getFormatInfo());
+          compositeConverter.setOptionList(cn.getOptions());
+          Compiler childCompiler = new Compiler(cn.getChildNode(),
+                  converterMap, compositeConverterMap);
+          childCompiler.setContext(context);
+          Converter childConverter = childCompiler.compile();
+          compositeConverter.setChildConverter(childConverter);
+          addToList(compositeConverter);
+          break;
+        case Node.SIMPLE_KEYWORD:
+          SimpleKeywordNode kn = (SimpleKeywordNode) n;
+          DynamicConverter dynaConverter = createConverter(kn);
+          if (dynaConverter != null) {
+            dynaConverter.setFormattingInfo(kn.getFormatInfo());
+            dynaConverter.setOptionList(kn.getOptions());
+            addToList(dynaConverter);
+          } else {
+            // if the appropriate dynaconverter cannot be found, then replace
+            // it with a dummy LiteralConverter indicating an error.
+            Converter errConveter = new LiteralConverter("%PARSER_ERROR["
+                    + kn.getValue() + "]");
+            addStatus(new ErrorStatus("[" + kn.getValue()
+                    + "] is not a valid conversion word", this));
+            addToList(errConveter);
+          }
 
       }
     }
@@ -87,31 +87,60 @@ class Compiler extends ContextAwareBase {
   /**
    * Attempt to create a converter using the information found in
    * 'converterMap'.
-   * 
+   *
    * @param kn
    * @return
    */
   @SuppressWarnings("unchecked")
-  DynamicConverter createConverter(KeywordNode kn) {
+  DynamicConverter createConverter(SimpleKeywordNode kn) {
     String keyword = (String) kn.getValue();
     String converterClassStr = (String) converterMap.get(keyword);
 
     if (converterClassStr != null) {
       try {
         return (DynamicConverter) OptionHelper.instantiateByClassName(
-            converterClassStr, DynamicConverter.class, context);
+                converterClassStr, DynamicConverter.class, context);
       } catch (Exception e) {
         addError("Failed to instantiate converter class [" + converterClassStr
-            + "]", e);
+                + "]", e);
         return null;
       }
     } else {
       addError("There is no conversion class registered for conversion word ["
-          + keyword + "]");
+              + keyword + "]");
       return null;
     }
   }
 
+  /**
+   * Attempt to create a converter using the information found in
+   * 'compositeConverterMap'.
+   *
+   * @param cn
+   * @return
+   */
+  @SuppressWarnings("unchecked")
+  CompositeConverter createCompiteConverter(CompositeNode cn) {
+    String keyword = (String) cn.getValue();
+    String converterClassStr = (String) compositeConverterMap.get(keyword);
+
+    if (converterClassStr != null) {
+      try {
+        return (CompositeConverter) OptionHelper.instantiateByClassName(
+                converterClassStr, CompositeConverter.class, context);
+      } catch (Exception e) {
+        addError("Failed to instantiate converter class [" + converterClassStr
+                + "]", e);
+        return null;
+      }
+    } else {
+      addError("There is no conversion class registered for composite conversion word ["
+              + keyword + "]");
+      return null;
+    }
+  }
+
+
   // public void setStatusManager(StatusManager statusManager) {
   // this.statusManager = statusManager;
   // }
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/CompositeNode.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/CompositeNode.java
index 8fd2029..cf3c402 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/CompositeNode.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/CompositeNode.java
@@ -13,11 +13,12 @@
  */
 package ch.qos.logback.core.pattern.parser;
 
-public class CompositeNode extends FormattingNode {
+public class CompositeNode extends SimpleKeywordNode {
 	Node childNode;
 
-	CompositeNode() {
-		super(Node.COMPOSITE);
+	CompositeNode(String keyword) {
+		super(Node.COMPOSITE_KEYWORD, keyword);
+
 	}
 
 	public Node getChildNode() {
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Node.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Node.java
index 615e2e9..e9bee8b 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Node.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Node.java
@@ -15,8 +15,8 @@ package ch.qos.logback.core.pattern.parser;
 
 public class Node {
 	static final int LITERAL = 0;
-	static final int KEYWORD = 1;
-	static final int COMPOSITE = 2;
+	static final int SIMPLE_KEYWORD = 1;
+	static final int COMPOSITE_KEYWORD = 2;
 
 	final int type;
 	final Object value;
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
index 65308db..ad4c762 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java
@@ -52,7 +52,7 @@ public class OptionTokenizer {
     this.escapeUtil = escapeUtil;
   }
 
-  List tokenize() throws ScanException {
+  List tokenize() throws ScanException {
     List tokenList = new ArrayList();
     StringBuffer buf = new StringBuffer();
 
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java
index 268edea..510aa7a 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java
@@ -13,18 +13,46 @@
  */
 package ch.qos.logback.core.pattern.parser;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import ch.qos.logback.core.pattern.Converter;
 import ch.qos.logback.core.pattern.FormatInfo;
+import ch.qos.logback.core.pattern.IdentityCompositeConverter;
+import ch.qos.logback.core.pattern.ReplacingCompositeConverter;
 import ch.qos.logback.core.pattern.util.IEscapeUtil;
 import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
 import ch.qos.logback.core.spi.ContextAwareBase;
 
+// ~=lamda
+// E = TE|T
+
+// Left factorization
+// E = T(E|~)
+// Eopt = E|~
+// replace E|~ with Eopt in E
+// E = TEopt
+
+// T = LITERAL | '%' C | '%' FORMAT_MODIFIER C
+// C = SIMPLE_KEYWORD OPTION | COMPOSITE_KEYWORD COMPOSITE
+// OPTION = {...} | ~
+// COMPOSITE = E ')' OPTION
+
+
 
 public class Parser extends ContextAwareBase {
 
+  public final static Map DEFAULT_COMPOSITE_CONVERTER_MAP = new HashMap();
+  public final static String REPLACER_CONVERTER_WORD = "replace";
+  static {
+    DEFAULT_COMPOSITE_CONVERTER_MAP.put(Token.BARE_COMPOSITE_KEYWORD_TOKEN.getValue().toString(),
+            IdentityCompositeConverter.class.getName());
+    DEFAULT_COMPOSITE_CONVERTER_MAP.put(REPLACER_CONVERTER_WORD,
+             ReplacingCompositeConverter.class.getName());
+
+  }
+
   final List tokenList;
   int pointer = 0;
   
@@ -32,7 +60,6 @@ public class Parser extends ContextAwareBase {
     this.tokenList = ts.tokenize();
   }
 
-  // this variant should be used for testing purposes only
   public Parser(String pattern) throws ScanException {
     this(pattern, new RegularEscapeUtil());
   }
@@ -46,40 +73,51 @@ public class Parser extends ContextAwareBase {
     }
   }
 
-  public Node parse() throws ScanException {
-    return E();
-  }
-
   /**
    * When the parsing step is done, the Node list can be transformed into a
    * converter chain.
-   * 
+   *
    * @param top
    * @param converterMap
    * @return
    * @throws ScanException
    */
-  public Converter compile(final Node top, Map converterMap) {
-    Compiler compiler = new Compiler(top, converterMap);
+  public Converter compile(final Node top, Map converterMap, Map compositeConverterMap) {
+    Compiler compiler = new Compiler(top, converterMap, compositeConverterMap);
     compiler.setContext(context);
     //compiler.setStatusManager(statusManager);
     return compiler.compile();
   }
 
+  public Node parse() throws ScanException {
+    return E();
+  }
+
+  // E = TEopt
   Node E() throws ScanException {
-    // System.out.println("in E()");
     Node t = T();
     if (t == null) {
       return null;
     }
     Node eOpt = Eopt();
     if (eOpt != null) {
-      // System.out.println("setting next node to " + eOpt);
       t.setNext(eOpt);
     }
     return t;
   }
 
+  // Eopt = E|~
+  Node Eopt() throws ScanException {
+    // System.out.println("in Eopt()");
+    Token next = getCurentToken();
+    // System.out.println("Current token is " + next);
+    if (next == null) {
+      return null;
+    } else {
+      return E();
+    }
+  }
+
   Node T() throws ScanException {
     // System.out.println("in T()");
     Token t = getCurentToken();
@@ -117,17 +155,6 @@ public class Parser extends ContextAwareBase {
 
   }
 
-  Node Eopt() throws ScanException {
-    // System.out.println("in Eopt()");
-    Token next = getCurentToken();
-    // System.out.println("Current token is " + next);
-    if (next == null) {
-      return null;
-    } else {
-      return E();
-    }
-  }
-
   FormattingNode C() throws ScanException {
     Token t = getCurentToken();
     // System.out.println("in C()");
@@ -135,11 +162,11 @@ public class Parser extends ContextAwareBase {
     expectNotNull(t, "a LEFT_PARENTHESIS or KEYWORD");
     int type = t.getType();
     switch (type) {
-    case Token.KEYWORD:
+    case Token.SIMPLE_KEYWORD:
       return SINGLE();
-    case Token.LEFT_PARENTHESIS:
+    case Token.COMPOSITE_KEYWORD:
       advanceTokenPointer();
-      return COMPOSITE();
+      return COMPOSITE(t.getValue().toString());
     default:
       throw new IllegalStateException("Unexpected token " + t);
     }
@@ -149,19 +176,19 @@ public class Parser extends ContextAwareBase {
     // System.out.println("in SINGLE()");
     Token t = getNextToken();
     // System.out.println("==" + t);
-    KeywordNode keywordNode = new KeywordNode(t.getValue());
+    SimpleKeywordNode keywordNode = new SimpleKeywordNode(t.getValue());
 
     Token ot = getCurentToken();
     if (ot != null && ot.getType() == Token.OPTION) {
-      List optionList = new OptionTokenizer((String) ot.getValue()).tokenize();
+      List optionList = new OptionTokenizer((String) ot.getValue()).tokenize();
       keywordNode.setOptions(optionList);
       advanceTokenPointer();
     }
     return keywordNode;
   }
 
-  FormattingNode COMPOSITE() throws ScanException {
-    CompositeNode compositeNode = new CompositeNode();
+  FormattingNode COMPOSITE(String keyword) throws ScanException {
+    CompositeNode compositeNode = new CompositeNode(keyword);
 
     Node childNode = E();
     // System.out.println("Child node: " + childNode);
@@ -177,6 +204,12 @@ public class Parser extends ContextAwareBase {
     } else {
       // System.out.println("got expected ')'");
     }
+    Token ot = getCurentToken();
+    if (ot != null && ot.getType() == Token.OPTION) {
+      List optionList = new OptionTokenizer((String) ot.getValue()).tokenize();
+      compositeNode.setOptions(optionList);
+      advanceTokenPointer();
+    }
     return compositeNode;
   }
 
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/KeywordNode.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/SimpleKeywordNode.java
similarity index 71%
rename from logback-core/src/main/java/ch/qos/logback/core/pattern/parser/KeywordNode.java
rename to logback-core/src/main/java/ch/qos/logback/core/pattern/parser/SimpleKeywordNode.java
index 3d2879c..3eda998 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/KeywordNode.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/SimpleKeywordNode.java
@@ -1,60 +1,64 @@
-/**
- * Logback: the reliable, generic, fast and flexible logging framework.
- * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
- *
- * This program and the accompanying materials are dual-licensed under
- * either the terms of the Eclipse Public License v1.0 as published by
- * the Eclipse Foundation
- *
- *   or (per the licensee's choosing)
- *
- * under the terms of the GNU Lesser General Public License version 2.1
- * as published by the Free Software Foundation.
- */
-package ch.qos.logback.core.pattern.parser;
-
-import java.util.List;
-
-public class KeywordNode extends FormattingNode {
-
-  List optionList;
-
-  KeywordNode(Object value) {
-    super(Node.KEYWORD, value);
-  }
-
-  public List getOptions() {
-    return optionList;
-  }
-
-  public void setOptions(List optionList) {
-    this.optionList = optionList;
-  }
-
-  public boolean equals(Object o) {
-    // System.out.println("Keyword.equals()");
-    if (!super.equals(o)) {
-      return false;
-    }
-
-    if (!(o instanceof KeywordNode)) {
-      return false;
-    }
-    KeywordNode r = (KeywordNode) o;
-
-    return (optionList != null ? optionList.equals(r.optionList)
-        : r.optionList == null);
-  }
-
-  public String toString() {
-    StringBuffer buf = new StringBuffer();
-    if (optionList == null) {
-      buf.append("KeyWord(" + value + "," + formatInfo + ")");
-    } else {
-      buf.append("KeyWord(" + value + ", " + formatInfo + "," + optionList
-          + ")");
-    }
-    buf.append(printNext());
-    return buf.toString();
-  }
-}
+/**
+ * Logback: the reliable, generic, fast and flexible logging framework.
+ * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
+ *
+ * This program and the accompanying materials are dual-licensed under
+ * either the terms of the Eclipse Public License v1.0 as published by
+ * the Eclipse Foundation
+ *
+ *   or (per the licensee's choosing)
+ *
+ * under the terms of the GNU Lesser General Public License version 2.1
+ * as published by the Free Software Foundation.
+ */
+package ch.qos.logback.core.pattern.parser;
+
+import java.util.List;
+
+public class SimpleKeywordNode extends FormattingNode {
+
+  List optionList;
+
+  SimpleKeywordNode(Object value) {
+    super(Node.SIMPLE_KEYWORD, value);
+  }
+
+  protected  SimpleKeywordNode(int type, Object value) {
+    super(type, value);
+  }
+
+  public List getOptions() {
+    return optionList;
+  }
+
+  public void setOptions(List optionList) {
+    this.optionList = optionList;
+  }
+
+  public boolean equals(Object o) {
+    // System.out.println("Keyword.equals()");
+    if (!super.equals(o)) {
+      return false;
+    }
+
+    if (!(o instanceof SimpleKeywordNode)) {
+      return false;
+    }
+    SimpleKeywordNode r = (SimpleKeywordNode) o;
+
+    return (optionList != null ? optionList.equals(r.optionList)
+        : r.optionList == null);
+  }
+
+  public String toString() {
+    StringBuffer buf = new StringBuffer();
+    if (optionList == null) {
+      buf.append("KeyWord(" + value + "," + formatInfo + ")");
+    } else {
+      buf.append("KeyWord(" + value + ", " + formatInfo + "," + optionList
+          + ")");
+    }
+    buf.append(printNext());
+    return buf.toString();
+  }
+}
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java
index 2965a1c..1e8a385 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java
@@ -16,7 +16,7 @@ package ch.qos.logback.core.pattern.parser;
 class Token {
 
   static final int PERCENT = 37;
-  static final int LEFT_PARENTHESIS = 40;
+  //static final int LEFT_PARENTHESIS = 40;
   static final int RIGHT_PARENTHESIS = 41;
   static final int MINUS = 45;
   static final int DOT = 46;
@@ -24,14 +24,15 @@ class Token {
   static final int CURLY_RIGHT = 125;
   static final int LITERAL = 1000;
   static final int FORMAT_MODIFIER = 1002;
-  static final int KEYWORD = 1004;
+  static final int SIMPLE_KEYWORD = 1004;
+  static final int COMPOSITE_KEYWORD = 1005;
   static final int OPTION = 1006;
 
   static final int EOF = Integer.MAX_VALUE;
 
   static Token EOF_TOKEN = new Token(EOF, "EOF");
   static Token RIGHT_PARENTHESIS_TOKEN = new Token(RIGHT_PARENTHESIS);
-  static Token LEFT_PARENTHESIS_TOKEN = new Token(LEFT_PARENTHESIS);
+  static Token BARE_COMPOSITE_KEYWORD_TOKEN = new Token(COMPOSITE_KEYWORD, "BARE");
   static Token PERCENT_TOKEN = new Token(PERCENT);
 
   private final int type;
@@ -72,15 +73,15 @@ class Token {
       case OPTION:
         typeStr = "OPTION";
         break;
-      case KEYWORD:
-        typeStr = "KEYWORD";
+      case SIMPLE_KEYWORD:
+        typeStr = "SIMPLE_KEYWORD";
         break;
+      case COMPOSITE_KEYWORD:
+          typeStr = "COMPOSITE_KEYWORD";
+          break;
       case RIGHT_PARENTHESIS:
         typeStr = "RIGHT_PARENTHESIS";
         break;
-      case LEFT_PARENTHESIS:
-        typeStr = "LEFT_PARENTHESIS";
-        break;
      default:
         typeStr = "UNKNOWN";
     }
diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
index b0dc881..19d8311 100644
--- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
+++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java
@@ -24,17 +24,17 @@ import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
  * 

* Return a steady stream of tokens. *

- * + *

*

- * The returned tokens are one of: LITERAL, '%', FORMAT_MODIFIER, KEYWWORD, + * The returned tokens are one of: LITERAL, '%', FORMAT_MODIFIER, SIMPLE_KEYWORD, COMPOSITE_KEYWORD * OPTION, LEFT_PARENTHESIS, and RIGHT_PARENTHESIS. *

- * + *

*

* The '\' character is used as escape. It can be used to escape '_', '%', '(' * and '('. *

- * + *

*

* Note that there is no EOS token returned. *

@@ -42,7 +42,6 @@ import ch.qos.logback.core.pattern.util.RegularEscapeUtil; class TokenStream { private static final char ESCAPE_CHAR = '\\'; - private static final char PERCENT_CHAR = CoreConstants.PERCENT_CHAR; private static final char CURLY_LEFT = '{'; private static final char CURLY_RIGHT = '}'; @@ -66,7 +65,7 @@ class TokenStream { TokenStream(String pattern, IEscapeUtil escapeUtil) { if (pattern == null || pattern.length() == 0) { throw new IllegalArgumentException( - "null or empty pattern string not allowed"); + "null or empty pattern string not allowed"); } this.pattern = pattern; patternLength = pattern.length(); @@ -83,105 +82,121 @@ class TokenStream { switch (state) { - case LITERAL_STATE: - switch (c) { - case ESCAPE_CHAR: - escape("%()", buf); + case LITERAL_STATE: + handleLiteralState(c, tokenList, buf); break; - case PERCENT_CHAR: - addValuedToken(Token.LITERAL, buf, tokenList); - tokenList.add(Token.PERCENT_TOKEN); - state = FORMAT_MODIFIER_STATE; + // + case FORMAT_MODIFIER_STATE: + handleFormatModifierState(c, tokenList, buf); break; - - case CoreConstants.RIGHT_PARENTHESIS_CHAR: - if (buf.length() >= 1 && buf.charAt(buf.length() - 1) == '\\') { - buf.deleteCharAt(buf.length() - 1); - buf.append(CoreConstants.RIGHT_PARENTHESIS_CHAR); - } else { - addValuedToken(Token.LITERAL, buf, tokenList); - tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); + case OPTION_STATE: + switch (c) { + case CURLY_RIGHT: + addValuedToken(Token.OPTION, buf, tokenList); + state = LITERAL_STATE; + break; + case ESCAPE_CHAR: + escape("%{}", buf); + break; + default: + buf.append(c); } break; + case KEYWORD_STATE: + handleKeywordState(c, tokenList, buf); + break; default: - buf.append(c); - } + } + } + + // EOS + switch (state) { + case LITERAL_STATE: + addValuedToken(Token.LITERAL, buf, tokenList); break; - // - case FORMAT_MODIFIER_STATE: - if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) { - addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList); - tokenList.add(Token.LEFT_PARENTHESIS_TOKEN); - state = LITERAL_STATE; - } else if (Character.isJavaIdentifierStart(c)) { - addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList); - state = KEYWORD_STATE; - buf.append(c); - } else { - buf.append(c); - } + case KEYWORD_STATE: + tokenList.add(new Token(Token.SIMPLE_KEYWORD, buf.toString())); + buf.setLength(0); break; + + case FORMAT_MODIFIER_STATE: case OPTION_STATE: - switch (c) { - case CURLY_RIGHT: - addValuedToken(Token.OPTION, buf, tokenList); - state = LITERAL_STATE; - break; - case ESCAPE_CHAR: - escape("%{}", buf); - break; - default: - buf.append(c); - } + throw new ScanException("Unexpected end of pattern string"); + } + + return tokenList; + } + + private void handleFormatModifierState(char c, List tokenList, StringBuffer buf) { + if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) { + addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList); + tokenList.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN); + state = LITERAL_STATE; + } else if (Character.isJavaIdentifierStart(c)) { + addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList); + state = KEYWORD_STATE; + buf.append(c); + } else { + buf.append(c); + } + } + + private void handleLiteralState(char c, List tokenList, StringBuffer buf) { + switch (c) { + case ESCAPE_CHAR: + escape("%()", buf); break; - case KEYWORD_STATE: - if (c == CURLY_LEFT) { - addValuedToken(Token.KEYWORD, buf, tokenList); - state = OPTION_STATE; - } else if (Character.isJavaIdentifierPart(c)) { - buf.append(c); - } else if (c == PERCENT_CHAR) { - addValuedToken(Token.KEYWORD, buf, tokenList); - tokenList.add(Token.PERCENT_TOKEN); - state = FORMAT_MODIFIER_STATE; + + case CoreConstants.PERCENT_CHAR: + addValuedToken(Token.LITERAL, buf, tokenList); + tokenList.add(Token.PERCENT_TOKEN); + state = FORMAT_MODIFIER_STATE; + break; + + case CoreConstants.RIGHT_PARENTHESIS_CHAR: + if (buf.length() >= 1 && buf.charAt(buf.length() - 1) == '\\') { + buf.deleteCharAt(buf.length() - 1); + buf.append(CoreConstants.RIGHT_PARENTHESIS_CHAR); } else { - addValuedToken(Token.KEYWORD, buf, tokenList); - if (c == CoreConstants.RIGHT_PARENTHESIS_CHAR) { - // if c is a right parenthesis, then add it as such - tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); - } else if (c == ESCAPE_CHAR) { - if ((pointer < patternLength)) { - char next = pattern.charAt(pointer++); - escapeUtil.escape("%()", buf, next, pointer); - } - } else { - buf.append(c); - } - state = LITERAL_STATE; + addValuedToken(Token.LITERAL, buf, tokenList); + tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); } break; default: - } + buf.append(c); } + } - // EOS - switch (state) { - case LITERAL_STATE: - addValuedToken(Token.LITERAL, buf, tokenList); - break; - case KEYWORD_STATE: - tokenList.add(new Token(Token.KEYWORD, buf.toString())); - buf.setLength(0); - break; - - case FORMAT_MODIFIER_STATE: - case OPTION_STATE: - throw new ScanException("Unexpected end of pattern string"); + private void handleKeywordState(char c, List tokenList, StringBuffer buf) { + if (c == CURLY_LEFT) { + addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList); + state = OPTION_STATE; + } else if (Character.isJavaIdentifierPart(c)) { + buf.append(c); + } else if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) { + addValuedToken(Token.COMPOSITE_KEYWORD, buf, tokenList); + state = LITERAL_STATE; + } else if (c == CoreConstants.PERCENT_CHAR) { + addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList); + tokenList.add(Token.PERCENT_TOKEN); + state = FORMAT_MODIFIER_STATE; + } else { + addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList); + if (c == CoreConstants.RIGHT_PARENTHESIS_CHAR) { + // if c is a right parenthesis, then add it as such + tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); + } else if (c == ESCAPE_CHAR) { + if ((pointer < patternLength)) { + char next = pattern.charAt(pointer++); + escapeUtil.escape("%()", buf, next, pointer); + } + } else { + buf.append(c); + } + state = LITERAL_STATE; } - - return tokenList; } void escape(String escapeChars, StringBuffer buf) { diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java index 88adfe6..be3c8b5 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java @@ -66,7 +66,7 @@ public class FileNamePattern extends ContextAwareBase { Parser p = new Parser(patternForParsing, new AlmostAsIsEscapeUtil()); p.setContext(context); Node t = p.parse(); - this.headTokenConverter = p.compile(t, CONVERTER_MAP); + this.headTokenConverter = p.compile(t, CONVERTER_MAP, Parser.DEFAULT_COMPOSITE_CONVERTER_MAP); } catch (ScanException sce) { addError("Failed to parse pattern \"" + pattern + "\".", sce); diff --git a/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java b/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java index 1e7cc80..235b30a 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/AllCoreTest.java @@ -30,7 +30,5 @@ import org.junit.runners.Suite.SuiteClasses; ch.qos.logback.core.sift.PackageTest.class, ch.qos.logback.core.encoder.PackageTest.class, ch.qos.logback.core.recovery.PackageTest.class}) -public class - AllCoreTest { - +public class AllCoreTest { } diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java index 8c64c59..39bb596 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java @@ -29,7 +29,7 @@ import ch.qos.logback.core.pattern.Converter123; import ch.qos.logback.core.pattern.ConverterHello; import ch.qos.logback.core.status.StatusChecker; import ch.qos.logback.core.util.StatusPrinter; - +import static ch.qos.logback.core.pattern.parser.Parser.DEFAULT_COMPOSITE_CONVERTER_MAP; public class CompilerTest { @@ -56,7 +56,7 @@ public class CompilerTest { public void testLiteral() throws Exception { Parser p = new Parser("hello"); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("hello", result); } @@ -67,7 +67,7 @@ public class CompilerTest { Parser p = new Parser("abc %hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("abc Hello", result); } @@ -75,7 +75,7 @@ public class CompilerTest { Parser p = new Parser("abc %hello %OTT"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("abc Hello 123", result); } @@ -87,7 +87,7 @@ public class CompilerTest { Parser p = new Parser("abc %7hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("abc Hello", result); } @@ -96,7 +96,7 @@ public class CompilerTest { Parser p = new Parser("abc %-7hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("abc Hello ", result); } @@ -105,7 +105,7 @@ public class CompilerTest { Parser p = new Parser("abc %.3hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("abc llo", result); } @@ -114,7 +114,7 @@ public class CompilerTest { Parser p = new Parser("abc %.-3hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("abc Hel", result); } @@ -123,7 +123,7 @@ public class CompilerTest { Parser p = new Parser("abc %4.5OTT"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("abc 123", result); } @@ -131,7 +131,7 @@ public class CompilerTest { Parser p = new Parser("abc %-4.5OTT"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("abc 123 ", result); } @@ -139,7 +139,7 @@ public class CompilerTest { Parser p = new Parser("abc %3.4hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("abc ello", result); } @@ -147,7 +147,7 @@ public class CompilerTest { Parser p = new Parser("abc %-3.-4hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("abc Hell", result); } @@ -168,7 +168,7 @@ public class CompilerTest { Parser p = new Parser("%(ABC %hello)"); p.setContext(c); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); StatusPrinter.print(c); assertEquals("ABC Hello", result); @@ -177,7 +177,7 @@ public class CompilerTest { Parser p = new Parser("%(ABC %hello)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap,DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("ABC Hello", result); } @@ -189,7 +189,7 @@ public class CompilerTest { Parser p = new Parser("xyz %4.10(ABC)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("xyz ABC", result); } @@ -198,7 +198,7 @@ public class CompilerTest { Parser p = new Parser("xyz %-4.10(ABC)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("xyz ABC ", result); } @@ -207,7 +207,7 @@ public class CompilerTest { Parser p = new Parser("xyz %.2(ABC %hello)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("xyz lo", result); } @@ -216,7 +216,7 @@ public class CompilerTest { Parser p = new Parser("xyz %.-2(ABC)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("xyz AB", result); } @@ -225,7 +225,7 @@ public class CompilerTest { Parser p = new Parser("xyz %30.30(ABC %20hello)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("xyz ABC Hello", result); } @@ -236,7 +236,7 @@ public class CompilerTest { Parser p = new Parser("%unknown"); p.setContext(context); Node t = p.parse(); - p.compile(t, converterMap); + p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); StatusChecker chercker = new StatusChecker(context.getStatusManager()); assertTrue(chercker .containsMatch("\\[unknown] is not a valid conversion word")); @@ -248,7 +248,7 @@ public class CompilerTest { Parser p = new Parser("xyz %hello\\_world"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap); + Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); String result = write(head, new Object()); assertEquals("xyz Helloworld", result); } diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java index 6fab0fc..e220964 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java @@ -25,6 +25,8 @@ import ch.qos.logback.core.pattern.FormatInfo; public class ParserTest { + String BARE = Token.BARE_COMPOSITE_KEYWORD_TOKEN.getValue().toString(); + @Test public void testBasic() throws Exception { Parser p = new Parser("hello"); @@ -40,7 +42,7 @@ public class ParserTest { Parser p = new Parser("hello%xyz"); Node t = p.parse(); Node witness = new Node(Node.LITERAL, "hello"); - witness.next = new KeywordNode("xyz"); + witness.next = new SimpleKeywordNode("xyz"); assertEquals(witness, t); } @@ -48,7 +50,7 @@ public class ParserTest { Parser p = new Parser("hello%xyz{x}"); Node t = p.parse(); Node witness = new Node(Node.LITERAL, "hello"); - KeywordNode n = new KeywordNode("xyz"); + SimpleKeywordNode n = new SimpleKeywordNode("xyz"); List optionList = new ArrayList(); optionList.add("x"); n.setOptions(optionList); @@ -64,8 +66,8 @@ public class ParserTest { Node t = p.parse(); Node witness = new Node(Node.LITERAL, "hello"); - CompositeNode composite = new CompositeNode(); - Node child = new KeywordNode("child"); + CompositeNode composite = new CompositeNode(BARE); + Node child = new SimpleKeywordNode("child"); composite.setChildNode(child); witness.next = composite; @@ -81,8 +83,8 @@ public class ParserTest { Node t = p.parse(); Node witness = new Node(Node.LITERAL, "hello"); - CompositeNode composite = new CompositeNode(); - Node child = new KeywordNode("child"); + CompositeNode composite = new CompositeNode(BARE); + Node child = new SimpleKeywordNode("child"); composite.setChildNode(child); witness.next = composite; child.next = new Node(Node.LITERAL, " "); @@ -93,11 +95,11 @@ public class ParserTest { Parser p = new Parser("hello%(%child %h)"); Node t = p.parse(); Node witness = new Node(Node.LITERAL, "hello"); - CompositeNode composite = new CompositeNode(); - Node child = new KeywordNode("child"); + CompositeNode composite = new CompositeNode(BARE); + Node child = new SimpleKeywordNode("child"); composite.setChildNode(child); child.next = new Node(Node.LITERAL, " "); - child.next.next = new KeywordNode("h"); + child.next.next = new SimpleKeywordNode("h"); witness.next = composite; assertEquals(witness, t); } @@ -106,14 +108,14 @@ public class ParserTest { Parser p = new Parser("hello%(%child %h) %m"); Node t = p.parse(); Node witness = new Node(Node.LITERAL, "hello"); - CompositeNode composite = new CompositeNode(); - Node child = new KeywordNode("child"); + CompositeNode composite = new CompositeNode(BARE); + Node child = new SimpleKeywordNode("child"); composite.setChildNode(child); child.next = new Node(Node.LITERAL, " "); - child.next.next = new KeywordNode("h"); + child.next.next = new SimpleKeywordNode("h"); witness.next = composite; composite.next = new Node(Node.LITERAL, " "); - composite.next.next = new KeywordNode("m"); + composite.next.next = new SimpleKeywordNode("m"); assertEquals(witness, t); } @@ -121,17 +123,17 @@ public class ParserTest { Parser p = new Parser("hello%( %child \\(%h\\) ) %m"); Node t = p.parse(); Node witness = new Node(Node.LITERAL, "hello"); - CompositeNode composite = new CompositeNode(); + CompositeNode composite = new CompositeNode(BARE); Node child = new Node(Node.LITERAL, " "); composite.setChildNode(child); Node c = child; - c = c.next = new KeywordNode("child"); + c = c.next = new SimpleKeywordNode("child"); c = c.next = new Node(Node.LITERAL, " ("); - c = c.next = new KeywordNode("h"); + c = c.next = new SimpleKeywordNode("h"); c = c.next = new Node(Node.LITERAL, ") "); witness.next = composite; composite.next = new Node(Node.LITERAL, " "); - composite.next.next = new KeywordNode("m"); + composite.next.next = new SimpleKeywordNode("m"); assertEquals(witness, t); } @@ -142,15 +144,15 @@ public class ParserTest { { Parser p = new Parser("%top %(%child%(%h))"); Node t = p.parse(); - Node witness = new KeywordNode("top"); + Node witness = new SimpleKeywordNode("top"); Node w = witness.next = new Node(Node.LITERAL, " "); - CompositeNode composite = new CompositeNode(); + CompositeNode composite = new CompositeNode(BARE); w = w.next = composite; - Node child = new KeywordNode("child"); + Node child = new SimpleKeywordNode("child"); composite.setChildNode(child); - composite = new CompositeNode(); + composite = new CompositeNode(BARE); child.next = composite; - composite.setChildNode(new KeywordNode("h")); + composite.setChildNode(new SimpleKeywordNode("h")); assertEquals(witness, t); } @@ -161,14 +163,14 @@ public class ParserTest { { Parser p = new Parser("%45x"); Node t = p.parse(); - FormattingNode witness = new KeywordNode("x"); + FormattingNode witness = new SimpleKeywordNode("x"); witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE)); assertEquals(witness, t); } { Parser p = new Parser("%4.5x"); Node t = p.parse(); - FormattingNode witness = new KeywordNode("x"); + FormattingNode witness = new SimpleKeywordNode("x"); witness.setFormatInfo(new FormatInfo(4, 5)); assertEquals(witness, t); } @@ -176,14 +178,14 @@ public class ParserTest { { Parser p = new Parser("%-4.5x"); Node t = p.parse(); - FormattingNode witness = new KeywordNode("x"); + FormattingNode witness = new SimpleKeywordNode("x"); witness.setFormatInfo(new FormatInfo(4, 5, false, true)); assertEquals(witness, t); } { Parser p = new Parser("%-4.-5x"); Node t = p.parse(); - FormattingNode witness = new KeywordNode("x"); + FormattingNode witness = new SimpleKeywordNode("x"); witness.setFormatInfo(new FormatInfo(4, 5, false, false)); assertEquals(witness, t); } @@ -191,10 +193,10 @@ public class ParserTest { { Parser p = new Parser("%-4.5x %12y"); Node t = p.parse(); - FormattingNode witness = new KeywordNode("x"); + FormattingNode witness = new SimpleKeywordNode("x"); witness.setFormatInfo(new FormatInfo(4, 5, false, true)); Node n = witness.next = new Node(Node.LITERAL, " "); - n = n.next = new KeywordNode("y"); + n = n.next = new SimpleKeywordNode("y"); ((FormattingNode) n).setFormatInfo(new FormatInfo(12, Integer.MAX_VALUE)); assertEquals(witness, t); } @@ -205,7 +207,7 @@ public class ParserTest { { Parser p = new Parser("%45x{'test '}"); Node t = p.parse(); - KeywordNode witness = new KeywordNode("x"); + SimpleKeywordNode witness = new SimpleKeywordNode("x"); witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE)); List ol = new ArrayList(); ol.add("test "); @@ -216,7 +218,7 @@ public class ParserTest { { Parser p = new Parser("%45x{a, b}"); Node t = p.parse(); - KeywordNode witness = new KeywordNode("x"); + SimpleKeywordNode witness = new SimpleKeywordNode("x"); witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE)); List ol = new ArrayList(); ol.add("a"); @@ -232,7 +234,7 @@ public class ParserTest { { Parser p = new Parser("%x{}a"); Node t = p.parse(); - KeywordNode witness = new KeywordNode("x"); + SimpleKeywordNode witness = new SimpleKeywordNode("x"); witness.next = new Node(Node.LITERAL, "a"); assertEquals(witness, t); } @@ -246,7 +248,7 @@ public class ParserTest { Node t = p.parse(); Node witness = new Node(Node.LITERAL, "hello"); - CompositeNode composite = new CompositeNode(); + CompositeNode composite = new CompositeNode(BARE); composite.setFormatInfo(new FormatInfo(5, Integer.MAX_VALUE)); Node child = new Node(Node.LITERAL, "XYZ"); composite.setChildNode(child); diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java index d737a56..c9d12a0 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java @@ -74,7 +74,7 @@ public class TokenStreamTest { List tl = new TokenStream("%c").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "c")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "c")); assertEquals(witness, tl); } @@ -83,9 +83,9 @@ public class TokenStreamTest { List tl = new TokenStream("%a%b").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "a")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "a")); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "b")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "b")); assertEquals(witness, tl); } @@ -96,7 +96,7 @@ public class TokenStreamTest { witness.add(new Token(Token.LITERAL, "xyz")); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.FORMAT_MODIFIER, "-34")); - witness.add(new Token(Token.KEYWORD, "c")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "c")); assertEquals(witness, tl); } } @@ -106,15 +106,15 @@ public class TokenStreamTest { List tl = new TokenStream("%d{1234} [%34.-67toto] %n").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "d")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "d")); witness.add(new Token(Token.OPTION, "1234")); witness.add(new Token(Token.LITERAL, " [")); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.FORMAT_MODIFIER, "34.-67")); - witness.add(new Token(Token.KEYWORD, "toto")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "toto")); witness.add(new Token(Token.LITERAL, "] ")); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "n")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "n")); assertEquals(witness, tl); } @@ -132,7 +132,7 @@ public class TokenStreamTest { List tl = new TokenStream("%()").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(Token.LEFT_PARENTHESIS_TOKEN); + witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN); witness.add(Token.RIGHT_PARENTHESIS_TOKEN); assertEquals(witness, tl); } @@ -158,7 +158,7 @@ public class TokenStreamTest { List witness = new ArrayList(); witness.add(new Token(Token.LITERAL, "\\")); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); assertEquals(witness, tl); } @@ -166,7 +166,7 @@ public class TokenStreamTest { List tl = new TokenStream("%x\\)").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); witness.add(new Token(Token.LITERAL, ")")); assertEquals(witness, tl); } @@ -175,7 +175,7 @@ public class TokenStreamTest { List tl = new TokenStream("%x\\_a").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); witness.add(new Token(Token.LITERAL, "a")); assertEquals(witness, tl); } @@ -183,9 +183,9 @@ public class TokenStreamTest { List tl = new TokenStream("%x\\_%b").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "b")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "b")); assertEquals(witness, tl); } } @@ -196,7 +196,7 @@ public class TokenStreamTest { List tl = new TokenStream("%x{t}").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); witness.add(new Token(Token.OPTION, "t")); assertEquals(witness, tl); } @@ -205,7 +205,7 @@ public class TokenStreamTest { List tl = new TokenStream("%x{t,y}").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); witness.add(new Token(Token.OPTION, "t,y")); assertEquals(witness, tl); } @@ -214,7 +214,7 @@ public class TokenStreamTest { List tl = new TokenStream("%x{\"hello world.\", \"12y \"}").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); witness.add(new Token(Token.OPTION, "\"hello world.\", \"12y \"")); assertEquals(witness, tl); } @@ -223,7 +223,7 @@ public class TokenStreamTest { List tl = new TokenStream("%x{opt\\}}").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "x")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); witness.add(new Token(Token.OPTION, "opt}")); assertEquals(witness, tl); } @@ -234,10 +234,10 @@ public class TokenStreamTest { List tl = new TokenStream("%(hello %class{.4?})").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(Token.LEFT_PARENTHESIS_TOKEN); + witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN); witness.add(new Token(Token.LITERAL, "hello ")); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "class")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "class")); witness.add(new Token(Token.OPTION, ".4?")); witness.add(Token.RIGHT_PARENTHESIS_TOKEN); assertEquals(witness, tl); @@ -249,14 +249,14 @@ public class TokenStreamTest { List witness = new ArrayList(); witness.add(new Token(Token.LITERAL, "X ")); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "a")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "a")); witness.add(new Token(Token.LITERAL, " ")); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.FORMAT_MODIFIER, "-12.550")); - witness.add(Token.LEFT_PARENTHESIS_TOKEN); + witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN); witness.add(new Token(Token.LITERAL, "hello ")); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "class")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "class")); witness.add(new Token(Token.OPTION, ".4?")); witness.add(Token.RIGHT_PARENTHESIS_TOKEN); assertEquals(witness, tl); @@ -268,18 +268,18 @@ public class TokenStreamTest { List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.FORMAT_MODIFIER, "-1")); - witness.add(Token.LEFT_PARENTHESIS_TOKEN); + witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "d")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "d")); witness.add(new Token(Token.LITERAL, " ")); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.FORMAT_MODIFIER, "45")); - witness.add(Token.LEFT_PARENTHESIS_TOKEN); + witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "class")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "class")); witness.add(new Token(Token.LITERAL, " ")); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "file")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "file")); witness.add(Token.RIGHT_PARENTHESIS_TOKEN); witness.add(Token.RIGHT_PARENTHESIS_TOKEN); @@ -291,13 +291,13 @@ public class TokenStreamTest { List tl = new TokenStream("%(%a%(%b))").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); - witness.add(Token.LEFT_PARENTHESIS_TOKEN); + witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "a")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "a")); witness.add(Token.PERCENT_TOKEN); - witness.add(Token.LEFT_PARENTHESIS_TOKEN); + witness.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "b")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "b")); witness.add(Token.RIGHT_PARENTHESIS_TOKEN); witness.add(Token.RIGHT_PARENTHESIS_TOKEN); @@ -312,7 +312,7 @@ public class TokenStreamTest { List witness = new ArrayList(); witness.add(new Token(Token.LITERAL, "(")); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "h")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "h")); witness.add(new Token(Token.LITERAL, ")")); assertEquals(witness, tl); } @@ -321,7 +321,7 @@ public class TokenStreamTest { List witness = new ArrayList(); witness.add(new Token(Token.LITERAL, "(")); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "h")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "h")); witness.add(new Token(Token.LITERAL, ")")); assertEquals(witness, tl); } @@ -329,14 +329,54 @@ public class TokenStreamTest { @Test public void testWindowsLikeBackSlashes() throws ScanException { - { - List tl = new TokenStream("c:\\hello\\world.%i", - new AlmostAsIsEscapeUtil()).tokenize(); + List tl = new TokenStream("c:\\hello\\world.%i", + new AlmostAsIsEscapeUtil()).tokenize(); + + List witness = new ArrayList(); + witness.add(new Token(Token.LITERAL, "c:\\hello\\world.")); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.SIMPLE_KEYWORD, "i")); + assertEquals(witness, tl); + } + @Test + public void compositedKeyword() throws ScanException { + { + List tl = new TokenStream("%d(A)", + new AlmostAsIsEscapeUtil()).tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.COMPOSITE_KEYWORD, "d")); + witness.add(new Token(Token.LITERAL, "A")); + witness.add(Token.RIGHT_PARENTHESIS_TOKEN); + assertEquals(witness, tl); + } + { + List tl = new TokenStream("a %subst(%b C)", + new AlmostAsIsEscapeUtil()).tokenize(); List witness = new ArrayList(); - witness.add(new Token(Token.LITERAL, "c:\\hello\\world.")); + witness.add(new Token(Token.LITERAL, "a ")); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.COMPOSITE_KEYWORD, "subst")); witness.add(Token.PERCENT_TOKEN); - witness.add(new Token(Token.KEYWORD, "i")); + witness.add(new Token(Token.SIMPLE_KEYWORD, "b")); + witness.add(new Token(Token.LITERAL, " C")); + witness.add(Token.RIGHT_PARENTHESIS_TOKEN); + assertEquals(witness, tl); + } + } + @Test + public void compositedKeywordFollowedByOptions() throws ScanException { + { + List tl = new TokenStream("%d(A){o}", + new AlmostAsIsEscapeUtil()).tokenize(); + List witness = new ArrayList(); + witness.add(Token.PERCENT_TOKEN); + witness.add(new Token(Token.COMPOSITE_KEYWORD, "d")); + witness.add(new Token(Token.LITERAL, "A")); + witness.add(Token.RIGHT_PARENTHESIS_TOKEN); + witness.add(new Token(Token.OPTION, "o")); + assertEquals(witness, tl); } } ----------------------------------------------------------------------- Summary of changes: goscp | 3 + .../qos/logback/classic/pattern/DateConverter.java | 1 + .../classic/turbo/ReconfigureOnChangeTest.java | 2 +- .../ch/qos/logback/core/OutputStreamAppender.java | 5 +- .../ch/qos/logback/core/html/HTMLLayoutBase.java | 2 +- .../logback/core/pattern/CompositeConverter.java | 16 +- .../ch/qos/logback/core/pattern/ConverterUtil.java | 15 +- .../qos/logback/core/pattern/DynamicConverter.java | 8 +- .../core/pattern/IdentityCompositeConverter.java | 13 +- .../logback/core/pattern/PatternLayoutBase.java | 2 +- .../core/pattern/ReplacingCompositeConverter.java | 25 ++-- .../qos/logback/core/pattern/parser/Compiler.java | 109 +++++++---- .../logback/core/pattern/parser/CompositeNode.java | 7 +- .../ch/qos/logback/core/pattern/parser/Node.java | 4 +- .../core/pattern/parser/OptionTokenizer.java | 2 +- .../ch/qos/logback/core/pattern/parser/Parser.java | 89 +++++++--- .../{KeywordNode.java => SimpleKeywordNode.java} | 124 +++++++------ .../ch/qos/logback/core/pattern/parser/Token.java | 17 +- .../logback/core/pattern/parser/TokenStream.java | 189 +++++++++++--------- .../core/rolling/helper/FileNamePattern.java | 2 +- .../test/java/ch/qos/logback/core/AllCoreTest.java | 4 +- .../logback/core/pattern/parser/CompilerTest.java | 42 +++--- .../logback/core/pattern/parser/ParserTest.java | 66 ++++---- .../core/pattern/parser/TokenStreamTest.java | 116 ++++++++---- 24 files changed, 495 insertions(+), 368 deletions(-) create mode 100644 goscp copy logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/NestedType.groovy => logback-core/src/main/java/ch/qos/logback/core/pattern/IdentityCompositeConverter.java (73%) copy logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/AppenderDelegate.groovy => logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java (53%) rename logback-core/src/main/java/ch/qos/logback/core/pattern/parser/{KeywordNode.java => SimpleKeywordNode.java} (71%) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From git-noreply at pixie.qos.ch Wed Dec 15 22:53:06 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Wed, 15 Dec 2010 22:53:06 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-43-g888d97d Message-ID: <20101215215307.30DA43170AD@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via 888d97dcca98ab928da7d67bf6660c293cd47b9e (commit) from 2742a97de478cd3fc270223816eaa1c24d13cd82 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=888d97dcca98ab928da7d67bf6660c293cd47b9e http://github.com/ceki/logback/commit/888d97dcca98ab928da7d67bf6660c293cd47b9e commit 888d97dcca98ab928da7d67bf6660c293cd47b9e Author: Ceki Gulcu Date: Wed Dec 15 22:49:48 2010 +0100 ongoing work on compound conversion words diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassicConverter.java b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassicConverter.java index 8933733..15bd005 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassicConverter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/pattern/ClassicConverter.java @@ -14,7 +14,6 @@ package ch.qos.logback.classic.pattern; import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.spi.LoggerContextAware; import ch.qos.logback.classic.spi.LoggerContextAwareBase; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.Context; @@ -24,53 +23,10 @@ import ch.qos.logback.core.status.Status; /** * This class serves the super-class of all converters in logback. It extends - * {@link DynamicConverter} and also implements {@link LoggerContextAware}. - * + * {@link DynamicConverter}. + * * @author Ceki Gulcu */ -abstract public class ClassicConverter extends DynamicConverter implements - LoggerContextAware { - - LoggerContextAwareBase lcab = new LoggerContextAwareBase(); - - public void setLoggerContext(LoggerContext lc) { - lcab.setLoggerContext(lc); - } - - public void setContext(Context context) { - lcab.setContext(context); - } - - public Context getContext() { - return lcab.getContext(); - } - - public void addStatus(Status status) { - lcab.addStatus(status); - } - - public void addInfo(String msg) { - lcab.addInfo(msg); - } - - public void addInfo(String msg, Throwable ex) { - lcab.addInfo(msg, ex); - } - - public void addWarn(String msg) { - lcab.addWarn(msg); - } - - public void addWarn(String msg, Throwable ex) { - lcab.addWarn(msg, ex); - } - - public void addError(String msg) { - lcab.addError(msg); - } - - public void addError(String msg, Throwable ex) { - lcab.addError(msg, ex); - } +abstract public class ClassicConverter extends DynamicConverter { } diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java index 7189586..e72d4b3 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.java @@ -94,7 +94,7 @@ public class ReconfigureOnChangeFilter extends TurboFilter { // its values may *not* be incremented sequentially. However, we don't care // about the actual value of the field except that from time to time the // expression (invocationCounter++ & 0xF) == 0xF) should be true. - private int invocationCounter = 0; + private long invocationCounter = 0; @Override public FilterReply decide(Marker marker, Logger logger, Level level, @@ -108,6 +108,7 @@ public class ReconfigureOnChangeFilter extends TurboFilter { return FilterReply.NEUTRAL; } + //System.out.println("."); synchronized (lock) { boolean changed = changeDetected(); if (changed) { diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java index 8ede4bc..fad905e 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java @@ -22,6 +22,8 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; +import ch.qos.logback.core.status.Status; +import ch.qos.logback.core.util.StatusPrinter; import org.junit.Before; import org.junit.Test; @@ -42,7 +44,7 @@ public class PatternLayoutTest extends AbstractPatternLayoutBaseTest optionList = new ArrayList(); @@ -59,8 +61,8 @@ public class PatternLayoutTest extends AbstractPatternLayoutBaseTest sla = (StringListAppender) root.getAppender("LIST"); + StringListAppender sla = (StringListAppender) root.getAppender("LIST"); assertNotNull(sla); assertEquals(1, sla.strList.size()); - assertEquals(SampleConverter.SAMPLE_STR+" - "+msg, sla.strList.get(0)); + assertEquals(SampleConverter.SAMPLE_STR + " - " + msg, sla.strList.get(0)); } + + } diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java index 16a36c0..1965b1d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigurePerf.java @@ -33,14 +33,16 @@ import ch.qos.logback.core.joran.spi.JoranException; import ch.qos.logback.core.status.InfoStatus; import ch.qos.logback.core.testUtil.Env; +import static org.junit.Assert.fail; + public class ReconfigurePerf { final static int THREAD_COUNT = 50; - final static int LOOP_LEN = 1000 * 1000; + //final static int LOOP_LEN = 1000 * 1000; // the space in the file name mandated by // http://jira.qos.ch/browse/LBCORE-119 final static String CONF_FILE_AS_STR = ClassicTestConstants.INPUT_PREFIX - + "turbo/scan_perf.xml"; + + "turbo/scan_perf_barebones.xml"; // it actually takes time for Windows to propagate file modification changes // values below 100 milliseconds can be problematic the same propagation @@ -60,9 +62,9 @@ public class ReconfigurePerf { // take into account propagation latency occurs on Linux if (Env.isLinux()) { sleepBetweenUpdates = 850; - totalTestDuration = sleepBetweenUpdates * 5; + totalTestDuration = sleepBetweenUpdates * 25; } else { - totalTestDuration = sleepBetweenUpdates * 10; + totalTestDuration = sleepBetweenUpdates * 50; } harness = new MultiThreadedHarness(totalTestDuration); } @@ -86,11 +88,11 @@ public class ReconfigurePerf { public void scan1() throws JoranException, IOException, InterruptedException { File file = new File(CONF_FILE_AS_STR); configure(file); - doRun(); - doRun(); - doRun(); + //doRun(); + //doRun(); + //doRun(); System.out.println("ENTER :"); - System.in.read(); + //System.in.read(); doRun(); } @@ -99,28 +101,28 @@ public class ReconfigurePerf { harness.execute(runnableArray); } - ReconfigureOnChangeFilter initROCF() throws MalformedURLException { - ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter(); - rocf.setContext(loggerContext); - File file = new File(CONF_FILE_AS_STR); - loggerContext.putObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN, - file.toURI().toURL()); - rocf.start(); - return rocf; - } - - - public double directLoop(ReconfigureOnChangeFilter rocf) { - long start = System.nanoTime(); - for (int i = 0; i < LOOP_LEN; i++) { - rocf.decide(null, logger, Level.DEBUG, " ", null, null); - } - long end = System.nanoTime(); - return (end - start) / (1.0d * LOOP_LEN); - } - - void addInfo(String msg, Object o) { - loggerContext.getStatusManager().add(new InfoStatus(msg, o)); - } +// ReconfigureOnChangeFilter initROCF() throws MalformedURLException { +// ReconfigureOnChangeFilter rocf = new ReconfigureOnChangeFilter(); +// rocf.setContext(loggerContext); +// File file = new File(CONF_FILE_AS_STR); +// loggerContext.putObject(CoreConstants.URL_OF_LAST_CONFIGURATION_VIA_JORAN, +// file.toURI().toURL()); +// rocf.start(); +// return rocf; +// } + + +// public double directLoop(ReconfigureOnChangeFilter rocf) { +// long start = System.nanoTime(); +// for (int i = 0; i < LOOP_LEN; i++) { +// rocf.decide(null, logger, Level.DEBUG, " ", null, null); +// } +// long end = System.nanoTime(); +// return (end - start) / (1.0d * LOOP_LEN); +// } +// +// void addInfo(String msg, Object o) { +// loggerContext.getStatusManager().add(new InfoStatus(msg, o)); +// } } diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java index cdb0958..14a8033 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/DynamicConverter.java @@ -15,10 +15,16 @@ package ch.qos.logback.core.pattern; import java.util.List; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.ContextAwareBase; import ch.qos.logback.core.spi.LifeCycle; +import ch.qos.logback.core.status.Status; abstract public class DynamicConverter extends FormattingConverter - implements LifeCycle { + implements LifeCycle, ContextAware { + + ContextAwareBase cab = new ContextAwareBase(this); // Contains a list of option Strings. private List optionList; @@ -67,4 +73,40 @@ abstract public class DynamicConverter extends FormattingConverter protected List getOptionList() { return optionList; } + + public void setContext(Context context) { + cab.setContext(context); + } + + public Context getContext() { + return cab.getContext(); + } + + public void addStatus(Status status) { + cab.addStatus(status); + } + + public void addInfo(String msg) { + cab.addInfo(msg); + } + + public void addInfo(String msg, Throwable ex) { + cab.addInfo(msg, ex); + } + + public void addWarn(String msg) { + cab.addWarn(msg); + } + + public void addWarn(String msg, Throwable ex) { + cab.addWarn(msg, ex); + } + + public void addError(String msg) { + cab.addError(msg); + } + + public void addError(String msg, Throwable ex) { + cab.addError(msg, ex); + } } diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java index c5e29ef..55ef3ff 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java @@ -13,19 +13,45 @@ */ package ch.qos.logback.core.pattern; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.spi.ContextAware; + import java.util.List; +import java.util.regex.Pattern; public class ReplacingCompositeConverter extends CompositeConverter { + Pattern pattern; String regex; - String by; + String replacement; public void start() { - final List optionList = getOptionList(); - regex = optionList.get(0); + final List optionList = getOptionList(); + if (optionList == null) { + addError("at least two options are expected whereas you have declared none"); + return; + } + + int numOpts = optionList.size(); + + if (numOpts < 2) { + addError("at least two options are expected whereas you have declared only " + numOpts + "as [" + optionList + "]"); + return; + } + regex = optionList.get(0); + pattern = Pattern.compile(regex); + + //.matcher(this).replaceAll(replacement); + + replacement = optionList.get(1); + System.out.println("regex="+regex); + super.start(); } + @Override String transform(String in) { - return null; //To change body of implemented methods use File | Settings | File Templates. + if (!started) + return in; + return pattern.matcher(in).replaceAll(replacement); } -} +} \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java index ad4c762..369a67f 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java @@ -16,6 +16,7 @@ package ch.qos.logback.core.pattern.parser; import java.util.ArrayList; import java.util.List; +import ch.qos.logback.core.pattern.util.AsIsEscapeUtil; import ch.qos.logback.core.pattern.util.IEscapeUtil; import ch.qos.logback.core.pattern.util.RegularEscapeUtil; @@ -43,7 +44,7 @@ public class OptionTokenizer { * @param pattern */ OptionTokenizer(String pattern) { - this(pattern, new RegularEscapeUtil()); + this(pattern, new AsIsEscapeUtil()); } OptionTokenizer(String pattern, IEscapeUtil escapeUtil) { @@ -68,6 +69,8 @@ public class OptionTokenizer { case '\r': case '\n': break; + case COMMA_CHAR: + break; case SINGLE_QUOTE_CHAR: case DOUBLE_QUOTE_CHAR: state = QUOTED_COLLECTING_STATE; diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java index 19d8311..085947a 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import ch.qos.logback.core.CoreConstants; import ch.qos.logback.core.pattern.util.IEscapeUtil; import ch.qos.logback.core.pattern.util.RegularEscapeUtil; +import ch.qos.logback.core.pattern.util.RestrictedEscapeUtil; /** *

@@ -49,11 +50,14 @@ class TokenStream { private static final int FORMAT_MODIFIER_STATE = 1; private static final int KEYWORD_STATE = 2; private static final int OPTION_STATE = 3; + private static final int RIGHT_PARENTHESIS_STATE = 4; final String pattern; final int patternLength; final IEscapeUtil escapeUtil; + final IEscapeUtil optionEscapeUtil = new RestrictedEscapeUtil(); + int state = LITERAL_STATE; int pointer = 0; @@ -81,30 +85,21 @@ class TokenStream { pointer++; switch (state) { - case LITERAL_STATE: handleLiteralState(c, tokenList, buf); break; - // case FORMAT_MODIFIER_STATE: handleFormatModifierState(c, tokenList, buf); break; case OPTION_STATE: - switch (c) { - case CURLY_RIGHT: - addValuedToken(Token.OPTION, buf, tokenList); - state = LITERAL_STATE; - break; - case ESCAPE_CHAR: - escape("%{}", buf); - break; - default: - buf.append(c); - } + handleOptionState(c, tokenList, buf); break; case KEYWORD_STATE: handleKeywordState(c, tokenList, buf); break; + case RIGHT_PARENTHESIS_STATE: + handleRightParenthesisState(c, tokenList, buf); + break; default: } @@ -117,7 +112,9 @@ class TokenStream { break; case KEYWORD_STATE: tokenList.add(new Token(Token.SIMPLE_KEYWORD, buf.toString())); - buf.setLength(0); + break; + case RIGHT_PARENTHESIS_STATE: + tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); break; case FORMAT_MODIFIER_STATE: @@ -128,6 +125,38 @@ class TokenStream { return tokenList; } + private void handleRightParenthesisState(char c, List tokenList, StringBuffer buf) { + tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); + switch (c) { + case CoreConstants.RIGHT_PARENTHESIS_CHAR: + break; + case CURLY_LEFT: + state = OPTION_STATE; + break; + case ESCAPE_CHAR: + escape("%{}", buf); + state = LITERAL_STATE; + break; + default: + buf.append(c); + state = LITERAL_STATE; + } + } + + private void handleOptionState(char c, List tokenList, StringBuffer buf) { + switch (c) { + case CURLY_RIGHT: + addValuedToken(Token.OPTION, buf, tokenList); + state = LITERAL_STATE; + break; + case ESCAPE_CHAR: + optionEscape("}", buf); + break; + default: + buf.append(c); + } + } + private void handleFormatModifierState(char c, List tokenList, StringBuffer buf) { if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) { addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList); @@ -155,13 +184,8 @@ class TokenStream { break; case CoreConstants.RIGHT_PARENTHESIS_CHAR: - if (buf.length() >= 1 && buf.charAt(buf.length() - 1) == '\\') { - buf.deleteCharAt(buf.length() - 1); - buf.append(CoreConstants.RIGHT_PARENTHESIS_CHAR); - } else { - addValuedToken(Token.LITERAL, buf, tokenList); - tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); - } + addValuedToken(Token.LITERAL, buf, tokenList); + state = RIGHT_PARENTHESIS_STATE; break; default: @@ -170,11 +194,12 @@ class TokenStream { } private void handleKeywordState(char c, List tokenList, StringBuffer buf) { - if (c == CURLY_LEFT) { + + if (Character.isJavaIdentifierPart(c)) { + buf.append(c); + } else if (c == CURLY_LEFT) { addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList); state = OPTION_STATE; - } else if (Character.isJavaIdentifierPart(c)) { - buf.append(c); } else if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) { addValuedToken(Token.COMPOSITE_KEYWORD, buf, tokenList); state = LITERAL_STATE; @@ -182,12 +207,12 @@ class TokenStream { addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList); tokenList.add(Token.PERCENT_TOKEN); state = FORMAT_MODIFIER_STATE; + } else if (c == CoreConstants.RIGHT_PARENTHESIS_CHAR) { + addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList); + state = RIGHT_PARENTHESIS_STATE; } else { addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList); - if (c == CoreConstants.RIGHT_PARENTHESIS_CHAR) { - // if c is a right parenthesis, then add it as such - tokenList.add(Token.RIGHT_PARENTHESIS_TOKEN); - } else if (c == ESCAPE_CHAR) { + if (c == ESCAPE_CHAR) { if ((pointer < patternLength)) { char next = pattern.charAt(pointer++); escapeUtil.escape("%()", buf, next, pointer); @@ -206,6 +231,16 @@ class TokenStream { } } + void optionEscape(String escapeChars, StringBuffer buf) { + if ((pointer < patternLength)) { + char next = pattern.charAt(pointer++); + optionEscapeUtil.escape(escapeChars, buf, next, pointer); + } + } + + + + private void addValuedToken(int type, StringBuffer buf, List tokenList) { if (buf.length() > 0) { tokenList.add(new Token(type, buf.toString())); diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java index f9103cd..959c82d 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AlmostAsIsEscapeUtil.java @@ -21,7 +21,7 @@ import ch.qos.logback.core.rolling.helper.FileNamePattern; * * @author Ceki Gülcü */ -public class AlmostAsIsEscapeUtil implements IEscapeUtil { +public class AlmostAsIsEscapeUtil extends RestrictedEscapeUtil { /** * Do not perform any character escaping, except for '%', and ')'. @@ -40,16 +40,6 @@ public class AlmostAsIsEscapeUtil implements IEscapeUtil { */ public void escape(String escapeChars, StringBuffer buf, char next, int pointer) { - - if (next == CoreConstants.PERCENT_CHAR - || next == CoreConstants.RIGHT_PARENTHESIS_CHAR) { - buf.append(next); - } else { - // restitute the escape char (because it was consumed - // before this method was called). - buf.append("\\"); - // restitute the next character - buf.append(next); - } + super.escape(""+CoreConstants.PERCENT_CHAR+CoreConstants.RIGHT_PARENTHESIS_CHAR, buf, next, pointer); } } diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AsIsEscapeUtil.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AsIsEscapeUtil.java new file mode 100644 index 0000000..224bad9 --- /dev/null +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/AsIsEscapeUtil.java @@ -0,0 +1,38 @@ +/** + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2009, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ +package ch.qos.logback.core.pattern.util; + +import ch.qos.logback.core.CoreConstants; +import ch.qos.logback.core.rolling.helper.FileNamePattern; + +/** + * @author Ceki Gülcü + */ +public class AsIsEscapeUtil implements IEscapeUtil { + + /** + * Do not perform any character escaping. + *

+ * Note that this method assumes that it is called after the escape character + * has been consumed. + */ + public void escape(String escapeChars, StringBuffer buf, char next, + int pointer) { + // restitute the escape char (because it was consumed + // before this method was called). + buf.append("\\"); + // restitute the next character + buf.append(next); + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RestrictedEscapeUtil.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RestrictedEscapeUtil.java new file mode 100644 index 0000000..219d8ae --- /dev/null +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/util/RestrictedEscapeUtil.java @@ -0,0 +1,37 @@ +/** + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2009, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ +package ch.qos.logback.core.pattern.util; + +/** + * This implementation is intended for use in PatternLayout. + * + * @author Ceki Gülcü + */ +public class RestrictedEscapeUtil implements IEscapeUtil { + + public void escape(String escapeChars, StringBuffer buf, char next, + int pointer) { + if (escapeChars.indexOf(next) >= 0) { + buf.append(next); + } else { + // restitute the escape char (because it was consumed + // before this method was called). + buf.append("\\"); + // restitute the next character + buf.append(next); + } + } + + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java b/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java index 133bbbf..874a03d 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/ContextAwareBase.java @@ -29,6 +29,14 @@ import ch.qos.logback.core.status.WarnStatus; public class ContextAwareBase implements ContextAware { private int noContextWarning = 0; protected Context context; + final Object declaredOrigin; + + public ContextAwareBase() { + declaredOrigin = this; + } + public ContextAwareBase(Object declaredOrigin) { + this.declaredOrigin = declaredOrigin; + } public void setContext(Context context) { if (this.context == null) { @@ -56,7 +64,7 @@ public class ContextAwareBase implements ContextAware { * @return the declared origin, by default 'this' */ protected Object getDeclaredOrigin() { - return this; + return declaredOrigin; } public void addStatus(Status status) { diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java index e1a3d53..6c8db70 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java @@ -118,6 +118,20 @@ public class OptionTokenizerTest { witness.add("b"); assertEquals(witness, ol); } + { + List ol = new OptionTokenizer("'a', b").tokenize(); + List witness = new ArrayList(); + witness.add("a"); + witness.add("b"); + assertEquals(witness, ol); + } + { + List ol = new OptionTokenizer("'', b").tokenize(); + List witness = new ArrayList(); + witness.add(""); + witness.add("b"); + assertEquals(witness, ol); + } } } \ No newline at end of file diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java index c9d12a0..751f515 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java @@ -19,6 +19,7 @@ import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.List; +import org.junit.Ignore; import org.junit.Test; import ch.qos.logback.core.pattern.util.AlmostAsIsEscapeUtil; ----------------------------------------------------------------------- Summary of changes: .../logback/classic/pattern/ClassicConverter.java | 50 +---------- .../classic/turbo/ReconfigureOnChangeFilter.java | 3 +- .../ch/qos/logback/classic/PatternLayoutTest.java | 43 +++++++-- .../qos/logback/classic/turbo/ReconfigurePerf.java | 64 +++++++------- .../qos/logback/core/pattern/DynamicConverter.java | 44 +++++++++- .../core/pattern/ReplacingCompositeConverter.java | 36 +++++++- .../core/pattern/parser/OptionTokenizer.java | 5 +- .../logback/core/pattern/parser/TokenStream.java | 91 ++++++++++++++------ .../core/pattern/util/AlmostAsIsEscapeUtil.java | 14 +--- .../logback/core/pattern/util/AsIsEscapeUtil.java | 38 ++++++++ .../core/pattern/util/RestrictedEscapeUtil.java | 37 ++++++++ .../ch/qos/logback/core/spi/ContextAwareBase.java | 10 ++- .../core/pattern/parser/OptionTokenizerTest.java | 14 +++ .../core/pattern/parser/TokenStreamTest.java | 1 + 14 files changed, 313 insertions(+), 137 deletions(-) create mode 100644 logback-core/src/main/java/ch/qos/logback/core/pattern/util/AsIsEscapeUtil.java create mode 100644 logback-core/src/main/java/ch/qos/logback/core/pattern/util/RestrictedEscapeUtil.java hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From noreply-jira at qos.ch Wed Dec 15 23:57:51 2010 From: noreply-jira at qos.ch (Jay Taylor (JIRA)) Date: Wed, 15 Dec 2010 23:57:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBSITE-42) SMTPHost property name incorrect in documentation Message-ID: <658599864.1292453871276.JavaMail.ceki@pixie> SMTPHost property name incorrect in documentation ------------------------------------------------- Key: LBSITE-42 URL: http://jira.qos.ch/browse/LBSITE-42 Project: logback-site Issue Type: Bug Components: Documentation Affects Versions: 0.9.26 Environment: Linux hostname-03 2.6.27-17-server #1 SMP Fri Mar 12 04:04:33 UTC 2010 i686 GNU/Linux Reporter: Jay Taylor Assignee: Logback dev list Priority: Trivial The following documentation appears to have some incorrect information: http://logback.qos.ch/manual/appenders.html#SMTPAppender The table includes a property named "smtpHost". Using this value results in logback ignoring the setting and attempting to send mail through localhost. The correct property name appears to be "SMTPHost". The documentation also states that the parameter is mandatory. It appears to fall back to localhost if it is not encountered (perhaps java-mail is doing that). I would assume that "smtpPort" is incorrect too based on the setter name of "SMTPPort" in SMTPAppenderBase. Log info: |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.classic.net.SMTPAppender] |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [TEST] |-ERROR in ch.qos.logback.core.joran.spi.Interpreter at 22:13 - no applicable action for [smtpHost], current pattern is [[configuration][appender][smtpHost]] |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.classic.net.SMTPAppender] ... |-ERROR in ch.qos.logback.classic.net.SMTPAppender[POR] - Error occured while sending e-mail notification. javax.mail.SendFailedException: Send failure (javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25 (java.net.ConnectException: Connection refused)) at javax.mail.SendFailedException: Send failure (javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25 (java.net.ConnectException: Connection refused)) at at javax.mail.Transport.send(Transport.java:163) at at javax.mail.Transport.send(Transport.java:48) at at ch.qos.logback.core.net.SMTPAppenderBase.sendBuffer(SMTPAppenderBase.java:323) at at ch.qos.logback.core.net.SMTPAppenderBase.append(SMTPAppenderBase.java:181) at at ch.qos.logback.core.AppenderBase.doAppend(AppenderBase.java:85) -- 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 From noreply-jira at qos.ch Thu Dec 16 08:57:52 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Thu, 16 Dec 2010 08:57:52 +0100 (CET) Subject: [logback-dev] [JIRA] Assigned: (LBSITE-42) SMTPHost property name incorrect in documentation In-Reply-To: <658599864.1292453871276.JavaMail.ceki@pixie> Message-ID: <431413731.1292486272914.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBSITE-42?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu reassigned LBSITE-42: -------------------------------- Assignee: Ceki Gulcu (was: Logback dev list) > SMTPHost property name incorrect in documentation > ------------------------------------------------- > > Key: LBSITE-42 > URL: http://jira.qos.ch/browse/LBSITE-42 > Project: logback-site > Issue Type: Bug > Components: Documentation > Affects Versions: 0.9.26 > Environment: Linux hostname-03 2.6.27-17-server #1 SMP Fri Mar 12 04:04:33 UTC 2010 i686 GNU/Linux > Reporter: Jay Taylor > Assignee: Ceki Gulcu > Priority: Trivial > > The following documentation appears to have some incorrect information: http://logback.qos.ch/manual/appenders.html#SMTPAppender > The table includes a property named "smtpHost". Using this value results in logback ignoring the setting and attempting to send mail through localhost. > The correct property name appears to be "SMTPHost". The documentation also states that the parameter is mandatory. It appears to fall back to localhost if it is not encountered (perhaps java-mail is doing that). > I would assume that "smtpPort" is incorrect too based on the setter name of "SMTPPort" in SMTPAppenderBase. > Log info: > |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.classic.net.SMTPAppender] > |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [TEST] > |-ERROR in ch.qos.logback.core.joran.spi.Interpreter at 22:13 - no applicable action for [smtpHost], current pattern is [[configuration][appender][smtpHost]] > |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.classic.net.SMTPAppender] > ... > |-ERROR in ch.qos.logback.classic.net.SMTPAppender[POR] - Error occured while sending e-mail notification. javax.mail.SendFailedException: Send failure (javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25 (java.net.ConnectException: Connection refused)) > at javax.mail.SendFailedException: Send failure (javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25 (java.net.ConnectException: Connection refused)) > at at javax.mail.Transport.send(Transport.java:163) > at at javax.mail.Transport.send(Transport.java:48) > at at ch.qos.logback.core.net.SMTPAppenderBase.sendBuffer(SMTPAppenderBase.java:323) > at at ch.qos.logback.core.net.SMTPAppenderBase.append(SMTPAppenderBase.java:181) > at at ch.qos.logback.core.AppenderBase.doAppend(AppenderBase.java:85) -- 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 From noreply-jira at qos.ch Thu Dec 16 08:57:52 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Thu, 16 Dec 2010 08:57:52 +0100 (CET) Subject: [logback-dev] [JIRA] Updated: (LBSITE-42) SMTPHost property name incorrect in documentation In-Reply-To: <658599864.1292453871276.JavaMail.ceki@pixie> Message-ID: <748226498.1292486272980.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBSITE-42?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu updated LBSITE-42: ----------------------------- Priority: Major (was: Trivial) > SMTPHost property name incorrect in documentation > ------------------------------------------------- > > Key: LBSITE-42 > URL: http://jira.qos.ch/browse/LBSITE-42 > Project: logback-site > Issue Type: Bug > Components: Documentation > Affects Versions: 0.9.26 > Environment: Linux hostname-03 2.6.27-17-server #1 SMP Fri Mar 12 04:04:33 UTC 2010 i686 GNU/Linux > Reporter: Jay Taylor > Assignee: Ceki Gulcu > > The following documentation appears to have some incorrect information: http://logback.qos.ch/manual/appenders.html#SMTPAppender > The table includes a property named "smtpHost". Using this value results in logback ignoring the setting and attempting to send mail through localhost. > The correct property name appears to be "SMTPHost". The documentation also states that the parameter is mandatory. It appears to fall back to localhost if it is not encountered (perhaps java-mail is doing that). > I would assume that "smtpPort" is incorrect too based on the setter name of "SMTPPort" in SMTPAppenderBase. > Log info: > |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.classic.net.SMTPAppender] > |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [TEST] > |-ERROR in ch.qos.logback.core.joran.spi.Interpreter at 22:13 - no applicable action for [smtpHost], current pattern is [[configuration][appender][smtpHost]] > |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.classic.net.SMTPAppender] > ... > |-ERROR in ch.qos.logback.classic.net.SMTPAppender[POR] - Error occured while sending e-mail notification. javax.mail.SendFailedException: Send failure (javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25 (java.net.ConnectException: Connection refused)) > at javax.mail.SendFailedException: Send failure (javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25 (java.net.ConnectException: Connection refused)) > at at javax.mail.Transport.send(Transport.java:163) > at at javax.mail.Transport.send(Transport.java:48) > at at ch.qos.logback.core.net.SMTPAppenderBase.sendBuffer(SMTPAppenderBase.java:323) > at at ch.qos.logback.core.net.SMTPAppenderBase.append(SMTPAppenderBase.java:181) > at at ch.qos.logback.core.AppenderBase.doAppend(AppenderBase.java:85) -- 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 From noreply-jira at qos.ch Thu Dec 16 10:31:51 2010 From: noreply-jira at qos.ch (Vincent Ricard (JIRA)) Date: Thu, 16 Dec 2010 10:31:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBACCESS-22) Wrong date format in access log Message-ID: <1382324541.1292491911246.JavaMail.ceki@pixie> Wrong date format in access log ------------------------------- Key: LBACCESS-22 URL: http://jira.qos.ch/browse/LBACCESS-22 Project: logback-access Issue Type: Bug Environment: French default locale Reporter: Vincent Ricard Assignee: Logback dev list Priority: Minor Hi, According to http://httpd.apache.org/docs/current/mod/mod_log_config.html#formats (see '%t' documentation) and http://httpd.apache.org/docs/current/logs.html#common, the output should be "10/Dec/2010" (with no accents, even with my french environment). So, i think the CoreConstants.CLF_DATE_PATTERN should be "dd/MMM/yyyy:HH:mm:ss Z"; and the SimpleDateFormat should be instantiated with Locale.EN_US or Locale.ENGLISH for the %t default case. Regards -- 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 From noreply-jira at qos.ch Thu Dec 16 16:38:51 2010 From: noreply-jira at qos.ch (Radenko Kalajdzic (JIRA)) Date: Thu, 16 Dec 2010 16:38:51 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBGENERAL-37) Need to scan included files In-Reply-To: <1065459848.1257888044290.JavaMail.ceki@pixie> Message-ID: <1979030140.1292513931313.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBGENERAL-37?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11916#action_11916 ] Radenko Kalajdzic commented on LBGENERAL-37: -------------------------------------------- I need this functionnality too. > Need to scan included files > --------------------------- > > Key: LBGENERAL-37 > URL: http://jira.qos.ch/browse/LBGENERAL-37 > Project: logback-general > Issue Type: New Feature > Reporter: Geoffrey > Assignee: Logback dev list > Priority: Minor > > I'm using the following configuration and I'm looking for a method to scan included files. > > > lala > > > Once scan directive is used, logback is going to rescan this file every 10 seconds whether its modification date has changed. > The issue is that I have to overwrite the previous file in order to rescan the target ${logback-file}. > I suggest adding an attribute in the configuration marker in order to force logback to scan included files . It could be something like that: > > ..... > > In order to process this task, at each scan logback should memorize the reference to the included files, and their latest modification date. Consequently, every 10 seconds, logback check the whole list of files and rescan the main file if something has changed. -- 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 From noreply-jira at qos.ch Fri Dec 17 09:19:52 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Fri, 17 Dec 2010 09:19:52 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBCORE-185) continuous size based rolling in case file renaming fails Message-ID: <19404251.1292573992271.JavaMail.ceki@pixie> continuous size based rolling in case file renaming fails --------------------------------------------------------- Key: LBCORE-185 URL: http://jira.qos.ch/browse/LBCORE-185 Project: logback-core Issue Type: Bug Components: Appender Reporter: Ceki Gulcu Assignee: Logback dev list Priority: Critical In case file renaming fails during roll over, size based triggering is triggered continuously. To reproduce: use size based triggering+open the log file in another process. -- 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 From noreply-jira at qos.ch Fri Dec 17 10:09:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Fri, 17 Dec 2010 10:09:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBCORE-186) Logging when two instances of the application running at the same time Message-ID: <1448277109.1292576991287.JavaMail.ceki@pixie> Logging when two instances of the application running at the same time ----------------------------------------------------------------------- Key: LBCORE-186 URL: http://jira.qos.ch/browse/LBCORE-186 Project: logback-core Issue Type: Bug Reporter: Ceki Gulcu Assignee: Logback dev list What happens then two instances of the application are running at the same time, e.g. weblogic support for running two simultaneous versions of the same app? -- 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 From noreply-jira at qos.ch Fri Dec 17 10:09:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Fri, 17 Dec 2010 10:09:51 +0100 (CET) Subject: [logback-dev] [JIRA] Assigned: (LBCORE-186) Logging when two instances of the application running at the same time In-Reply-To: <1448277109.1292576991287.JavaMail.ceki@pixie> Message-ID: <853727315.1292576991635.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-186?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu reassigned LBCORE-186: --------------------------------- Assignee: Ceki Gulcu (was: Logback dev list) > Logging when two instances of the application running at the same time > ----------------------------------------------------------------------- > > Key: LBCORE-186 > URL: http://jira.qos.ch/browse/LBCORE-186 > Project: logback-core > Issue Type: Bug > Reporter: Ceki Gulcu > Assignee: Ceki Gulcu > > What happens then two instances of the application are running at the same time, e.g. weblogic support for running two simultaneous versions of the same app? -- 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 From noreply-jira at qos.ch Fri Dec 17 10:11:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Fri, 17 Dec 2010 10:11:51 +0100 (CET) Subject: [logback-dev] [JIRA] Assigned: (LBCORE-185) continuous size based rolling in case file renaming fails In-Reply-To: <19404251.1292573992271.JavaMail.ceki@pixie> Message-ID: <1230764159.1292577111438.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-185?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu reassigned LBCORE-185: --------------------------------- Assignee: Ceki Gulcu (was: Logback dev list) > continuous size based rolling in case file renaming fails > --------------------------------------------------------- > > Key: LBCORE-185 > URL: http://jira.qos.ch/browse/LBCORE-185 > Project: logback-core > Issue Type: Bug > Components: Appender > Reporter: Ceki Gulcu > Assignee: Ceki Gulcu > Priority: Critical > > In case file renaming fails during roll over, size based triggering is triggered continuously. To reproduce: use size based triggering+open the log file in another process. -- 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 From noreply-jira at qos.ch Fri Dec 17 10:15:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Fri, 17 Dec 2010 10:15:51 +0100 (CET) Subject: [logback-dev] [JIRA] Updated: (LBCORE-185) continuous size based rolling in case file renaming fails In-Reply-To: <19404251.1292573992271.JavaMail.ceki@pixie> Message-ID: <382214044.1292577351521.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-185?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu updated LBCORE-185: ------------------------------ Priority: Blocker (was: Critical) > continuous size based rolling in case file renaming fails > --------------------------------------------------------- > > Key: LBCORE-185 > URL: http://jira.qos.ch/browse/LBCORE-185 > Project: logback-core > Issue Type: Bug > Components: Appender > Reporter: Ceki Gulcu > Assignee: Ceki Gulcu > Priority: Blocker > > In case file renaming fails during roll over, size based triggering is triggered continuously. To reproduce: use size based triggering+open the log file in another process. -- 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 From git-noreply at pixie.qos.ch Fri Dec 17 17:36:14 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Fri, 17 Dec 2010 17:36:14 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-44-g41c1e10 Message-ID: <20101217163615.22F8E3170C7@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via 41c1e10c305e5a34005c3ccabbc2e35a46faf2e8 (commit) from 888d97dcca98ab928da7d67bf6660c293cd47b9e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=41c1e10c305e5a34005c3ccabbc2e35a46faf2e8 http://github.com/ceki/logback/commit/41c1e10c305e5a34005c3ccabbc2e35a46faf2e8 commit 41c1e10c305e5a34005c3ccabbc2e35a46faf2e8 Author: Ceki Gulcu Date: Fri Dec 17 17:36:10 2010 +0100 working version of compound keywords diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java index 510aa7a..dff1bf8 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java @@ -118,14 +118,10 @@ public class Parser extends ContextAwareBase { } } + // T = LITERAL | '%' C | '%' FORMAT_MODIFIER C Node T() throws ScanException { - // System.out.println("in T()"); Token t = getCurentToken(); - if (t == null) { - throw new IllegalStateException("a LITERAL or '%'"); - } - - // System.out.println("Current token is " + t); + expectNotNull(t, "a LITERAL or '%'"); switch (t.getType()) { case Token.LITERAL: @@ -137,7 +133,7 @@ public class Parser extends ContextAwareBase { FormatInfo fi; Token u = getCurentToken(); FormattingNode c; - expectNotNull(u, "a FORMAT_MODIFIER, KEYWORD or LEFT_PARENTHESIS"); + expectNotNull(u, "a FORMAT_MODIFIER, SIMPLE_KEYWORD or COMPOUND_KEYWORD"); if (u.getType() == Token.FORMAT_MODIFIER) { fi = FormatInfo.valueOf((String) u.getValue()); advanceTokenPointer(); diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java index 6c8db70..bd23c5a 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java @@ -20,7 +20,7 @@ import java.util.List; import org.junit.Test; -public class OptionTokenizerTest { +public class OptionTokenizerTest { @Test public void testEmpty() throws ScanException { @@ -66,18 +66,20 @@ public class OptionTokenizerTest { { List ol = new OptionTokenizer("' x\\t'").tokenize(); List witness = new ArrayList(); - witness.add(" x\t"); + witness.add(" x\\t"); assertEquals(witness, ol); } { List ol = new OptionTokenizer("' x\\''").tokenize(); List witness = new ArrayList(); - witness.add(" x\'"); + witness.add(" x\\'"); assertEquals(witness, ol); } } + + @Test public void testDoubleQuote() throws ScanException { { @@ -97,14 +99,14 @@ public class OptionTokenizerTest { { List ol = new OptionTokenizer("\" x\\t\"").tokenize(); List witness = new ArrayList(); - witness.add(" x\t"); + witness.add(" x\\t"); assertEquals(witness, ol); } { List ol = new OptionTokenizer("\" x\\\"\"").tokenize(); List witness = new ArrayList(); - witness.add(" x\""); + witness.add(" x\\\""); assertEquals(witness, ol); } } ----------------------------------------------------------------------- Summary of changes: .../ch/qos/logback/core/pattern/parser/Parser.java | 10 +++------- .../core/pattern/parser/OptionTokenizerTest.java | 12 +++++++----- 2 files changed, 10 insertions(+), 12 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From noreply-jira at qos.ch Fri Dec 17 17:52:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Fri, 17 Dec 2010 17:52:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBCORE-187) TimestampAction should base current time on LoggerContext birthtime field Message-ID: <1028159143.1292604771281.JavaMail.ceki@pixie> TimestampAction should base current time on LoggerContext birthtime field ------------------------------------------------------------------------- Key: LBCORE-187 URL: http://jira.qos.ch/browse/LBCORE-187 Project: logback-core Issue Type: Bug Affects Versions: 0.9.26 Reporter: Ceki Gulcu Assignee: Logback dev list As things stand currently, TimestampAction uses the date of invocation of the config file as the value to format and place as a property. Under certain circumstances, it might be useful to take the context's birth date as input value. -- 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 From noreply-jira at qos.ch Fri Dec 17 17:52:52 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Fri, 17 Dec 2010 17:52:52 +0100 (CET) Subject: [logback-dev] [JIRA] Assigned: (LBCORE-187) TimestampAction should base current time on LoggerContext birthtime field In-Reply-To: <1028159143.1292604771281.JavaMail.ceki@pixie> Message-ID: <1531281742.1292604772570.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-187?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu reassigned LBCORE-187: --------------------------------- Assignee: Ceki Gulcu (was: Logback dev list) > TimestampAction should base current time on LoggerContext birthtime field > ------------------------------------------------------------------------- > > Key: LBCORE-187 > URL: http://jira.qos.ch/browse/LBCORE-187 > Project: logback-core > Issue Type: Bug > Affects Versions: 0.9.26 > Reporter: Ceki Gulcu > Assignee: Ceki Gulcu > > As things stand currently, TimestampAction uses the date of invocation of the config file as the value to format and place as a property. Under certain circumstances, it might be useful to take the context's birth date as input value. -- 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 From git-noreply at pixie.qos.ch Fri Dec 17 18:49:42 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Fri, 17 Dec 2010 18:49:42 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-45-gcf96aaf Message-ID: <20101217174942.65E073170D0@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via cf96aaf8191b6312ed715c1f4729986205f8645f (commit) from 41c1e10c305e5a34005c3ccabbc2e35a46faf2e8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=cf96aaf8191b6312ed715c1f4729986205f8645f http://github.com/ceki/logback/commit/cf96aaf8191b6312ed715c1f4729986205f8645f commit cf96aaf8191b6312ed715c1f4729986205f8645f Author: Ceki Gulcu Date: Fri Dec 17 18:49:55 2010 +0100 doc improvements diff --git a/logback-site/src/site/pages/recipes/emailPerTransaction.html b/logback-site/src/site/pages/recipes/emailPerTransaction.html index 89e275d..87a7861 100644 --- a/logback-site/src/site/pages/recipes/emailPerTransaction.html +++ b/logback-site/src/site/pages/recipes/emailPerTransaction.html @@ -26,18 +26,18 @@

Let Dave and Carol be software QA engineers working at a company called Fooware.com. As you might have guessed, - Fooware.com sells foos. Yes, foos. Let Buscrit be a - business critical back-end system running at - Fooware.com. Buscrit is called by a number of applications to - make business-critical transactions of various types. + Fooware.com sells foos. Yes, foos... Let Buscrit be a + business critical backend system running at Fooware.com. Buscrit + is called by a number of applications to make business-critical + transactions of various types.

We would like to allow Carol to access the logging data - generated by Buscrit as conveniently as possible. Carol could - access the log files directly on the server where Buscrit - runs. Let us assume that accessing the log files is somehow - impractical because one or ore more of the following conditions - holds true: + generated by Buscrit as conveniently as possible. We could + assume that Carol has access the log files directly on the + server where Buscrit runs. However, let us assume that accessing + the log files is somehow impractical because one or ore more of + the following conditions holds true:

    @@ -48,7 +48,7 @@ hosts where Byscrit runs
  1. Buscrit is tested by multiple testers, e.g. Dave and Carol - and others, simultanesouly so that it is hard to indetify and + and others, simultanesouly so that it is hard to identify and track an individual transaction in the log files
@@ -112,19 +112,19 @@ public class PrimeAction extends Action {

In a real world application, a transaction would involve systems external to the application, e.g. a database or a messaging queue. For the sake of this example, let us consider - each factorization request as a transaciton. At the + each factorization request as a transaction. At the end of each factorization request, i.e. each transaction, the logger of the PrimeAction instance is invoked with the SMTP_TRIGGER marker and the message "Prime computation ended". We can capitalize on this logging request to clearly identify the end of every transaction in order to trigger an - outgoing message. + outgoing email message.

Here is a configuration file which uses JaninoEventEvaluator to trigger an outgoing email for logging event marked with SMTP_TRIGGER. -

+

<configuration scan="true" scanPeriod="3 seconds">
@@ -134,8 +134,8 @@ public class PrimeAction extends Action {
 
   <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
     <SMTPHost>NAME_OF_SMTP_HOST</SMTPHost>
-    <To>...</To>
-    <From>...</From>
+    <to>...</to>                                         
+    <from>...</from>
     <layout class="ch.qos.logback.classic.html.HTMLLayout">
       <pattern>%date%level%logger{24}%msg</pattern>
     </layout>
@@ -157,7 +157,8 @@ public class PrimeAction extends Action {
       
       

Transaction isolation

- +

+

<configuration scan="true" scanPeriod="3 seconds">
diff --git a/logback-site/src/site/pages/recipes/index.html b/logback-site/src/site/pages/recipes/index.html
index 84dc02b..8c5f5a1 100644
--- a/logback-site/src/site/pages/recipes/index.html
+++ b/logback-site/src/site/pages/recipes/index.html
@@ -26,9 +26,9 @@
         real-world use cases:

+
  • Triggering an + email containing the isoloated logs of selected + transactions

    • ----------------------------------------------------------------------- Summary of changes: .../site/pages/recipes/emailPerTransaction.html | 33 ++++++++++--------- logback-site/src/site/pages/recipes/index.html | 6 ++-- 2 files changed, 20 insertions(+), 19 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From noreply-jira at qos.ch Fri Dec 17 20:58:51 2010 From: noreply-jira at qos.ch (Bert B-L (JIRA)) Date: Fri, 17 Dec 2010 20:58:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBCORE-188) Log Rotation/Gzip process leaving .tmp files behind Message-ID: <1972951794.1292615931253.JavaMail.ceki@pixie> Log Rotation/Gzip process leaving .tmp files behind --------------------------------------------------- Key: LBCORE-188 URL: http://jira.qos.ch/browse/LBCORE-188 Project: logback-core Issue Type: Bug Components: Rolling Affects Versions: 0.9.26 Reporter: Bert B-L Assignee: Logback dev list We are seeing logback leave .tmp files behind in the log directory, presumably due to a hiccup during log rotation or gzip. Size 2365956 Dec 11 00:00 statsreceiver.log.2010-12-10.gz 2679618 Dec 12 00:01 statsreceiver.log.2010-12-11.gz 9190879942 Dec 12 04:00 statsreceiver-debug.log23124507802228260.tmp 2542799 Dec 13 00:00 statsreceiver.log.2010-12-12.gz 9137740366 Dec 13 04:00 statsreceiver-debug.log23210907242250260.tmp 543937393 Dec 13 20:07 statsreceiver-debug.log.2010-12-13_19:00.gz 548781049 Dec 13 22:07 statsreceiver-debug.log.2010-12-13_21:00.gz 2284216 Dec 14 00:00 statsreceiver.log.2010-12-13.gz 8127562 Dec 15 00:00 statsreceiver.log.2010-12-14.gz 19067117496 Dec 15 13:00 statsreceiver-debug.log23416102512001260.tmp 18177324477 Dec 15 16:00 statsreceiver-debug.log23426920509229260.tmp 2257423 Dec 15 23:00 statsreceiver-debug.log.2010-12-15_22:00.gz The logback jar versions are: WEB-INF/lib/logback-classic-0.9.26.jar WEB-INF/lib/logback-core-0.9.26.jar There is only a single application writing to those files, though it is conceivable that the .tmp droppings correlate to restarts of that application. If this is expected on application restarts, could logback start gzip'ing them again when it comes back? Here is the logback.xml file: ${logdir:-.}/${prog:-unknown}.log true warn ${logdir:-.}/${prog:-unknown}.log.%d{yyyy-MM-dd}.gz 7 %-30(%d{yyyy-MM-dd HH:mm:ss} %.-1level :) %m Context:[%X{GTNDC_INFO}]%n ${logdir:-.}/${prog:-unknown}-debug.log true debug ${logdir:-.}/${prog:-unknown}-debug.log.%d{yyyy-MM-dd_HH:00}.gz 36 %-60(%d{yyyy-MM-dd HH:mm:ss} [%thread] %.-1level :) %m Context:[%X{GTNDC_INFO}]%n -- 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 From git-noreply at pixie.qos.ch Mon Dec 20 20:29:34 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Mon, 20 Dec 2010 20:29:34 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-46-g4556c00 Message-ID: <20101220192935.47674317106@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via 4556c00a26f4aaee2d44d9d3fdff642297c32ffa (commit) from cf96aaf8191b6312ed715c1f4729986205f8645f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=4556c00a26f4aaee2d44d9d3fdff642297c32ffa http://github.com/ceki/logback/commit/4556c00a26f4aaee2d44d9d3fdff642297c32ffa commit 4556c00a26f4aaee2d44d9d3fdff642297c32ffa Author: Ceki Gulcu Date: Mon Dec 20 20:27:13 2010 +0100 applied Inigo Surguy's proof reading patch diff --git a/logback-site/src/site/pages/access.html b/logback-site/src/site/pages/access.html index e639bf1..faf68c4 100644 --- a/logback-site/src/site/pages/access.html +++ b/logback-site/src/site/pages/access.html @@ -166,7 +166,7 @@

      The ch.qos.logback.access.jetty.RequestLogImpl class - implements jetty's RequestLog interface. Jetty delegates the management of access logging functionality to implementations of this interface. @@ -180,7 +180,7 @@

      In order to configure Jetty to use logback-access's RequestLogImpl, please add the following lines to - jetty's main configuration file, namely + Jetty's main configuration file, namely $JETTY_HOME/etc/jetty.xml:

      <Ref id="requestLog">
      @@ -200,8 +200,8 @@
           

      As long the path is specified, you can place the logback - configuration file in any location. Here is another example of - jetty configuration file, including the path to the + configuration file in any location. Here is another example of a + Jetty configuration file, including the path to the logback-access.xml configuration file.

      @@ -473,7 +473,7 @@ CLASSPATH="$CLASSPATH":"$CATALINA_HOME"/bin/mx4j-impl.jar

      Here is the output generated when accessing the logback-demo application configured as shown - above, yields:

      + above:

      GET /logback-demo/index.jsp HTTP/1.1 Host: localhost:8080 diff --git a/logback-site/src/site/pages/bugreport.html b/logback-site/src/site/pages/bugreport.html index b22e383..07c30c6 100644 --- a/logback-site/src/site/pages/bugreport.html +++ b/logback-site/src/site/pages/bugreport.html @@ -25,7 +25,7 @@

      The logback community consists of those who use logback and its modules, help answer questions on discussions lists, contribute documentation and patches, and those who develop and maintain its - code. Almost all those who assist on a day to day basis resolving + code. Those who assist on a day to day basis resolving bug reports do this for a wide variety of reasons, and almost all of them do this on their own time.

      diff --git a/logback-site/src/site/pages/codes.html b/logback-site/src/site/pages/codes.html index 8a936c8..9fa6bd7 100644 --- a/logback-site/src/site/pages/codes.html +++ b/logback-site/src/site/pages/codes.html @@ -193,7 +193,7 @@

      A Layout is mandatory for - SMTPAppender. It allows SMPTPAppender to format logging + SMTPAppender. It allows SMTPAppender to format logging events before sending an email.

      @@ -378,7 +378,7 @@

      Given that FixedWindowRollingPolicy performs - multiple file rename operations suring roll over, and that these + multiple file rename operations during roll over, and that these operations cannot be guaranteed to be safe in a multi-JVM context, prudent mode is not allowed in conjuction with a FixedWindowRollingPolicy. @@ -399,7 +399,7 @@ contents of the message sent to the syslog daemon.

      -

      For more information on SyslogAppeder please refer to the For more information on SyslogAppender please refer to the its documentation.

      diff --git a/logback-site/src/site/pages/consolePlugin.html b/logback-site/src/site/pages/consolePlugin.html index 8079cbb..aa66d1b 100644 --- a/logback-site/src/site/pages/consolePlugin.html +++ b/logback-site/src/site/pages/consolePlugin.html @@ -60,7 +60,7 @@

      - Once the transfert is complete, unzip the file called + Once the transfer is complete, unzip the file called ch.qos.logback.eclipse_VERSION.zip. Place the folder found inside the archive in the following directory: ECLIPSE_INSTALL/plugins/ where ECLIPSE_INSTALL is the directory where you've installed Eclipse. @@ -93,7 +93,7 @@ events to the localhost, on port 4321 by default. That's all it takes to run your software and log to the logback plugin. By default, logging events are not filtered, but please keep in mind that context-wide filtering in your logging configuration may affect the events - that are recieved by the logback plugin. + that are received by the logback plugin.

      If you already have @@ -127,8 +127,8 @@

      The first button on the left clears the console. The second button toggles - the auto-scroll functionnality. When enabled, you will always see the latest - logs that have been recieved by the plugin. If you disable the auto scrolling, + the auto-scroll functionality. When enabled, you will always see the latest + logs that have been received by the plugin. If you disable the auto scrolling, the view will display the current logs, and add the new ones at the bottom of the list.

      @@ -152,15 +152,15 @@

      Double-clicking on a log entry will open a Java editor and show you the line - where the entry was requested. It is an easy way to be access directly - to the class and method that logged the selected entry. + where the entry was requested. It is an easy way to directly access + the class and method that logged the selected entry.

      When an icon is shown on the left of the logging event, it means that the logging event contains a stacktrace. Right-clicking on the line reveals a sub-menu that lets you open Eclipse's StackTrace Console and display the - stacktrace. You can click on the underlined parts of the stack trace to open + stacktrace. You can click on the underlined parts of the stacktrace to open an editor revealing the selected class.

      @@ -224,7 +224,7 @@ view before the list is trimmed. By default, the logback plugin will display 20'000 events. Once this number is reached, the plugin automatically drops the 30% oldest logs. Please note that changing this value to a too much higher - value might lead to memory issues, or even crashing Eclipse. + value might lead to memory issues, or even crash Eclipse.

      @@ -232,12 +232,12 @@

      The logback plugin lets you filter logging events when they are - recieved. It uses the powerfull EvaluatorFilterobjects + received. It uses the powerful EvaluatorFilter objects that are available in logback. For detailled information about these filters, you might want to check the corresponding documentation in the logback manual. In this document, we will only cover some basic points, enough to get you started using the filtering - functionnality of the logback plugin. + functionality of the logback plugin.

      @@ -254,8 +254,8 @@

      - A filter is composed of three informations. First, a Java expression, - that will be evaluated for each logging event that is recieved by + A filter is composed of three pieces of information. First, a Java expression, + that will be evaluated for each logging event that is received by the logback plugin. This expression can use a set of common variables such as level, logger, message, and several others. For a complete list of available variables, please @@ -264,8 +264,9 @@

      - The second and third informations that compose a filter are the - action that will be taken depending on the result of the evaluation. + The second and third pieces of information that compose a filter are the + actions that will be taken depending on the result of the evaluation, for + a filter match and a filter mismatch. Three actions are possible: ACCEPT, DENY or NEUTRAL. Setting a filter's reply to ACCEPT or DENY will prevent the plugin from evaluating any @@ -302,7 +303,7 @@ We've just created a filter that will drop any requests whose level is lower than INFO. Note the use of the NEUTRAL value as the action to be taken when the filter is matched. Since - we do not know what other filters might want to do, there is not reason + we do not know what other filters might want to do, there is no reason to stop evaluating when the level is higher or equal to INFO.

      @@ -317,7 +318,7 @@

      - You should now be ready to experience the logback plugin and use its functionnalites. + You should now be ready to experience the logback plugin and use its functionality. If you have any question about its use, feel free to use the logback mailing lists.

      diff --git a/logback-site/src/site/pages/demo.html b/logback-site/src/site/pages/demo.html index 60565e0..207ebc8 100644 --- a/logback-site/src/site/pages/demo.html +++ b/logback-site/src/site/pages/demo.html @@ -62,7 +62,7 @@ and a RollingFileAppender. The RollingFileAppender sends logging events to a file called logFile.log and will rollover the active file every - minute. The old file will be renamed and compressed to zip + minute. The old file will be renamed and compressed to a zip file. The ConsoleAppender will output the logging requests to the console, and shorten the logger names to gain space on the console window, without loss of legibility. For example, @@ -71,8 +71,8 @@

      We highly encourage you to study the logback.xml - configuratiun file located under the src/main/resources/ - folder. You might want to keep open this file in an editor window, + configuration file located under the src/main/resources/ + folder. You might want to keep this file open in an editor window, since we will modify its contents thoughout the demo.

      @@ -82,7 +82,7 @@ created up until now. Status objects are a part of logback's internal reporting framework. They allow you to see what is going on inside logback, and check that a configuration file has - been parsed correctly, or that a rollovers occur as expected. + been parsed correctly, or that rollovers occur as expected.

      You should be seeing log messages printed on the console and the @@ -90,7 +90,7 @@

      If you visit the View logs page (by clicking on the link - located in the menu on the left), you should see empty contemts. Let + located in the menu on the left), you should see it has no content. Let us change that by uncommenting two parts in the config file.

      @@ -107,23 +107,23 @@ <appender-ref ref="CYCLIC" /> -->

      -

      The <appender-ref> element element, found at the +

      The <appender-ref> element found at the end of the configuration file links an appender to a given logger, in this particular case the root logger.

      -

      A CyclicBuffer keeps track of incoming logging event +

      A CyclicBuffer keeps track of the incoming logging event stream in a circular buffer for later display. After having removed the comments - around the two elemetns shown above, reload the logback-demo + around the two element/s shown above, reload the logback-demo web-application by exiting the previous "mvn" command with CTRL-C and issuing it again:

      mvn package jetty:run

      -

      This time View logs page should have contents.

      +

      This time the View logs page should have contents.

      view logs @@ -140,7 +140,7 @@ Howdydy-diddly-ho messages is wasteful. We can get rid of them with an appropriate filter. Uncomment the block entitled Cyclic buffer with Evaluator. You should then comment the - block entitled "Basic Cyclic buffer" that we uncommmented + block entitled "Basic Cyclic buffer" that we uncommented earlier.

      Let's take a look at the filter we've just added:

      @@ -157,12 +157,12 @@ </filter>

      The <expression> element uses the familiar - Java-language syntax. It checks that the name of the logger contains + Java language syntax. It checks that the name of the logger contains the String LoggingTask, but also that its message contains the string Howdydy-diddly-ho. Moreover, in order to be sure that the Howdydy-diddly-ho task actually works, we add a last condition which checks that that at least 20 seconds have - elapsed after application launch. The variables references in the + elapsed after application launch. The variable references in the expression, namely (logger, message and event) are implicitly made available by logback. The <OnMatch> element lets the user specify the filter's @@ -177,7 +177,7 @@

      Turbo Filters

      -

      Logback support with a special category of filters called +

      Logback supports a special category of filters called TurboFilters. TurboFilter objects are ultra-fast, context-wide filters. They can be very useful by setting context-wide (i.e. global) conditions for enabling or disabling @@ -212,17 +212,17 @@ ... </root>

      -

      Now restart the server as previously

      +

      Now restart the server as before.

      -

      Once on the demo main webpage again, perform a number of actions +

      Once on the main demo webpage again, perform a number of actions (e.g. calculate a few prime numbers) and visit the View logs page. The table should be empty.

      -

      Now log in into the logback-demo web-application with the +

      Now login to the logback-demo web-application with the username sebastien and perform a few prime computations. The View logs page should show the logging - events thgat were generated. Moreover, each logging event will have + events that were generated. Moreover, each logging event will have an MDC field associated with the name of the logged in user, in this case, sebastien. Please log off before continuing the demo, using the logout button on the left. @@ -230,10 +230,10 @@ mdc filters -

      Parametrized logging

      +

      Parameterized logging

      Parametrized + href="http://www.slf4j.org/faq.html#logging_performance">Parameterized logging is not a logback feature per se. It is part of SLF4J. Usually, a logging request is issued as follows:

      @@ -253,9 +253,9 @@ if the log statement is enabled.

      -

      At present, let us see what kind of gain can we expect from this +

      At present, let us see what kind of gain we can expect from this alternative approach. First, go to the Prime number page - and compute factors for intergers of your choice. Check the time it + and compute factors for integers of your choice. Check the time it takes to compute the results. To see a clearer difference between the two formatting methods, you might want to try the two big integers that are listed below the prime number textbox. Jot down @@ -263,7 +263,7 @@

      Now let us edit the NumberCruncherImpl class in - order to use parametrized logging. You will find this class in the + order to use parameterized logging. You will find this class in the src/main/java/ch/qos/logback/demo/prime/ directory. Comment line 54 (doing unconditional message concatenation) and uncomment line 55 (parameterized logging). Restart the server with mvn @@ -271,11 +271,11 @@ beforehand.

      -

      The time required to complete the computation should much lower +

      The time required to complete the computation should be much lower this time. Remember that we have turned off all logging in the previous step of this demo. In the initial version, we were constructing the message ("Trying "+i+" as a factor.") each - time a factor was tested. With the paramatrized logging, the + time a factor was tested. With the parameterized logging, the construction of the message was postponed and, since logging was turned off, never done. Thus, parameterized logging can significantly reduce the cost of disabled log statements. @@ -287,16 +287,16 @@ part of the SLF4J API. If you look at the LoggingTask class (part of logback-demo) which includes the Howdydy-diddly-ho log statement, you should see that it is bound to a marker named - HOWDY marker. Assume we wish to drop log statements - bearing the HOWDY marker. Here is the - TurboFilter to do just that. + HOWDY marker. If you wish to drop log statements + bearing the HOWDY marker, you can use this + TurboFilter to do so:

      <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> <Name>HOWDY_FILTER</Name> - <Marker>HOWDY</Marker> - <OnMatch>DENY</OnMatch> - </turboFilter>

      + <Marker>HOWDY</Marker> + <OnMatch>DENY</OnMatch> +</turboFilter>

      After you have set the root logger's level back to DEBUG and uncommented the MarkerFilter block in logback.xml, @@ -305,7 +305,7 @@

      The logs bearing the Howdydy-diddly-ho message should no - longer appear as they associated with a HOWDY marker. You can check + longer appear as they are associated with a HOWDY marker. You can check that by visiting the View Logs page.

      @@ -335,20 +335,20 @@ </configuration>

    Note that logback-classic and logback-access are configured via - different files, logback.xml and respectively - logback-acces.xml. At present time, you might want to turn + different files: logback.xml and + logback-access.xml respectively. If you wanted to turn off logging for logback-classic by setting the level of the root - logger to OFF. Logback-access will be unaffected by this change. + logger to OFF, logback-access would be unaffected by this change.

    -

    To see the logs produced by logback access, just visit a few +

    To see the logs produced by logback-access, just visit a few pages and look at your console. The information contained in each line has been specified in the configuration file. The ConsoleAppender named STDOUT contains a - PatternLayout component. This very component that one - uses in logback classic to display either the message, logger name - or level of the request is used in logback access to display the - request method, requested page, status code and many others. + PatternLayout component. This layout component is + used in logback-classic to display either the message, logger name + or level of the request, but in logback-access it is used to display the + request method, requested page, status code and many other fields.

    Here is a sample output for this appender.

    @@ -377,7 +377,7 @@ page is accessed.

    -

    The configuration lines that are necessary are listed below. +

    The necessary configuration lines are listed below.

    <appender name="STDOUT_LOTTERY" @@ -421,31 +421,31 @@ now. At every try, logback will produce a log as shown below:

    -

    LOTTERY: 192.168.1.6 [POST /logback-demo/Lottery.do HTTP/1.1] Guess=321

    > +

    LOTTERY: 192.168.1.6 [POST /logback-demo/Lottery.do HTTP/1.1] Guess=321

    Sending emails

    -

    Logback access provides several components that are usually used +

    Logback-access provides several components that are usually used by the classic module. For example, a SMTPAppender can be used to send an email when a specific event occurs. Here, we will contact the lottery administrator each time a winner is detected. To achieve this, we will add a SMTPAppender to the existing configuration. Please uncomment the part of logback-access.xml named Lottery to Email. Do not - forget to uncomment the appender-ref element, at the end of - the configuration file, referencing the appender called - SMTP. In the appender element, notice the use of a - URLEvaluator. This evaluator allows us to only specify - one or more URLs that have to be watched. When one of them are + forget to uncomment the appender-ref element at the end of + the configuration file that references the SMTP appender. + In the appender element, notice the use of a + URLEvaluator. This evaluator allows us to specify + one or more URLs that are to be watched. When one of them is accessed, an email is sent.

    A reload of the configuration has to be done before we can test this new component. Once done, try to play the lottery with the - number 99. You should see a congratulation message but, + number 99. You should see a "congratulation" message but, most importantly, the specified recipients should have a new mail in their mailbox. The content of the email is a nicely formatted HTML - table with informations about the access that have occured before + table with information about the accesses that occurred before the triggering event.

    @@ -454,12 +454,12 @@

    Logback publishes several components via JMX. This allows you to see the status of certain objects, and change several configuration parameters. Publishing logback's components via JMX is possible - with Jetty and Tomcat. For more information about JMXConfigurator + with Jetty and Tomcat. For more information about the JMXConfigurator please refer to the relevant chapter in the manual.

    -

    Let us test the level setting possibility of the configurator. +

    Let us test setting levels using the configurator. The Prime Number page requests two types of logs. When the calculation checks if a number is a factor, a DEBUG log is displayed. When the calculation has found a factor, a INFO diff --git a/logback-site/src/site/pages/documentation.html b/logback-site/src/site/pages/documentation.html index 841ac67..bdfcf72 100644 --- a/logback-site/src/site/pages/documentation.html +++ b/logback-site/src/site/pages/documentation.html @@ -51,7 +51,7 @@

  • - Walk-through logback-demo webApp + Walk-through logback-demo web app
  • User guide of the logback plugin for Eclipse diff --git a/logback-site/src/site/pages/download.html b/logback-site/src/site/pages/download.html index 5ec28b3..634a00d 100644 --- a/logback-site/src/site/pages/download.html +++ b/logback-site/src/site/pages/download.html @@ -63,9 +63,9 @@

    A console plugin for Eclipse is also available. It allows you - to recieve logging events in a convenient Eclipse view, and - offers, among other features, integrates with logbacks filtering - framework. A more precise description can be found in the plugin's + to receive logging events in a convenient Eclipse view, and + offers integration with logback's filtering + framework, among other features. A more precise description can be found in the plugin's user guide. Unfortunately, the console plugin is somewhat outdated. It expects logback version 0.9.9. It will be upgraded in the coming weeks.

    @@ -112,9 +112,9 @@

    Forks

    -

    At present time there are 13 forks of logback on github. If you - are the author of one of those forks and would like feedback from - potential users, plase drop us a line at logback-dev mailing list +

    At present time there are 18 forks of logback on github. If you + are the author of one of these forks and would like feedback from + potential users, please drop us a line at the logback-dev mailing list with a brief description of your fork. We will gladly add a link to your fork to the list below (currently empty).

    diff --git a/logback-site/src/site/pages/faq.html b/logback-site/src/site/pages/faq.html index 78477d4..195f83e 100644 --- a/logback-site/src/site/pages/faq.html +++ b/logback-site/src/site/pages/faq.html @@ -92,7 +92,7 @@

    The logback project is dual licensed under the LGPL and - the EPL for two mains reasons. For one, the different + the EPL for two main reasons. For one, the different license emphasizes that the fact that logback is a related but different project than log4j.

    @@ -213,7 +213,7 @@ href="manual/configuration.html#variableSubstitution">variable substitution, it is possible to have a single configuration file to output logs to different destinations - depending on each JEE application. Here is a sample + for each JEE application. Here is a sample configuration file designed for this purpose.

    <configuration> @@ -242,7 +242,7 @@

    LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); - // inject the name of the current application as "applicaiton-name" + // inject the name of the current application as "application-name" // property of the LoggerContext context.putProperty("application-name", NAME_OF_CURRENT_APPLICATION); JoranConfigurator jc = new JoranConfigurator(); @@ -262,9 +262,9 @@

    -

    Logback does not allow disabling logging from the command +

    Logback does not allow logging to be disabled from the command line. However, if the configuration file allows it, you can - set the level of logers on the command line via a java + set the level of logers on the command line via a Java system property. Here is such a configuration file.

    <configuration> @@ -320,7 +320,7 @@

    -

    Since Jetty's uses an older version of SLF4J internally, +

    Since Jetty uses an older version of SLF4J internally, we recommend that the old version be replaced by slf4j-api-${slf4j.version}.jar. This file can be downloaded from the -

    For automaticly configuring logback-classic, you can +

    For automatically configuring logback-classic, you can place the file logback.xml under the $JETTY_HOME/resources directory. You can find sample configuration files in the diff --git a/logback-site/src/site/pages/index.html b/logback-site/src/site/pages/index.html index eef4e2b..1ec22f0 100644 --- a/logback-site/src/site/pages/index.html +++ b/logback-site/src/site/pages/index.html @@ -79,9 +79,9 @@

    • JWebUnit
    • +
    • Lift
    • OpenGDA
    • OpenMeetings
    • -
    • Lift
    • OpenTSDB
    • Red5
    • Scalate
    • diff --git a/logback-site/src/site/pages/license.html b/logback-site/src/site/pages/license.html index 2dbcc92..22e8995 100644 --- a/logback-site/src/site/pages/license.html +++ b/logback-site/src/site/pages/license.html @@ -24,8 +24,8 @@ -

      As of relase 0.9.18, logback source code and binaries are - dual-licensed under EPL v1.0 and the LGPL 2.1, or more +

      As of release 0.9.18, logback source code and binaries are + dual-licensed under the EPL v1.0 and the LGPL 2.1, or more formally:

      Logback: the reliable, generic, fast and flexible logging framework. @@ -45,7 +45,7 @@ as published by the Free Software Foundation.

      The EPL/LGPL dual-license serves several purposes. The LGPL license ensures continuity in terms of licensing of the logback project. Prior to version 0.9.18, logback was licensed - (exlusively) under the LGPL v2.1. Moreover, since the EPL is + (exclusively) under the LGPL v2.1. Moreover, since the EPL is deemed incompatible by the Free Software Foundation, the LGPL will allow various @@ -64,14 +64,14 @@ as published by the Free Software Foundation.

      If you wish to make a significant contribution to the logback - project, you are invited to file Contributor + project, you are invited to file a Contributor License Agreement. The purpose of this agreement is to formalize the terms of your contribution and to protect the project in case of litigation.

      Upon request, we may exempt open-source projects from LGPL and - EPL's reciprocity clauses so that the said pojects can develop + EPL's reciprocity clauses so that the said projects can develop logback extensions under the license of their choice. Exemptions are granted on a case by case basis.

      diff --git a/logback-site/src/site/pages/mailinglist.html b/logback-site/src/site/pages/mailinglist.html index e6ee0fc..d114616 100644 --- a/logback-site/src/site/pages/mailinglist.html +++ b/logback-site/src/site/pages/mailinglist.html @@ -33,9 +33,9 @@

      Respect the mailing list type

      -

      The "User" lists where you can send questions and comments +

      The "User" lists are where you can send questions and comments about configuration, setup, usage and other "user" types of - questions. The "Developer" lists where you can send questions and + questions. The "Developer" lists are where you can send questions and comments about the actual software source code and other issues related to development.

      @@ -46,7 +46,7 @@

      Please do your best to ensure that you are not sending HTML or - "Stylelized" email to the list. If you are using Outlook or + "Styled" email to the list. If you are using Outlook or Outlook Express or Eudora, chances are that you are sending HTML email by default. There is usually a setting that will allow you to send "Plain Text" email. @@ -151,7 +151,7 @@

      On IRC

      -

      We can also be reached by IRC at We can also be reached on IRC at irc.freenode.net#qos.ch.

       

      diff --git a/logback-site/src/site/pages/manual/appenders.html b/logback-site/src/site/pages/manual/appenders.html index 0f326e8..6e87946 100644 --- a/logback-site/src/site/pages/manual/appenders.html +++ b/logback-site/src/site/pages/manual/appenders.html @@ -68,7 +68,7 @@ public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachabl setters and getters. A notable exception is the doAppend() method taking an object instance of type E as its only parameter. The actual type of E - would vary depending on the logback module. Within the + will vary depending on the logback module. Within the logback-classic module E would be of type ILoggingEvent and within the logback-access module it would be of type extends LifeCycle, ContextAware, FilterAttachabl return; } - // ok, we now invoke derived class' implementation of append + // ok, we now invoke the derived class's implementation of append this.append(eventObject); } finally { @@ -156,7 +156,7 @@ public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachabl href="../xref/ch/qos/logback/core/UnsynchronizedAppenderBase.html">ch.qos.logback.core.UnsynchronizedAppenderBase which is very similar to the AppenderBase - class. For the sake of conciseness, we want to be discussing + class. For the sake of conciseness, we will be discussing UnsynchronizedAppenderBase in the remainder of this document.

      @@ -183,7 +183,7 @@ public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachabl an appender, Joran, logback's configuration framework, calls the start() method to signal the appender to activate its properties. Depending on its kind, an appender may fail to start if - certain properties are missing or because of interferences between + certain properties are missing or because of interference between various properties. For example, given that file creation depends on truncation mode, FileAppender cannot act on the value of its File option until the value of the Append option @@ -202,7 +202,7 @@ public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachabl

      The next if statement checks the result of the attached filters. Depending on the decision resulting from the - filter chain, events can be denied or alternatively accepted. In + filter chain, events can be denied or explicitly accepted. In the absence of a decision by the filter chain, events are accepted by default.

      @@ -242,7 +242,7 @@ public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachabl appends events to a java.io.OutputStream. This class provides basic services that other appenders build upon. Users do not usually instantiate OutputStreamAppender objects - directly. Since in general the java.io.OutputStream + directly, since in general the java.io.OutputStream type cannot be conveniently mapped to a string, as there is no way to specify the target OutputStream object in a configuration script. Simply put, you cannot configure a @@ -431,7 +431,7 @@ public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachabl href="#prudent">prudent boolean - In prudent mode, FileAppeder will safely + In prudent mode, FileAppender will safely write to the specified file, even in the presence of other FileAppender instances running in different JVMs, potentially running on different hosts. The default @@ -553,7 +553,7 @@ public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachabl available to subsequent configuration elements as a variable. The datePattern attribute - denoted the date pattern used to convert the current time (at which + denotes 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 SimpleDateFormat. @@ -569,7 +569,7 @@ public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachabl

      RollingFileAppender - extends FileAppender with the capability to roll log + extends FileAppender with the capability to rollover log files. For example, RollingFileAppender can log to a file named log.txt file and, once a certain condition is met, change its logging target to another file. @@ -593,7 +593,7 @@ public interface Appender<E> extends LifeCycle, ContextAware, FilterAttachabl TriggeringPolicy set up. However, if its RollingPolicy also implements the TriggeringPolicy interface, then only the former needs - to be set up. + to be specified explicitly.

      Here are the available properties for RollingFileAppender:

      @@ -701,7 +701,7 @@ public interface RollingPolicy extends LifeCycle {

      The rollover method accomplishes the work involved in archiving the current log file. The - getActiveFileName() method is called to compute a the + getActiveFileName() method is called to compute the file name of the current log file (where live logs are written to). As indicated by getCompressionMode method a RollingPolicy is also responsible for determining the compression @@ -760,11 +760,11 @@ public interface RollingPolicy extends LifeCycle {

      This option represents the pattern that will be followed by the FixedWindowRollingPolicy when renaming - the log files. If must contain the string %i, which + the log files. It must contain the string %i, which will indicate the position where the value of the current window index will be inserted.

      -

      For example, using MyLogFile%i.log, associated +

      For example, using MyLogFile%i.log associated with minimum and maximum values of 1 and 3 will produce archive files named MyLogFile1.log, MyLogFile2.log and MyLogFile3.log. @@ -772,7 +772,7 @@ public interface RollingPolicy extends LifeCycle {

      Note that file compression is also specified via this property. For example, fileNamePattern set to - MyLogFile%i.log.zip means that archived file must be + MyLogFile%i.log.zip means that archived files must be compressed using the zip format; gz format is also supported.

      @@ -905,7 +905,7 @@ public interface RollingPolicy extends LifeCycle { interfaces.

      -

      TimeBasedRollingPolicy's configuration admits two +

      TimeBasedRollingPolicy's configuration has two properties, the mandatory fileNamePattern property and the optional maxHistory property. @@ -922,7 +922,7 @@ public interface RollingPolicy extends LifeCycle { String The mandatory fileNamePattern - property defines the name of the rolled (archived) log + property defines the name of the rolled-over (archived) log files. Its value should consist of the name of the file, plus a suitably placed %d conversion specifier. The %d conversion specifier may contain a date-and-time @@ -1317,9 +1317,9 @@ public interface TriggeringPolicy<E> extends LifeCycle { }

  • The isTriggeringEvent() method takes as parameters - the active file, and the logging event currently being + the active file and the logging event currently being processed. The concrete implementation determines whether the - rollover should occur or not, based on the said parameters. + rollover should occur or not, based on these parameters.

    The most widely-used triggering policy, namely @@ -1333,7 +1333,7 @@ public interface TriggeringPolicy<E> extends LifeCycle {

    - SizeBasedTriggeringPolicy looks at size of the + SizeBasedTriggeringPolicy looks at the size of the currently active file. If it grows larger than the specified size, it will signal the owning RollingFileAppender to trigger the rollover of the existing active file. @@ -1354,7 +1354,7 @@ public interface TriggeringPolicy<E> extends LifeCycle {

    Here is a sample configuration with a RollingFileAppender in conjunction with - SizeBasedTriggeringPolicy triggering roll over when + SizeBasedTriggeringPolicy triggering rollover when the log file reaches 5MB in size.

    @@ -1404,7 +1404,7 @@ public interface TriggeringPolicy<E> extends LifeCycle { SocketAppender -

    The appenders covered this far were only able to log on local +

    The appenders covered thus far are only able to log to local resources. In contrast, the SocketAppender is designed to log to a remote @@ -1419,7 +1419,7 @@ public interface TriggeringPolicy<E> extends LifeCycle { locally. Multiple SocketAppender instances running on different machines can direct their logging output to a central log server whose format is fixed. SocketAppender - does not admit an associated layout because it sends serialized + does not take an associated layout because it sends serialized events to a remote server. SocketAppender operates above the Transmission Control Protocol (TCP) layer which provides a reliable, sequenced, flow-controlled end-to-end octet @@ -1751,7 +1751,7 @@ public interface TriggeringPolicy<E> extends LifeCycle {

    By specifying a discriminator other than the default - one, it would be possible to receive email messages + one, it is possible to receive email messages containing a events pertaining to a particular user, user session or client IP address.

    @@ -1766,7 +1766,7 @@ public interface TriggeringPolicy<E> extends LifeCycle {

    This option is declared by creating a new <EventEvaluator/> element. The name of the class that the user wishes to use as the - SMTPAppender's Evaluator can needs + SMTPAppender's Evaluator needs to be specified via the class attribute.

    @@ -1879,7 +1879,7 @@ public interface TriggeringPolicy<E> extends LifeCycle { download the JavaMail API and the Java-Beans + href="http://java.sun.com/beans/glasgow/jaf.html">JavaBeans Activation Framework from their respective websites. Make sure to place these two jar files in the classpath before trying the following examples. @@ -1887,7 +1887,7 @@ public interface TriggeringPolicy<E> extends LifeCycle {

    A sample application, chapters.appenders.mail.EMail - generates a number of log messages messages followed by a single + generates a number of log messages followed by a single error message. It takes two parameters. The first parameter is an integer corresponding to the number of logging events to generate. The second parameter is the logback configuration @@ -1939,7 +1939,7 @@ public interface TriggeringPolicy<E> extends LifeCycle {

    In the next example configuration file mail2.xml, the values for the smtpHost, To and From + class="option">to and from properties are determined by variable substitution. Here is the relevant part of mail2.xml.

    @@ -1984,8 +1984,8 @@ public interface TriggeringPolicy<E> extends LifeCycle { However, they sometimes automatically downgrade HTML to plaintext. For example, to view HTML email in Thunderbird, the "View→Message Body As→Original HTML" option - must be set. Yahoo!Mail's support for HTML email, in particular - its CSS support is very good. GMail on the other hand, while it + must be set. Yahoo! Mail's support for HTML email, in particular + its CSS support is very good. Gmail on the other hand, while it honors the basic HTML table structure, ignores the internal CSS formatting. Gmail supports inline CSS formatting but since inline CSS would make the resulting output too voluminous, @@ -2024,7 +2024,7 @@ public interface TriggeringPolicy<E> extends LifeCycle {

    If the Evaluator property is not set, the SMTPAppender defaults to an OnErrorEveluator + href="../xref/ch/qos/logback/classic/boolex/OnErrorEvaluator.html">OnErrorEvaluator instance which triggers email transmission when it encounters an event of level ERROR. While triggering an outgoing email in response to an error is relatively reasonable, it is possible to @@ -2040,7 +2040,7 @@ public interface TriggeringPolicy<E> extends LifeCycle { SMTPAppender contains one and only one evaluator object. This object may manage its own internal state. For illustrative purposes, the CounterBasedEvaluator - class listed next, implements an event evaluator whereby every + class listed next implements an event evaluator whereby every 1024th event triggers an email message.

    @@ -2120,7 +2120,7 @@ public class CounterBasedEvaluator extends ContextAwareBase implements EventEval based triggering -

    Although reasonable the default triggering policy whereby every +

    Although reasonable, the default triggering policy whereby every event of level ERROR triggers an outgoing email may result in too many emails, cluttering the targeted user's mailbox. Logback ships with another triggering policy, called notifyAdmin,

    Note that since the event may lack a marker, the value of e.marker can be null. Hence the use of Groovy's safe - derefencing opeator, that is the .? operator. + dereferencing operator, that is the .? operator.

    @@ -2325,7 +2325,7 @@ logger.error(notifyAdmin, session or client IP address, depending on the specified discriminator.

    -

    The next example illustrates the use ofThe next example illustrates the use of MDCBasedDiscriminator in conjunction with the MDC key named "req.remoteHost", assumed to contain the IP address of the remote host accessing a fictitious @@ -2362,7 +2362,7 @@ logger.error(notifyAdmin, </root> </configuration> -

    Thus, each outgoing emails generated by +

    Thus, each outgoing email generated by SMTPAppender will belong to a unique remote host, greatly facilitating problem diagnosis.

    @@ -2397,7 +2397,7 @@ logger.error(notifyAdmin,

    If your JDBC driver supports the getGeneratedKeys method introduced in JDBC 3.0 specification, assuming you have created the appropriate database tables as mentioned above, then - no more steps are required, excluding the usual logback + no more steps are required, except for the usual logback configuration.

    @@ -2772,7 +2772,7 @@ logger.error(notifyAdmin, </configuration>

    - Not that in this configuration sample, we make heavy use of substitution variables. + Note that in this configuration sample, we make heavy use of substitution variables. They are sometimes handy when connection details have to be centralized in a single configuration file and shared by logback and other frameworks.

    @@ -2800,7 +2800,7 @@ logger.error(notifyAdmin, source will be bound to a JNDI context.

    -

    This is a very powerful possibility of Joran. If you'd like to +

    This is a very powerful capability of Joran. If you'd like to read more about Joran, please see the chapter to Joran.

    @@ -2969,7 +2969,7 @@ logger.error(notifyAdmin, The port number on the syslog server to connect to. Normally, one would not want - to change the default value, that is 514. + to change the default value of 514. @@ -2987,7 +2987,7 @@ logger.error(notifyAdmin, the source of a message.

    - The facility option must be set one + The facility option must be set to one of the strings KERN, USER, MAIL, DAEMON, AUTH, SYSLOG, LPR, NEWS, UUCP, CRON, AUTHPRIV, FTP, NTP, AUDIT, ALERT, CLOCK, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. Case is not important. @@ -3024,7 +3024,7 @@ logger.error(notifyAdmin,

    Since the format of a syslog request follows rather strict rules, there is no layout - to be used with SyslogAppender. However, the using the + to be used with SyslogAppender. However, using the suffixPattern option lets the user display whatever information she wishes.

    @@ -3336,7 +3336,7 @@ public class CountingConsoleAppender extends AppenderBase<ILoggingEvent> {

    Two tables are used by DBAppender: - access_event and access_event_header. They all + access_event and access_event_header. They both must exist before DBAppender can be used. Logback ships with SQL scripts that will create the tables. They can be found in the @@ -3414,7 +3414,7 @@ public class CountingConsoleAppender extends AppenderBase<ILoggingEvent> {

    The access_event_header table contains the header of each - requests. The information is organised as shown below: + request. The information is organised as shown below:

    @@ -3441,7 +3441,7 @@ public class CountingConsoleAppender extends AppenderBase<ILoggingEvent> {

    All properties of classic's DBAppender are available - in access' DBAppender. The latter offers one more option, + in access's DBAppender. The latter offers one more option, described below.

    @@ -3495,7 +3495,7 @@ public class CountingConsoleAppender extends AppenderBase<ILoggingEvent> { logback-access the default discriminator, namely AccessEventDiscriminator, is not MDC based. As its name suggests, AccessEventDiscriminator, - uses a designated field in AccessEvent as basis for selecting a + uses a designated field in AccessEvent as the basis for selecting a nested appender. If the value of the designated field is null, then the value specified in the defaultValue property is used. diff --git a/logback-site/src/site/pages/manual/architecture.html b/logback-site/src/site/pages/manual/architecture.html index b4a5841..939636b 100644 --- a/logback-site/src/site/pages/manual/architecture.html +++ b/logback-site/src/site/pages/manual/architecture.html @@ -56,9 +56,9 @@ switch back and forth between logback and other logging systems such as log4j or java.util.logging (JUL) introduced in JDK 1.4. The third module called access integrates with - Servlet containers to provide HTTP-access log functionality. The - access module will be covered in a separate document. + Servlet containers to provide HTTP-access log functionality. A + separate document covers + access module documentation.

    In the reminder of this document, we will write "logback" to @@ -152,8 +152,8 @@ public interface Logger { href="#effectiveLevel">Effective Level aka Level Inheritance -

    Loggers may be assigned levels. The set of possible levels, - that is TRACE, DEBUG, INFO, WARN and ERROR are defined in the +

    Loggers may be assigned levels. The set of possible levels + (TRACE, DEBUG, INFO, WARN and ERROR) are defined in the ch.qos.logback.classic.Level class. Note that in logback, the Level class is final and cannot be sub-classed, as a much more flexible approach exists in the form @@ -477,7 +477,7 @@ Logger y = LoggerFactory.getLogger("wombat");

    Thus, it is possible to configure a logger and then to retrieve the same instance somewhere else in the code without passing around references. In fundamental contradiction to biological - parenthood, where parents always preceed their children, logback + parenthood, where parents always precede their children, logback loggers can be created and configured in any order. In particular, a "parent" logger will find and link to its descendants even if it is instantiated after them. @@ -573,7 +573,7 @@ Logger y = LoggerFactory.getLogger("wombat"); A1 Since the root logger stands at the top of the logger - hiearchy, the additivity flag does not apply to it. + hierarchy, the additivity flag does not apply to it. @@ -665,7 +665,7 @@ Logger y = LoggerFactory.getLogger("wombat");

    incurs the cost of constructing the message parameter, that is converting both integer i and entry[i] - to a String, and concatenating intermediate strings. This, + to a String, and concatenating intermediate strings. This is regardless of whether the message will be logged or not.

    @@ -698,11 +698,11 @@ Logger y = LoggerFactory.getLogger("wombat");
    Object entry = new SomeObject(); 
     logger.debug("The entry is {}.", entry);
    -

    After evaluting whether to log or not, and only if the decision +

    Only after evaluating whether to log or not, and only if the decision is positive, will the logger implementation format the message and replace the '{}' pair with the string value of entry. In other words, this form does not incur the cost of parameter - construction in case the log statement is disabled. + construction when the log statement is disabled.

    @@ -716,7 +716,7 @@ logger.debug("The entry is {}.", entry); logger.debug("The new entry is {}.", entry); -

    A two argument variant is also availalble. For example, you can +

    A two argument variant is also available. For example, you can write:

    @@ -807,7 +807,7 @@ logger.debug("Value {} was inserted between {} and {}.", paramArray); String. Note that some appenders, such as the SocketAppender, do not transform the logging event into a string but serialize it instead. Consequently, they do not - require nor have a layout. + have nor require a layout.

    6. Sending out the LoggingEvent

    @@ -876,8 +876,8 @@ logger.debug("Value {} was inserted between {} and {}.", paramArray); margin. The message will be formatted only if the request is processed to the appenders. If it is processed, the component that formats the message offers high performance and does not - impact negatively the overall process. It respectively takes 2 - and 4 microseconds to format a message with 1 and 3 parameters. + negatively impact the overall process. It takes 2 + and 4 microseconds respectively to format a message with 1 and 3 parameters.

    Please notice that, despite the performance points just diff --git a/logback-site/src/site/pages/manual/configuration.html b/logback-site/src/site/pages/manual/configuration.html index ce31db1..372b410 100644 --- a/logback-site/src/site/pages/manual/configuration.html +++ b/logback-site/src/site/pages/manual/configuration.html @@ -44,7 +44,7 @@

    Joran stands for a cold north-west wind which, every now and then, blows forcefully on Lake Geneva. Located right in the middle - of Europe, the Geneva lake happens to be the continent's largest + of Europe, Lake Geneva happens to be the continent's largest sweet water reserve.

    @@ -105,10 +105,10 @@ classpath..

    -
  • In case neither file is found, logback configures itself +

  • If neither file is found, logback configures itself automatically using the BasicConfigurator - which will cause logging output to be directed on the console. + which will cause logging output to be directed to the console.

  • @@ -120,8 +120,8 @@

    -

    If you are using Maven and assuming the - logback-test.xml file is placed under +

    If you are using Maven and if you place the + logback-test.xml under the src/test/resources folder, Maven will ensure that it won't be included in the artifact produced. Thus, you can use a different configuration file, namely logback-test.xml @@ -225,8 +225,8 @@ public class Foo { org.slf4j.LoggerFactory and org.slf4j.Logger 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 logging - framework under its abstraction layer, it is rather easy to migrate + on logback. Since SLF4J permits the use of any logging + framework under its abstraction layer, it is easy to migrate large bodies of code from one logging framework to another.

    @@ -282,7 +282,7 @@ public class Foo { wish to inspect logback's internal status, then you can instruct logback to print status data by invoking the print() of the StatusPrinter class. The MyApp2 - application shown below is identical to MyApp1 except the + application shown below is identical to MyApp1 except for the addition of two lines of code for printing internal status data.

    @@ -357,8 +357,8 @@ public class Foo { </configuration>

    Setting the debug attribute within the - <configuration> element will output status information, under - the assumption that + <configuration> element will output status information, + assuming that:

    1. the configuration file is found
    2. @@ -366,21 +366,20 @@ public class Foo {

    If any of these two conditions is not fulfilled, Joran cannot - interpret debug attribute since the configuration file + interpret the debug attribute since the configuration file cannot be read. If the configuration file is found but is - ill-formed, then logback will detect the error condition and + malformed, then logback will detect the error condition and automatically print its internal status on the console. However, if - the configuration file cannot be found, since this is not - necessarily an error condition, logback will not automatically - print its status data. Programmatically invoking - StatusPrinter.print(), as as in MyApp2 - application above, ensures that status information is always + the configuration file cannot be found, logback will not automatically + print its status data, since this is not necessarily an error condition. Programmatically invoking + StatusPrinter.print() as in the MyApp2 + application above ensures that status information is always printed.

    -

    It is highly recommended to register a status listener, +

    It is strongly recommended to register a status listener, e.g. OnConsoleStatusListener, so that problems - occuring during the lifetime of your applicaiton, well after + occuring during the lifetime of your application, well after logback is initialized, can be reported. See the section on status listeners further below.

    @@ -390,7 +389,7 @@ public class Foo {

    If you wish, you can specify the location of the default configuration file with a system property named - logback.configurationFile. The value of the this + logback.configurationFile. The value of this property can be a URL, a resource on the class path or a path to a file external to the application.

    @@ -403,14 +402,14 @@ public class Foo {

    Logback-classic can scan for changes in its configuration file - and automatically reconfigure itself when the said configuration + and automatically reconfigure itself when the configuration file changes.

    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 + the configuration file changes. In order to instruct logback-classic to scan for changes in its configuration file and to automatically re-configure itself set the scan attribute of the @@ -455,7 +454,7 @@ public class Foo { href="../xref/ch/qos/logback/classic/turbo/ReconfigureOnChangeFilter.html">ReconfigureOnChangeFilter will be installed. TurboFilters are described in a later chapter. As a - consequence, scanning is done "in-thread", that is anytime a + consequence, scanning is done "in-thread", that is any time a printing method of logger is invoked. For example, for a logger named myLogger, when you write "myLogger.debug("hello");", and if the scan attribute is set to @@ -482,8 +481,8 @@ public class Foo {

    Logback relies on a configuration library called Joran which is part of logback-core. Logback's default configuration mechanism invokes JoranConfigurator on the default configuration - file it finds on the class path. For whatever reason if you wish to - override logback's default configuration mechanism, you can do so + file it finds on the class path. If you wish to + override logback's default configuration mechanism for whatever reason, you can do so by invoking JoranConfigurator directly. The next application, MyApp3, invokes JoranConfigurator on a configuration file passed as a parameter.

    @@ -549,7 +548,7 @@ public class MyApp3 { object, accessible via the LoggerContext.

    -

    Given a StatusManager you an access all the status +

    Given a StatusManager you can access all the status data associated with a logback context. To keep memory usage at reasonable levels, the default StatusManager implementation stores the status messages in two separate parts: @@ -581,7 +580,7 @@ public class MyApp3 { <url-pattern>/lbClassicStatus</url-pattern> </servlet-mapping> -

    The ViewStatusMessages servlet will viewable under +

    The ViewStatusMessages servlet will be viewable at the URL http://host/yourWebapp/lbClassicStatus

    @@ -618,7 +617,7 @@ public class MyApp3 { OnConsoleStatusListener onConsoleListener = new OnConsoleStatusListener(); statusManager.add(onConsoleListener); -

    Note that the registered status listener will receive status +

    Note that the registered status listener will only receive status events subsequent to its registration. It will not receive prior messages. Thus, it is usually a good idea to place status listener registration directives at top of the configuration file before @@ -646,7 +645,7 @@ public class MyApp3 {

    - Configuration file Syntax + Configuration file syntax

    As you have seen thus far in the manual with plenty of examples @@ -664,7 +663,7 @@ public class MyApp3 { configuration files.

    -

    As shall be demonstrated over and over, the syntax of logback +

    As will be demonstrated over and over, the syntax of logback configuration files is extremely flexible. As such, it is not possible to specify the allowed syntax with a DTD file or an XML schema. Nevertheless, the very basic structure of the configuration @@ -692,7 +691,7 @@ public class MyApp3 { sensitivity of tag names -

    As of logback version 0.9.17, tag names pertaining to explicit +

    Since logback version 0.9.17, tag names pertaining to explicit rules are case insensitive. For example, both <logger>, <Logger> and <LOGGER> are valid configuration elements and will @@ -703,9 +702,9 @@ public class MyApp3 { rules, tag names are case sensitive except for the first letter. Thus, <xyz> and <Xyz> are equivalent but not <xYz>. Implicit rules usually - follow the camel - case convention, common in the Java world. Since it is not - easy tell when a tag is associated with an explicit action and + follow the camelCase + convention, common in the Java world. Since it is not + easy to 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 case-sensitive or insensitive with respect to the first letter. If you are unsure which case to use @@ -720,7 +719,7 @@ public class MyApp3 {

    At this point you should have at least some understanding of level inheritance and the basic selection - rule. Otherwise, and unless you are an egyptologist, logback + rule. Otherwise, and unless you are an Egyptologist, logback configuration will be no more meaningful to you than are hieroglyphics.

    @@ -731,18 +730,18 @@ public class MyApp3 { level attribute, and an optional additivity attribute, admitting the values true or false. The value of the level attribute admitting the one of the + class="attr">level attribute admitting one of the case-insensitive string values TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF. The special case-insensitive value INHERITED, or its synonym NULL, will force the level of the logger to be inherited from higher up in the hierarchy. This comes in - handy in case you set the level of a logger and later decide that + handy if you set the level of a logger and later decide that it should inherit its level.

    The <logger> element may contain zero or more <appender-ref> elements; each appender thus - referenced is added to the named logger. Note that contrary to + referenced is added to the named logger. Note that unlike log4j, logback-classic does not close or remove any previously referenced appenders before adding the new appender reference. @@ -754,23 +753,22 @@ public class MyApp3 { logger, or the <root> element

    The <root> element configures the root - logger. It admits a single attribute, namely the level attribute. It does not admit any other + logger. It supports a single attribute, namely the level attribute. It does not allow any other attributes because the additivity flag does not apply to the root logger. Moreover, since the root logger is already named as - "ROOT", it does not admit a name attribute either. The value of the + "ROOT", it does not allow a name attribute either. The value of the level attribute can be one of the case-insensitive strings TRACE, DEBUG, INFO, WARN, ERROR, ALL or OFF. Note that the level of the root logger cannot be set to INHERITED or NULL.

    -

    The <root> element admits zero or more - <appender-ref> elements. Similar to the +

    Similarly to the <logger> element, the <root> element may contain zero or more <appender-ref> elements; each appender thus referenced is added to the root - logger. Note that contrary to log4j, logback-classic does + logger. Note that unlike log4j, logback-classic does not close or remove any previously referenced appenders before adding the new appender reference to the root logger.

    @@ -818,7 +816,7 @@ public class MyApp3 {

    Note that the message of level DEBUG generated by the "chapters.configuration.Foo" - logger has been supressed. See also the Foo class.

    + logger has been suppressed. See also the Foo class.

    You can configure the levels of as many loggers as you wish. In the next configuration file, we set the level of the @@ -993,9 +991,9 @@ public class MyApp3 { instantiate. The <appender> element may contain zero or one <layout> elements, zero or more <encoder> elements and zero or more - <filter> elements. Appart from these three common + <filter> elements. Apart from these three common elements, <appender> elements may contain any number - of elements corresponding to javabean properties of the appender + of elements corresponding to JavaBean properties of the appender class. Seamlessly supporting any property of a given logback component is one of the major strengths of Joran as discussed in a later chapter. The @@ -1010,7 +1008,7 @@ public class MyApp3 {

    The <layout> element takes a mandatory class attribute specifying the fully qualified name of the layout class to - instantiate. As with the the <appender> element, + instantiate. As with the <appender> element, <layout> may contain other elements corresponding to properties of the layout instance. Since it's such a common case, if the layout class is PatternLayout, then the class @@ -1132,7 +1130,7 @@ public class MyApp3 {

    Appender additivity is not intended as a trap for new users. It - is a quite convenient logback feature. For instance, you can + is quite a convenient logback feature. For instance, you can configure logging such that log messages appear on the console (for all loggers in the system) while messages only from some specific set of loggers flow into a specific appender. @@ -1180,7 +1178,7 @@ public class MyApp3 {

    In case the default cumulative behavior turns out to be unsuitable for your needs, you can override it by setting the additivity flag to false. Thus, a branch in your logger tree may - direct output to a set of appenders different than those of the rest + direct output to a set of appenders different from those of the rest of the tree.

    @@ -1275,7 +1273,7 @@ public class MyApp3 { value of the substituted variable can be defined in the configuration file itself, in an external properties file or as a system property. The corresponding value replaces ${aKey} - sequence. For example, if java.home.dir system property is + sequence. For example, if the java.home.dir system property is set to /home/xyz, then every occurrence of the sequence ${java.home.dir} will be interpreted as /home/xyz. As they often come in handy, the ${HOSTNAME} and ${CONTEXT_NAME} @@ -1291,7 +1289,7 @@ public class MyApp3 { to remote hosts via serialization.

    The next example shows a variable, a.k.a. a substitution - property, declared the beginning of the configuration file. It is + property, declared at the beginning of the configuration file. It is then used further down the file to specify the location of the output file.

    @@ -1405,7 +1403,7 @@ public class MyApp3 {

    Nested variable substitution

    -

    Nested variabled subsitution is also supported. By nested, we +

    Nested variable subsitution is also supported. By nested, we mean that the value definition of a variable contains references to other variables. Suppose you wish to use variables to specify not only the destination directory but also the file name, and combine @@ -1421,7 +1419,7 @@ fileName=myApp.log destination=${USER_HOME}/${fileName}

    Note that in the properties file above, "destination" is - composed out of two other variables, namely "USER_HOME" and + composed from two other variables, namely "USER_HOME" and "fileName".

    @@ -1450,7 +1448,7 @@ fileName=myApp.log variables

    Under certain circumstances, it may be desirable for a variable - to have a default value in case it is not declared or its value is + to have a default value if it is not declared or its value is null. As in the Bash shell, default values can be specified using the ":-" @@ -1509,7 +1507,7 @@ fileName=myApp.log <root level="${rootLevel}"/> </configuration> -

    At present time, logback does not ship with any classes +

    At the present time, logback does not ship with any classes implementing PropertyDefiner. We merely provide an extension point so that you may define properties dynamically.

    @@ -1550,7 +1548,7 @@ fileName=myApp.log </else> </if> -

    The condition is a java expression where only context properties +

    The condition is a Java expression in which only context properties or system properties are accessible. For a key passed as argument, the property() or its shorter equivalent p() methods return the String value of the property. @@ -1558,7 +1556,7 @@ fileName=myApp.log write property("k") or equivalently p("k"). If the property with key "k" is undefined, the property method will return the empty string and not null. This - avoids the need to to check for null values. If you need to check + avoids the need to check for null values. If you need to check whether a property is null, the isNull() method is provided. For example, you can write isNull("k").

    @@ -1602,7 +1600,7 @@ fileName=myApp.log statements are also supported. However, XML syntax is awfully cumbersome and is ill suited as the foundation of a general purpose programming language. Consequently, too many conditionals will - quickly render your configuration files ungrokable to subsequent + quickly render your configuration files incomprehensible to subsequent readers, including yourself.

    @@ -1684,7 +1682,7 @@ fileName=myApp.log

    Again, please note the mandatory - <included> element if you have not already done so.

    + <included> element.

    The contents to include can be referenced as a file, as a resource, or as a URL.

    @@ -1725,7 +1723,7 @@ fileName=myApp.log

    JMXConfigurator is one implementation of the - LoggerContextListener interface. It is desribed in a LoggerContextListener interface. It is described in a subsequent chapter.

    @@ -1756,7 +1754,7 @@ fileName=myApp.log

    Setting the resetJUL propery of LevelChangePropagator will reset all previous level configurations - of all j.u.l. loggers. Previously installed handlers however will be + of all j.u.l. loggers. However, previously installed handlers will be left untouched.

    <configuration debug="false">
    diff --git a/logback-site/src/site/pages/manual/encoders.html b/logback-site/src/site/pages/manual/encoders.html
    index 70dc3de..ecd1000 100644
    --- a/logback-site/src/site/pages/manual/encoders.html
    +++ b/logback-site/src/site/pages/manual/encoders.html
    @@ -47,10 +47,10 @@
         layout to transform an event into a string and write it out using
         a java.io.Writer. In previous versions of logback,
         users would nest a PatternLayout within
    -    FileAppender. As for logback 0.9.19,
    +    FileAppender. Since logback 0.9.19,
         FileAppender and sub-classes expect an encoder and no
    -    longer admit a layout.
    +    longer take a layout.
         

    Why the breaking change? @@ -61,14 +61,14 @@ layout has no control over when events get written out, layouts cannot aggregate events into batches. Contrast this with encoders which not only have total control over the format of the bytes - written out, also control when (and if) those bytes get written + written out, but also control when (and if) those bytes get written out.

    At the present time (2010-03-08), PatternLayoutEncoder is the only really useful encoder. It merely wraps a PatternLayout which does - most of the work. Thus, may seem that encoders do not bring much + most of the work. Thus, it may seem that encoders do not bring much to the table except needless complexity. However, we hope that with the advent of new and powerful encoders this impression will change.

    @@ -99,7 +99,7 @@ public interface Encoder<E> extends ContextAware, LifeCycle { /** * Encode and write an event to the appropriate {@link OutputStream}. - * Implementations are free to differ writing out of the encoded event and + * Implementations are free to defer writing out of the encoded event and * instead write in batches. */ void doEncode(E event) throws IOException; @@ -113,8 +113,8 @@ public interface Encoder<E> extends ContextAware, LifeCycle { void close() throws IOException; }
    -

    As you can see, the Encoder interface consists of few method - but surprisingly enough many useful things can be accomplished with +

    As you can see, the Encoder interface consists of few methods, + but surprisingly many useful things can be accomplished with those methods.

    diff --git a/logback-site/src/site/pages/manual/filters.html b/logback-site/src/site/pages/manual/filters.html index 5ae6f91..46d555c 100644 --- a/logback-site/src/site/pages/manual/filters.html +++ b/logback-site/src/site/pages/manual/filters.html @@ -63,9 +63,9 @@

    Regular logback-classic filters extend the Filter - abstract class which essentially consists of a single method, + abstract class which essentially consists of a single decide() method taking an ILoggingEvent - instance as parameter. + instance as its parameter.

    @@ -151,16 +151,16 @@ public class SampleFilter extends Filter>ILoggingEvent> { </configuration>

    With the help of Joran, logback's configuration framework, - specifiying properties or sub-componenets to filters is also + specifying properties or sub-componenets to filters is also easy. After adding the corresponding setter method in the filter class, specify the value of the property in an xml element named - after the property, nesting it within <filter> + after the property, nesting it within a <filter> element.

    -

    Often times, the desired filter logic consists of two +

    Often, the desired filter logic consists of two orthogonal parts, a match/mismatch test and a response depending - on the match/mismatch. For example, for a given test, say message + on the match/mismatch. For example, for a given test, e.g. message equals "foobar", one filter might respond ACCEPT on match and NEUTRAL on mismatch, and another filter might respond NEUTRAL on match and DENY on mismatch. @@ -169,8 +169,8 @@ public class SampleFilter extends Filter>ILoggingEvent> {

    Taking notice of this orthogonality, logback ships with the AbstractMatcherFilter class which provides a - useful skeleton for specifiying the appropriate response on match - and on mistmatch, with the help of two properties, named + useful skeleton for specifying the appropriate response on match + and on mismatch, with the help of two properties, named OnMatch and OnMismatch. Most of the regular filters included in logback are derived from AbstractMatcherFilter. @@ -248,14 +248,14 @@ public class SampleFilter extends Filter>ILoggingEvent> {

    EvaluatorFilter is a generic filter encapsulating an - EventEvaluator. As the name intimates, an + EventEvaluator. As the name suggests, an EventEvaluator evaluates whether a given criteria - is met for a given event. On match and respectively on mismatch, + is met for a given event. On match and on mismatch, the hosting EvaluatorFilter will return the value - specified by onMatch and respectively - to onMismatch properties. + specified by the onMatch + or onMismatch properties respectively.

    @@ -274,10 +274,10 @@ public class SampleFilter extends Filter>ILoggingEvent> { href="../xref/ch/qos/logback/classic/boolex/GEventEvaluator.html">GEventEvaluator is a concrete EventEvaluator - implementation taking artibtrary Groovy language boolean - expressions as the evaluation criteria. We refer such groovy - language boolean expressions as "groovy evalation - expressions". Groovy evaluation expressions enable hereto + implementation taking arbitrary Groovy language boolean + expressions as the evaluation criteria. We refer such Groovy + language boolean expressions as "groovy evaluation + expressions". Groovy evaluation expressions enable hitherto unprecedented flexibility in event filtering. GEventEvaluator requires the Groovy runtime. Please see the {

    Evaluation expressions are compiled on-the-fly during the interpretation of the configuration file. As a user, you do not need to worry about the actual plumbing. However, it is your - reponsibility to ensure that the groovy-language expression is + responsibility to ensure that the groovy-language expression is valid.

    -

    The evaluation expression acts on the current logging event, - logback automatically inserts the current logging event of type The evaluation expression acts on the current logging event. + Logback automatically inserts the current logging event of type ILoggingEvent as a variable referred to as 'event' as well as its shorthand referred to as 'e'. The variables TRACE, DEBUG, INFO, WARN and ERROR are also exported into the scope of the expression. Thus, "event.level == DEBUG" and "e.level == DEBUG" - are equvalent and valid groovy expressions which will return + are equivalent and valid groovy expressions which will return true only if the current logging event's level is identical to DEBUG. For other comparison operators on levels, the level field should be converted to integer with the @@ -343,10 +343,10 @@ public class SampleFilter extends Filter>ILoggingEvent> { checking whether the MDC associated with the event contains a value for "req.userAgent" matching the /Googlebot|msnbot|Yahoo/ regular expression. Note - that since the mdc map can be null, we are also using Groovy's safe - derefencing opeator, that is the .? operator. The equivalent - logic would have be much longer to express in Java. + dereferencing operator, that is the .? operator. The equivalent + logic would have been much longer if expressed in Java.

    If you are wondering how the identifier for the user agent was @@ -366,8 +366,8 @@ public class SampleFilter extends Filter>ILoggingEvent> {

    Logback-classic ships with another concrete EventEvaluator implementation called JaninoEventEvaluator - taking arbitrary java language boolean expressions as the - evaluation criteria. We refer to such java language boolean + taking arbitrary Java language boolean expressions as the + evaluation criteria. We refer to such Java language boolean expressions as "evaluation expressions". Evaluation expressions enable great flexibility in event filtering. JaninoEventEvaluator requires the {

    Evaluation expressions are compiled on-the-fly during the interpretation of the configuration file. As a user, you do not need to worry about the actual plumbing. However, it is your - reponsibility to ensure that the java-language expression returns + reponsibility to ensure that the Java language expression returns a boolean, i.e. that it evaluates to true or false.

    @@ -483,7 +483,7 @@ public class SampleFilter extends Filter>ILoggingEvent> { 'mdc' variable can be null and this possibility should be checked for in evaluator expressions. -

    The java.util.Map type is non-parametirezied +

    The java.util.Map type is non-parameterized because Janino does not support generics. It follows that the type returned by mdc.get() is Object and not String. To invoke String @@ -556,8 +556,8 @@ public class SampleFilter extends Filter>ILoggingEvent> { evaluator of type JaninoEventEvaluator is then injected into the EvaluatorFilter. In the absence of class attribute in the - <evaluator> element specified by the user, joran - will infer a default type, i.e. JaninoEventEvaluator, + <evaluator> element specified by the user, Joran + will infer a default type of JaninoEventEvaluator for the evaluator. This is one of the few occurrences where Joran implicitly infers the type of a component. @@ -675,7 +675,7 @@ java chapters.filters.FilterEvents src/main/java/chapters/filters/basicConfigura 266 [main] ERROR chapters.filters.FilterEvents - billing statement 6 266 [main] INFO chapters.filters.FilterEvents - logging statement 8

    -

    In case you need to define additional matchers, you can do so by +

    If you need to define additional matchers, you can do so by adding further <matcher> elements.

    @@ -711,7 +711,7 @@ java chapters.filters.FilterEvents src/main/java/chapters/filters/basicConfigura TurboFilter objects do not require the instantiation of a logging event to filter a logging request. As such, turbo filters are intended for high performance filtering of logging - events, even before they are created. + events, even before the events are created.

    @@ -776,11 +776,11 @@ public class SampleTurboFilter extends TurboFilter {

    The TurboFilter above accepts events that contain a specific marker. If said marker is not found, then the filter - passes the responsability to the next filter in the chain. + passes the responsibility to the next filter in the chain.

    To allow more flexibility, the marker that will be tested can - be specified in the configuration file. Hence the getter and + be specified in the configuration file, hence the getter and setter methods. We also implemented the start() method, to check that the option has been specified during the configuration process. @@ -945,9 +945,9 @@ logger.debug("Hello {}.", name1);

    The number of allowed repetitions can be specified by the AllowedRepetitions property. For example, if - the said property is set to 1, then the 2nd and subsequent + the property is set to 1, then the 2nd and subsequent occurrences of the same message will be dropped. Similarly, if the - said property is set to 2, then the 3rd and subsequent occurrences + property is set to 2, then the 3rd and subsequent occurrences of the same message will be dropped. By default, the AllowedRepetitions property is set to 5.

    @@ -1067,14 +1067,14 @@ logger.debug("Hello {}.", name1);

    EvaluatorFilter is a generic filter encapsulating an - EventEvaluator. As the name intimates, an + EventEvaluator. As the name suggests, an EventEvaluator evaluates whether a given criteria - is met for a given event. On match and respectively on mismatch, + is met for a given event. On match and on mismatch, the hosting EvaluatorFilter will return the value - specified by onMatch and respectively - to onMismatch properties. Note that + specified by the onMatch or + onMismatch properties respectively. Note that EvaluatorFilter has been previously discussed in the context of logback-classic (see above). The present text is mostly a repetition of the @@ -1086,8 +1086,8 @@ logger.debug("Hello {}.", name1); EventEvaluator. Logback-access ships with a concrete implementation named JaninoEventEvaluator. - It takes arbitrary java language boolean expressions as the - evaluation criteria. We refer to such java language boolean + It takes arbitrary Java language boolean expressions as the + evaluation criteria. We refer to such Java language boolean expressions as "evaluation expressions". Evaluation expressions enable great flexibility in event filtering. JaninoEventEvaluator requires the

    Evaluation expressions are compiled on-the-fly during the interpretation of the configuration file. As a user, you do not need to worry about the actual plumbing. However, it is your - reponsibility to ensure that the java-language expression returns + reponsibility to ensure that the Java language expression returns a boolean, i.e. that it evaluates to true or false.

    @@ -1109,7 +1109,7 @@ logger.debug("Hello {}.", name1); AccessEvent instance under the variable name event. You can read the various data associated with the HTTP request as well as the HTTP response via - the event variable. Please refer to the the event variable. Please refer to the AccessEvent class source code for the exact list.

    @@ -1137,7 +1137,7 @@ logger.debug("Hello {}.", name1); <appender-ref ref="STDOUT" /> </configuration> -

    In the next example, we still log request resulting 404 errors, +

    In the next example, we still log requests resulting in 404 errors, except those requests asking for CSS files.

    diff --git a/logback-site/src/site/pages/manual/groovy.html b/logback-site/src/site/pages/manual/groovy.html index 064dcb9..8e06a19 100644 --- a/logback-site/src/site/pages/manual/groovy.html +++ b/logback-site/src/site/pages/manual/groovy.html @@ -41,51 +41,51 @@ -

    Domains-specific languages or DSLs are rather pervasive. The +

    Domain-specific languages or DSLs are rather pervasive. The XML-based logback configuration can be viewed as a DSL instance. By the very nature of XML, XML-based configuration files are quite verbose and rather bulky. Moreover, a relatively large - body of code in logback, namely Joran, is dedicated to processes + body of code in logback, namely Joran, is dedicated to processing these XML-based configuration files. Joran supports nifty features such as variable substitution, conditional processing and - on-the-fly extensibility. However, not only Joran is a complex + on-the-fly extensibility. However, not only is Joran a complex beast, the user-experience it provides can be described as unsatisfactory or at the very least unintuitive.

    The Groovy-based DSL described in this chapter aims to be - consistent, intuitive, and powerful. Everything you can do XML in + consistent, intuitive, and powerful. Everything you can do using XML in configuration files, you can do in Groovy with a much shorter syntax. To help you migrate to Groovy style configuration, we have - developped a tool to - automatically migrate your existinglogback.xml files to + automatically migrate your existing logback.xml files to logback.groovy.

    General philosophy

    -

    As a general rule, logback.groovy files are groovy - programs. And since groovy is a super-set of Java, whatever +

    As a general rule, logback.groovy files are Groovy + programs. And since Groovy is a super-set of Java, whatever configuration actions you can perform in Java, you can do the same within a logback.groovy file. However, since configuring logback progammatically using Java syntax can be cumbersome, we added a few logback-specific extensions to make your life easier. We try hard to limit the number of logback-specific syntactic extensions to an absolute minimum. If you are already - familiar with groovy, you should be able to read, understand and + familiar with Groovy, you should be able to read, understand and even write your own logback.groovy files with great ease. Those unfamiliar with Groovy should still find logback.groovy syntax much more comfortable to use than logback.xml.

    -

    Given that logback.groovy files are groovy programs - with minimal logback-specific extensins, all the usual +

    Given that logback.groovy files are Groovy programs + with minimal logback-specific extensions, all the usual groovy constructs such as class imports, variable definitions, evaluation of ${..} expressions contained in strings - (GStrings), if-else statements are all avaiable in + (GStrings), and if-else statements are available in logback.groovy files.

    Extensions specific to logback.groovy

    @@ -105,7 +105,7 @@ the root logger. As an optional second argument of type List<String>, can be used to attach previously defined appenders by name. If you do not specify the list of - appender names, then an empty list is assumed. In groovy, an empty + appender names, then an empty list is assumed. In Groovy, an empty list is denoted by [].

    To set the level of the root logger to WARN, you would write:

    @@ -138,14 +138,14 @@ root(INFO, ["CONSOLE", "FILE"]) href="architecture.html#effectiveLevel">inherit its level from its nearest ancestor with an assigned level. The third argument of type List<String> is optional and defaults to an - emtpy list if omitted. The appender names in the list are attached - to the designated logger. The forth argument of type + empty list if omitted. The appender names in the list are attached + to the designated logger. The fourth argument of type Boolean is also optional and controls the additivity flag. If omitted, it defaults to null.

    -

    For example, the following script set the level of the +

    For example, the following script sets the level of the "com.foo" logger to INFO.

    import static ch.qos.logback.classic.Level.INFO
    @@ -219,8 +219,8 @@ root(DEBUG, ["FILE"])

    timestamp(String datePattern)

    The timestamp() method method returns a string - corresponding to the current time formatted according to - datePattern passed as parameter. The datePattern + corresponding to the current time formatted according to the + datePattern passed as a parameter. The datePattern parameter should follow the conventions defined by SimpleDateFormat.

    @@ -323,12 +323,12 @@ root(DEBUG, ["STDOUT"])

    Internal DSL, i.e. it's all groovy baby!

    The logback.groovy is an internal DSL meaning that its - contents are executed as a groovy script. Thus, all the usual - groovy constructs such as class imports, GString, variable + contents are executed as a Groovy script. Thus, all the usual + Groovy constructs such as class imports, GString, variable definitions, evaluation of ${..} expressions contained - within strings (GStrings), if-else statements are all avaiable in + within strings (GStrings), if-else statements are all available in logback.groovy files. In the following discussion, we will present - typical uses of these groovy constructs in logback.groovy + typical uses of these Groovy constructs in logback.groovy files.

    @@ -336,7 +336,7 @@ root(DEBUG, ["STDOUT"])

    Variable definitions and GStrings

    You can define variables anywhere within a - logback.groovy files, then use the variable within a + logback.groovy file, then use the variable within a GString. Here is an example.

    import ch.qos.logback.classic.encoder.PatternLayoutEncoder
    @@ -427,8 +427,8 @@ appender("STDOUT", ConsoleAppender) {
        

    Everything is context aware with a reference to the current context

    -

    The execution of the logback.grooy script is done - within a scope of a The execution of the logback.groovy script is done + within the scope of a ContextAware object. Thus, the current context is always accessible using the 'context' variable and you can invoke @@ -526,4 +526,4 @@ root(INFO, appenderList)

    - \ No newline at end of file + diff --git a/logback-site/src/site/pages/manual/index.html b/logback-site/src/site/pages/manual/index.html index 5d0599a..66abd44 100644 --- a/logback-site/src/site/pages/manual/index.html +++ b/logback-site/src/site/pages/manual/index.html @@ -29,7 +29,7 @@

    If you wish to print chapters in this document, we recommend that you do so using Firefox 2, with Adapt to + href="http://www.getfirefox.com">Firefox 2+, with Adapt to page size enabled, or Opera.

    @@ -37,7 +37,7 @@

    The complete logback manual documents the latest version of logback framework. In over 150 pages and dozens of concrete - examples, it covers both basic and advanced logback features: + examples, it covers both basic and advanced logback features, including:

    @@ -51,7 +51,7 @@
  • layouts

  • filters

  • mapped diagnostic contexts

  • -
  • joran, logback's configuration system

  • +
  • Joran, logback's configuration system

  • diff --git a/logback-site/src/site/pages/manual/introduction.html b/logback-site/src/site/pages/manual/introduction.html index 481d609..287fb5a 100644 --- a/logback-site/src/site/pages/manual/introduction.html +++ b/logback-site/src/site/pages/manual/introduction.html @@ -34,7 +34,7 @@ much more complex entities in four months than they can build.

    -

    —FREDERIC P. BROOKS, JR., The Mythical Man-Month

    +

    —FREDERICK P. BROOKS, JR., The Mythical Man-Month

    @@ -44,13 +44,13 @@

    Logback is intended as a successor to the popular log4j project. It was designed by Ceki Gülcü, log4j's - founder. It builds upon a decade long experience gained in + founder. It builds upon a decade of experience gained in designing industrial-strength logging systems. The resulting - product, logback is faster with a smaller footprint than all + product logback is faster and has a smaller footprint than all existing logging systems, sometimes by a wide margin. Logback also offers unique and rather useful features such as Markers, parameterized logging statements, conditional stack tracing and - powerful event filtering. These are only a few examples of useful + powerful event filtering. These are only a few examples of the useful features logback has to offer. For its own error reporting, logback relies on Status objects, which greatly facilitate troubleshooting. You may wish to rely on Status objects @@ -66,8 +66,8 @@

    Requirements

    -

    Logback-classic module requires the presence - slf4j-api.jar, logback-core.jar in addition to +

    Logback-classic module requires the presence of + slf4j-api.jar and logback-core.jar in addition to logback-classic.jar on the classpath.

    @@ -99,7 +99,7 @@ public class HelloWorld1 { href="http://slf4j.org/api/org/slf4j/Logger.html">Logger and LoggerFactory - classes defined in the SLF4J API, more specifically within the + classes defined in the SLF4J API, specifically within the org.slf4j package.

    @@ -117,8 +117,8 @@ public class HelloWorld1 {

    Note that the above example does not reference any logback classes. In most cases, as far as logging is concerned, your classes will only need to import SLF4J classes. Thus, the vast - majority, if not all, of your classes will be cognizant of SLF4J - API and oblivious to the existence of logback. + majority, if not all, of your classes will use the SLF4J + API and will be oblivious to the existence of logback.

    @@ -182,7 +182,7 @@ public class HelloWorld2 { policy, which is a basic ConsoleAppender. An Appender is a class that can be seen as an output destination. Appenders exist for many different destinations - including the console, files, Syslog, TCP Socket, JMS and many + including the console, files, Syslog, TCP Sockets, JMS and many more. Users can also easily create their own Appenders as appropriate for their specific situation.

    @@ -199,7 +199,7 @@ public class HelloWorld2 {

    Note that in the above example we have instructed logback to - print its internal state by invoking + print its internal state by invoking the StatusPrinter.print() method. Logback's internal status information can be very useful in diagnosing logback-related problems. diff --git a/logback-site/src/site/pages/manual/jmxConfig.html b/logback-site/src/site/pages/manual/jmxConfig.html index 7e7f7d9..c35bfb4 100644 --- a/logback-site/src/site/pages/manual/jmxConfig.html +++ b/logback-site/src/site/pages/manual/jmxConfig.html @@ -37,7 +37,7 @@

    If your server run on JDK 1.6 or later, then you can just - invoke jconsole application on the commmand line and + invoke the jconsole application on the command line and then connect to your server's MBeanServer. If you are running an older JVM, then you should read the section on JMX enabling your server. @@ -76,23 +76,23 @@

    • Reload logback configuration using the default configuration - file
    • + file. -
    • Reload the configuration with the specified URL
    • -
    • Reload the configuration with the specified file
    • +
    • Reload the configuration with the specified URL.
    • +
    • Reload the configuration with the specified file.
    • Set the level of a specified logger. To set to null, pass the string "null" as value.
    • -
    • Get the level of a specified logger. Returned value can be +
    • Get the level of a specified logger. The returned value can be null.
    • Get the effective - level of a specified logger
    • + level of a specified logger.

    JMXConfigurator exposes the list of existing loggers and a status list as attributes.

    -

    The status list can help you diagnose logbacks internal +

    The status list can help you diagnose logback's internal state.

    statusList.gif @@ -106,12 +106,12 @@ from being garbage collected when it is stopped or re-deployed, resulting in a severe memory leak.

    -

    Thus, unless your application is standalone java application, +

    Thus, unless your application is a standalone Java application, you MUST unregister the JMXConfigurator instance from the JVM's Mbeans server. Invoking the reset() method of the appropriate LoggerContext will automatically unregister any JMXConfigurator instance. A good place to reset the - logger context is in the the contextDestroyed() + logger context is in the contextDestroyed() method of a javax.servlet.ServletContextListener. Here is sample code:

    @@ -143,11 +143,11 @@ public class MyContextListener implements ServletContextListener {

    If you deploy multiple web-applications in the same server, - then, and assuming you have not overriden the default context selector, and assuming you + and if you have not overridden the default context selector, and if you have placed a copy of logback-*.jar and slf4j-api.jar under the WEB-INF/lib folder of - each web-application, by default each JMXConfigurator + each web-application, then by default each JMXConfigurator instance will be registered under the same name, that is, "ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator". In other words, by default the various JMXConfigurator @@ -180,14 +180,14 @@ public class MyContextListener implements ServletContextListener { ... <configuration> -

    In jconsole's MBeans panel, you would two distinct +

    In jconsole's MBeans panel, you would see two distinct JMXConfigurator instances:

    multiple.gif

    You may fully control the name under which JMXConfigurator is - registered with MBeans server with the help of the "objectName" - attribute of <jmxConfigurator> element.

    + registered with an MBeans server with the help of the "objectName" + attribute of the <jmxConfigurator> element.

    @@ -199,7 +199,7 @@ public class MyContextListener implements ServletContextListener {

    If your server runs with JDK 1.6 or later, your server should be JMX enabled by default.

    -

    For older JVMs, we suggest that you refer JMX-related +

    For older JVMs, we suggest that you refer to the JMX-related documentation of your web-server. Such documentation is available for both Tomcat @@ -236,8 +236,8 @@ public class MyContextListener implements ServletContextListener { </Get>

    If you wish to access the MBeans exposed by Jetty via the - jconsole application, then you need start jetty after - having set the "com.sun.management.jmxremote" java system + jconsole application, then you need to start Jetty after + having set the "com.sun.management.jmxremote" Java system property.

    @@ -246,8 +246,8 @@ public class MyContextListener implements ServletContextListener {

    java -Dcom.sun.management.jmxremote -jar start.jar [config files]

    -

    And if you wish to launch jetty as a Maven plugin, then you - need set the "com.sun.management.jmxremote" system property via +

    And if you wish to launch Jetty as a Maven plugin, then you + need to set the "com.sun.management.jmxremote" system property via the MAVEN_OPTS shell variable:

    @@ -266,10 +266,10 @@ mvn jetty:run

    MX4J with Jetty (tested under JDK 1.5 and 1.6)

    -

    Ig you wish to acces JMXConfigurator via MX4J's +

    If you wish to access JMXConfigurator via MX4J's HTTP interface and assuming you have already downloaded MX4J, you then need to - modify the jetty configuration file discussed previously by adding + modify the Jetty configuration file discussed previously by adding an instruction to set the management port.

    @@ -294,7 +294,7 @@ mvn jetty:run

    class path.

    -

    If you are running jetty as a Maven plug-in, then you need to add +

    If you are running Jetty as a Maven plug-in, then you need to add mx4j-tools as a dependency.

    <plugin>
    @@ -338,7 +338,7 @@ mvn jetty:run

    CATALINA_OPTS="-Dcom.sun.management.jmxremote"

    -

    Once started with these options, Mbeans exposed by Tomcat as +

    Once started with these options, MBeans exposed by Tomcat as well logback's JMXConfigurator can be accessed with jconsole by issuing the following command in a shell:

    @@ -360,7 +360,7 @@ mvn jetty:run

    Assuming you have already downloaded MX4J, placethe + href="http://mx4j.sourceforge.net/">MX4J, place the mx4j-tools.jar file under the $TOMCAT_HOME/bin/ directory. Then, add the following lines to the $TOMCAT_HOME/bin/catalina.sh configuration file: diff --git a/logback-site/src/site/pages/manual/layouts.html b/logback-site/src/site/pages/manual/layouts.html index 133f36e..3cb8333 100644 --- a/logback-site/src/site/pages/manual/layouts.html +++ b/logback-site/src/site/pages/manual/layouts.html @@ -68,7 +68,7 @@

    Logback-classic

    -

    Logback-classic is wired to processes only events of type +

    Logback-classic is wired to process only events of type ch.qos.logback.classic.spi.ILoggingEvent. This fact will be apparent throughout this section.

    @@ -132,7 +132,7 @@ public class MySampleLayout extends LayoutBase<ILoggingEvent> { instantiating a StringBuffer. It proceeds by adding various fields of the event parameter. The Texan from Texas was careful to print the formatted form of the message. This is - significant in case one or more parameters were passed along with + significant if one or more parameters were passed along with the logging request.

    @@ -260,9 +260,9 @@ public class MySampleLayout2 extends LayoutBase<ILoggingEvent> { needed to enable the configuration of a property. Note that the PrintThreadName property is a boolean and not a String. Configuration of logback components was - covered in detail in the chapter on configuration. The chapter on joran provides further detail. Here is + covered in detail in the chapter on configuration. The chapter on Joran provides further detail. Here is the configuration file tailor made for MySampleLayout2.

    @@ -297,7 +297,7 @@ public class MySampleLayout2 extends LayoutBase<ILoggingEvent> { PatternLayout. As all layouts, PatternLayout takes a logging event and returns a String. However, this String can be - customized at will by tweaking PatternLayout's + customized by tweaking PatternLayout's conversion pattern.

    @@ -317,7 +317,7 @@ public class MySampleLayout2 extends LayoutBase<ILoggingEvent> {

    As already mentioned on several occasions, FileAppender and sub-classes expect an - encoder. Consequently, when used in conjuction with + encoder. Consequently, when used in conjunction with FileAppender or its subclasses a PatternLayout must be wrapped within an encoder. Given that the @@ -371,7 +371,7 @@ public class PatternSample { }

    In the above example, the conversion pattern is set to be - "%-5level [%thread]: %message%n". A synopssis of conversion + "%-5level [%thread]: %message%n". A synopsis of conversion word included in logback will be given shortly. Running PatternSample application as:

    @@ -491,7 +491,7 @@ WARN [main]: Message 2

    -

    Please note that the right most segment in a logger name +

    Please note that the rightmost segment in a logger name is never abbreviated, even if its length is longer than the length option. Other segments may be shortened to at most a single character but are never removed.

    @@ -511,14 +511,14 @@ WARN [main]: Message 2

    Just like the %logger conversion word above, - this conversion admits an integer as an option to shorten + this conversion takes an integer as an option to shorten the class name. Zero carries special meaning and will cause the simple class name to be printed without the package name prefix. By default the class name is printed in full.

    Generating the caller class information is not - particularly fast. Thus, it's use should be avoided unless + particularly fast. Thus, its use should be avoided unless execution speed is not an issue.

    @@ -583,7 +583,7 @@ WARN [main]: Message 2

    In addition to the date pattern, this converter admits a second option as the timezone. Thus, the '%date{HH:mm:ss.SSS,Australia/Perth} would print the time in - the time zone of Perth Australia, the worlds most isolated + the time zone of Perth, Australia, the world's most isolated city.

    @@ -706,7 +706,7 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38)

    Generating the method name is not particularly fast. - Thus, it's use should be avoided unless + Thus, its use should be avoided unless execution speed is not an issue.

    @@ -780,7 +780,7 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38) generated the logging event.

    -

    If mdc conversion word is followed by a key +

    If the mdc conversion word is followed by a key between braces, as in %mdc{clientNumber}, then the value in the MDC corresponding to the key will be output.

    @@ -858,7 +858,7 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38)

    This conversion word can also use evaluators to test logging events against a given criterion before creating the output. For example, using %ex{full, EX_DISPLAY_EVAL} - will display the full stack trace of the exception, only if + will display the full stack trace of the exception only if the evaluator called EX_DISPLAY_EVAL returns a negative answer. Evaluators are described further down in this document. @@ -888,8 +888,8 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38) PatternLayout will automatically add it as the last conversion word, on account of the importance of stack trace information. The $nopex conversion word can be - substituted for %xThrowable, in case you do not wish stack - trace information to be displayed. See also %nopex + substituted for %xThrowable, if you do not wish stack + trace information to be displayed. See also the %nopex conversion word.

    @@ -926,7 +926,7 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38) the printed class packaging information to differ from the real class packaging information. So, in the above example, given that packaging data for the Wombat class is preceded - by a tilde, it possible that the correct packaging data is + by a tilde, it is possible that the correct packaging data is in reality [wombat.jar:1.7].

    @@ -1041,7 +1041,7 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38)

    Format modifiers

    -

    By default the relevant information is output as is. However, +

    By default the relevant information is output as-is. However, with the aid of format modifiers it is possible to change the minimum and maximum width and the justifications of each data field. @@ -1160,7 +1160,7 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38)

    The table below list examples for format modifier - truncation. Please note that the brackets, i.e the pair of "[]" + truncation. Please note that the square brackets, i.e the pair of "[]" characters, are not part of the output. They are used to delimit the width of output.

    @@ -1282,7 +1282,7 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38) needs to be escaped. Thus, "(%d [%thread]\)" is equivalent to "\(%d [%thread]\)". But since it is not easy to recall which parenthesis needs escaping and which - doesn't necessarily, you can escape both so that they are + doesn't, you can escape both so that they are interpreted as literals.

    @@ -1303,8 +1303,8 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38) the logging events to the console, displaying date, thread, level, message and caller data. Given that extracting the caller data of a logging event is on the expensive side, we will do so only when - the logging request originates from a specific logger, and whose - message contains a certain string. Thus, we make sure that only + the logging request originates from a specific logger, and when + the message contains a certain string. Thus, we make sure that only specific logging requests will have their caller information generated and displayed. In other cases, where the caller data is superfluous, we will not penalize application performance. @@ -1313,7 +1313,7 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38)

    Evaluators and in particular evaluation expressions are presented in a dedicated section of the - chapter on filters which you MUST read if you want use + chapter on filters which you MUST read if you want to use evaluators in any meaninful way. Also note that the examples below are implicitly based on JaninoEventEvaluator which requires the </configuration>

    The above evaluation expression matches events which emanate - from logger with a name containing the string "chapters.layouts" - and the message containing the string "who calls thee". Due to XML + from a logger with a name containing the string "chapters.layouts" + and the message contains the string "who calls thee". Due to XML encoding rules, the & character cannot be written as is, and needs to be escaped as &amp;.

    @@ -1444,12 +1444,11 @@ Caller+0 at chapters.layouts.CallerEvaluatorExample.main(CallerEvaluatorExampl some specific exceptions.

    -

    The java code shown below creates three log requests, each with - an exception. The second exception different from the others - contains the string "do not display this" and conttrary to the - others it is of type +

    The Java code shown below creates three log requests, each with + an exception. The second exception is different from the others: + it contains the string "do not display this" and it is of type chapters.layouts.TestException. As its message - commands, let us now prevent the third exception from being + commands, let us now prevent the second exception from being printed.

    @@ -1544,7 +1543,7 @@ java.lang.Exception: display

    Notice how the second log statement has no stack trace. We - effectively supressed the stack trace for the + effectively suppressed the stack trace for the TextException. The text between square brackets at the end of each stack trace line is packaging information discussed @@ -1572,7 +1571,7 @@ java.lang.Exception: display href="../xref/ch/qos/logback/classic/pattern/ClassicConverter.html"> ClassicConverter objects are responsible for extracting information out of ILoggingEvent instances - and producing a String. For example, the + and producing a String. For example, LoggerConverter, the converter underlying the %logger conversion word, extracts the name of the logger from @@ -1713,7 +1712,7 @@ public class MySampleConverter extends ClassicConverter { or more generally by literal text. Each specifier found in the pattern will result in a separate column. Likewise a separate column will be generated for each block of literal text found in - the pattern potentially wasting valuable real estate on your + the pattern, potentially wasting valuable real-estate on your screen.

    Here is simple but functional configuration file illustrating @@ -1786,7 +1785,7 @@ public class MySampleConverter extends ClassicConverter {

    The presentation of the HTML created by HTMLLayout is controlled through a Cascading Style Sheet (CSS). In the absence of specific instructions, HTMLLayout will - default to its internal CSS. However, your can instruct + default to its internal CSS. However, you can instruct HTMLLayout to use an external CSS file. For this purpose a cssBuilder element can be nested within a <layout> element, as shown below. @@ -1822,7 +1821,7 @@ public class MySampleConverter extends ClassicConverter {

    As the original XMLLayout in log4j version 1.2.15, XMLLayout in - logback-classic admits two boolean properties, locationInfo and properties. Setting locationInfo to true enables the inclusion @@ -1860,7 +1859,7 @@ public class MySampleConverter extends ClassicConverter {

    Writing your own Layout

    Writing a custom Layout for logback access is - nearly identical to its siblingLayout in + nearly identical to its sibling Layout in logback-classic.

    @@ -1870,7 +1869,7 @@ public class MySampleConverter extends ClassicConverter {

    PatternLayout in logback-access can be configured - much in the same way as its classic counterpart. However it + in much the same way as its classic counterpart. However it features additional conversion specifiers suited for logging particular bits of information availalbe only in HTTP servlet requests and HTTP servlet responses. @@ -2111,7 +2110,7 @@ public class MySampleConverter extends ClassicConverter { -

    Logback access' PatternLayout also recognize three keywords, which +

    Logback access' PatternLayout also recognizes three keywords, which act like shortcuts to a certain pattern.

    diff --git a/logback-site/src/site/pages/manual/loggingSeparation.html b/logback-site/src/site/pages/manual/loggingSeparation.html index 17f6b54..0be426c 100644 --- a/logback-site/src/site/pages/manual/loggingSeparation.html +++ b/logback-site/src/site/pages/manual/loggingSeparation.html @@ -52,7 +52,7 @@

    The chapter deals with a relatively difficult problem of providing a separate logging environment for multiple applications running on the same web or EJB container. In the remainder of this - chapter the term "application" will be used to refer either a + chapter the term "application" will be used to refer to either a web-application or a J2EE application interchangeably. In a separated logging environment, each application sees a distinct logback environment, so that the logback configuration of one @@ -69,7 +69,7 @@

    The simplest and easiest approach

    -

    Assuming your container supports child first class loading, +

    Assuming your container supports child-first class loading, separation of logging can be accomplished by embedding a copy of slf4j and logback jar files in each of your applications. For web-applications, placing slf4j and logback jar files under the @@ -189,7 +189,7 @@ file called logback-kenobi.xml as a resource using the thread context class loader. Thus, for example for the kenobi web-application, logback-kenobi.xml should be - placed under the under the WEB-INF/classes folder. + placed under the WEB-INF/classes folder.

    If you wish to, you may specify a different configuration file @@ -208,9 +208,9 @@ <env-entry-value>aFolder/my_config.xml</env-entry-value> </env-entry> -

    The my_config.xml should be placed under - WEB-INF/classes/aFolfer/. The important point to remember - is that the configuration is looked up as a java resource using +

    The file my_config.xml should be placed under + WEB-INF/classes/aFolder/. The important point to remember + is that the configuration is looked up as a Java resource using the current thread's context class loader.

    @@ -258,11 +258,11 @@

    When ContextJNDISelector is active, each time a logger is retrieved, a JNDI lookup must be performed. This can negatively impact performance, especially if you are using - non-static (aka instance) logger references. Logback ships with a + non-static (a.k.a. instance) logger references. Logback ships with a servlet filter named LoggerContextFilter, specifically designed to avoid the JNDI lookup cost. It can - be installed by adding the following lines to your applications + be installed by adding the following lines to your application's web.xml file.

    <filter>
    @@ -278,7 +278,7 @@
        LoggerContextFilter will obtain the logger context
        associated with the application and then place it in a
        ThreadLocal variable. ContextJNDISelector
    -   will first check if the said ThreadLocal variable is
    +   will first check if the ThreadLocal variable is
        set. If it is set, then JNDI lookup will skipped. Note that at the
        end of the http request, the ThreadLocal variable will
        be nulled.  Installing LoggerContextFilter improves
    @@ -327,7 +327,7 @@
         LoggerFactory.getLogger() will return a logger
         belonging to a logger context associated with the calling/current
         application. But if Mustafar has a static logger
    -    reference, then its logger will be attach to logger context of the
    +    reference, then its logger will be attached to the logger context of the
         application that calls it first. Thus,
         ContextJNDISelector does not provide logging
         separation in case of shared classes using static logger
    @@ -385,8 +385,8 @@
     
     
        

    If kenobi and yoda are web-applications, then the above - configuration will output yoda's logs output to yoda.log - and kenobi's logs to kenobi.log, this even logs generated + configuration will output yoda's log output to yoda.log + and kenobi's logs to kenobi.log; this even works for logs generated by static logger references located in shared classes.

    You can try out the technique just described with the help of the @@ -446,7 +446,7 @@ DEBUG ch.qos.starwars.shared.Mustafar cn=yoda - in foo()

    kenobi.log. Each of these contexts reference FileAppender instances, nested within distinct - SiftingAppender instances, logging to the same + SiftingAppender instances, that are logging to the same file. Although logging separation seems to function according to our wishes, FileAppender instances cannot safely write to the same file unless they enable prudent diff --git a/logback-site/src/site/pages/manual/mdc.html b/logback-site/src/site/pages/manual/mdc.html index afdb15b..5522b3d 100644 --- a/logback-site/src/site/pages/manual/mdc.html +++ b/logback-site/src/site/pages/manual/mdc.html @@ -73,7 +73,7 @@ public class MDC { //Get the context identified by the key parameter. public static String get(String key); - //Remove the the context identified by the key parameter. + //Remove the context identified by the key parameter. public static void remove(String key); //Clear all entries in the MDC. @@ -116,7 +116,7 @@ import ch.qos.logback.core.ConsoleAppender; public class SimpleMDC { static public void main(String[] args) throws Exception { - // You can put values in the MDC at any time. Before anything else + // You can put values in the MDC at any time. Before anything else // we put the first name MDC.put("first", "Dorothy"); @@ -642,8 +642,8 @@ public class UserServletFilter implements Filter {

    MDCInsertingServletFilter

    -

    Within web-applications, it often proves helpful to know the - hostname, request uri and user-agent associated with a given http +

    Within web applications, it often proves helpful to know the + hostname, request uri and user-agent associated with a given HTTP request. MDCInsertingServletFilter inserts such data into the MDC under the following keys. @@ -719,7 +719,7 @@ public class UserServletFilter implements Filter { <url-pattern>/*</url-pattern> </filter-mapping>

    -

    If your web-app has multiple filter, make sure that +

    If your web-app has multiple filters, make sure that MDCInsertingServletFilter is declared before other filters. For example, assuming the main processing in your web-app is done in filter 'F', the MDC values set by diff --git a/logback-site/src/site/pages/manual/migrationFromLog4j.html b/logback-site/src/site/pages/manual/migrationFromLog4j.html index 6f44908..15e6727 100644 --- a/logback-site/src/site/pages/manual/migrationFromLog4j.html +++ b/logback-site/src/site/pages/manual/migrationFromLog4j.html @@ -51,23 +51,23 @@ closely related. The core components, such as loggers, appenders and layouts exist in both frameworks and serve identical purposes. Similarly, the most important internal data-structure, - namely LoggingEvent exists in both frameworks with - rather similar but non-identical implementations. Most notably, In + namely LoggingEvent, exists in both frameworks with + rather similar but non-identical implementations. Most notably, in logback-classic LoggingEvent implements the - ILoggingEvent interface. Most of the changes requried + ILoggingEvent interface. Most of the changes required in migrating log4j components to logback-classic are related to differences in implementation of the LoggingEvent class. Rest assured, these differences are rather limited. If in spite of your best efforts you are unable to migrate any given log4j component to logback-classic, do post a question on the logback-dev mailing list. A logback - developper should be able to provide guidance. + developer should be able to provide guidance.

    Migrating a log4j layout

    -

    Let us begin by migrating a hypothetcical and trivially simple +

    Let us begin by migrating a hypothetical and trivially simple log4j layout named TrivialLog4jLayout which returns the message contained in a logging events as the @@ -202,7 +202,7 @@ public class TrivialLogbackAppender extends AppenderBase<ILoggingEvent> { requiresLayout method is not used in logback and can be removed. In logback, the stop() method is the equivalent of log4j's close() method. However, - AppenderBase in logback-classic, contains an nop + AppenderBase in logback-classic, contains a nop implementation for stop which is sufficient for the purposes of this trivial appender.

    diff --git a/logback-site/src/site/pages/manual/onJoran.html b/logback-site/src/site/pages/manual/onJoran.html index 0060d72..2c6d5be 100644 --- a/logback-site/src/site/pages/manual/onJoran.html +++ b/logback-site/src/site/pages/manual/onJoran.html @@ -51,7 +51,7 @@ folder.

    -

    To install joran, simply download +

    To install Joran, simply download logback and add logback-core-${version}.jar to your classpath.

    @@ -64,10 +64,10 @@ their properties are specified within the ejb.xml file. Similarly, logback settings can be specified in a configuration file, expressed in XML format. Annotations available - in JDK 1.5 and heavily used in EJB 3.0 replace many of directives - previously found in XML files. Joran also makes use of annonations - but at a much smaller extent. Due to the dynamic nature of logback - configuration data (compared to EJBs) Joran's use of annonations + in JDK 1.5 and heavily used in EJB 3.0 replace many directives + previously found in XML files. Joran also makes use of annotations + but to a much smaller extent. Due to the dynamic nature of logback + configuration data (compared to EJBs) Joran's use of annotations is rather limited.

    @@ -79,8 +79,8 @@ the configuration file changed. The modified code had to be recompiled and redeployed. Just as importantly, the code of the DOMConfigurator consisted of loops dealing with - children elements containing many interspersed if/else - statements. One could not help but notice that that particular + child elements containing many interspersed if/else + statements. One could not help but notice that this particular code reeked of redundancy and duplication. The commons-digester project had shown us that it was possible to parse XML files @@ -147,8 +147,8 @@

    A Joran pattern is essentially a string. There are two kind of patterns, exact and wildcard. The pattern "a/b" - can be used to match <b> element nested within a - top-level <a> element. The "a/b" will not match + can be used to match a <b> element nested within a + top-level <a> element. The "a/b" pattern will not match any other element, hence the exact match designation.

    Wildcards can be used to match suffixes or prefixes. For @@ -166,7 +166,7 @@ association of patterns. Actions extend the Action class, consisting of the following abstract methods. Other methods - have been omitted for berevity. + have been omitted for brevity.

    @@ -200,8 +200,8 @@ public abstract class Action { }

    Thus, every action must implement the begin() and - end() methods. The implemetnation of the - body() method being optional on account of the + end() methods. The implementation of the + body() method is optional on account of the empty/nop implementation provided by Action.

    @@ -215,10 +215,10 @@ public abstract class Action {

    As mentioned above, Joran is built on top of the SAX API. As an XML document is parsed, each element generates events corresponding - to the start, body and end of each element. When a joran + to the start, body and end of each element. When a Joran configurator receives these events, it will attempt to find in its rule store an action corresponding to the current - pattern.. For example, the current pattern for the start, body + pattern. For example, the current pattern for the start, body or end event of element B nested within a top-level A element is "A/B". The current pattern is a data structure maintained automatically by Joran as it receives and @@ -226,7 +226,7 @@ public abstract class Action {

    When several rules match the current pattern, then exact matches override suffix matches, and suffix matches overide prefix - matches. For exact details of implementation, please see the SimpleRuleStore class.

    @@ -259,14 +259,14 @@ public abstract class Action { trivial action called HelloWorldAction which prints "Hello World" on the - console when it's begin() method is invoked. The + console when its begin() method is invoked. The parsing of XML files is done by a configurator. For the purposes of - this chapter, we have developped a very simple configurator called + this chapter, we have developed a very simple configurator called SimpleConfigurator. The HelloWorld - application brings all pieces together. + application brings all these pieces together:

      @@ -276,10 +276,10 @@ public abstract class Action { HelloWorldAction instance
    • It creates a SimpleConfigutator, passing it the aforementioned rules map
    • -
    • it then invokes the doConfigure method of the +
    • It then invokes the doConfigure method of the configurator, passing the designated XML file as parameter
    • -
    • as a last step, the accumulated Status message in the context, +
    • As a last step, the accumulated Status message in the context, if any, are printed
    @@ -294,7 +294,7 @@ public abstract class Action {

    java chapters.onJoran.helloWorld.HelloWorld src/main/java/chapters/onJoran/helloWorld/hello.xml

    -

    You are highly encourared to poke about this example, by adding +

    You are highly encourared to poke about in this example, by adding new rules on the rule store, modifying the XML document (hello.xml) and adding new actions.

    @@ -427,7 +427,7 @@ public abstract class Action { will pop two previously pushed integers, i.e. 10 and 3, and compute their product. It will push the result, i.e. 30, at the top of the stack. At the very end, in reponse to the end event corresponding to - the <;/computation> tag, the ComputationAction1 will print the + the </computation> tag, the ComputationAction1 will print the object at the top of the stack. Thus, running:

    @@ -491,7 +491,7 @@ public abstract class Action { attaches the resulting object to the parent.

    -

    Joran supports similar capability in the form of implicit +

    Joran supports a similar capability in the form of implicit actions. Joran keeps a list of implicit actions which are applied if no explicit pattern could match the current pattern. However, applying an implicit action may not be always appropriate. Before @@ -499,7 +499,7 @@ public abstract class Action { whether it is appropriate in the current situation. Only if the action replies in the affirmative does the Joran configurator invoke the (implicit) action. Note that this extra step makes it possible - to support multiple implicit actions for or possibly none, if no + to support multiple implicit actions or possibly none, if no implicit action is appropriate for a given situation.

    @@ -553,7 +553,7 @@ Element [abc] asked to be printed. 20:33:43,750 |-ERROR in c.q.l.c.joran.spi.Interpreter@10:9 - no applicable action for [xyz], current pattern is [[foo][xyz]]

    Given that NOPAction instance is explicitly - associated with the "*/foo" pattern, NOPActgion's + associated with the "*/foo" pattern, NOPAction's begin() and end() methods are invoked on <foo> elements. PrintMeImplicitAction is never triggered for any of the <foo> elements. For other elements, @@ -582,20 +582,20 @@ Element [abc] asked to be printed.

    NestedBasicPropertyIA is applicable for any property - whose type, is a primitive type, or equivalent object type in the - java.lang package, an enumeration type, or any type + whose type is a primitive type (or equivalent object type in the + java.lang package), an enumeration type, or any type adhering to the "valueOf" convention. Such properties are said to be basic or simple. A class is said to adhere to the "valueOf" convention if it contains a static method named valueOf() taking a java.lang.String as parameter and returning an instance of the type in question. At - present time, Level, Duration and FileSize - classes follow this convention.. + classes follow this convention.

    NestedComplexPropertyIA action is applicable, in the @@ -619,21 +619,21 @@ Element [abc] asked to be printed.

    1. there is an internal rule associating the parent object's - property with a designated class, + property with a designated class
    2. the setter method contains a @DefaultClass attribute - designating a given class,
    3. + designating a given class -
    4. the parameter type of the setter method is a contcrete class - possessing a public constructor, +
    5. the parameter type of the setter method is a concrete class + possessing a public constructor

    Default class mapping

    -

    In logback-classic, there are a handful of inernal rules mapping - parent class/property name couples to a default class. These are +

    In logback-classic, there are a handful of internal rules mapping + parent class/property name pairs to a default class. These are listed in the table below.

    @@ -693,7 +693,7 @@ Element [abc] asked to be printed.

    Note that in addition to single simple properties or single - complex properties, logback's implicit actions support collectons of + complex properties, logback's implicit actions support collections of properties, be they simple or complex. Instead of a setter method, the property is specified by an "adder" method.

    diff --git a/logback-site/src/site/pages/news.html b/logback-site/src/site/pages/news.html index 136af2a..dadd9f7 100644 --- a/logback-site/src/site/pages/news.html +++ b/logback-site/src/site/pages/news.html @@ -1515,8 +1515,8 @@ ALTER TABLE logging_event ADD arg3 VARCHAR(254);

    Version 0.2.5 of logback has been released.

    -

    This release offers better documentation. With a number of - correction mande in the short introduction to logback-classic. +

    This release offers better documentation, with a number of + corrections made in the short introduction to logback-classic.


    @@ -1526,7 +1526,7 @@ ALTER TABLE logging_event ADD arg3 VARCHAR(254);

    Version 0.2 of logback has been released.

    -

    It offers better tests, a few more functionalities, and enhanced +

    It offers better tests, some more functionality, and enhanced documentation. We also improved the site design to make it simpler and more efficient.

    diff --git a/logback-site/src/site/pages/reasonsToSwitch.html b/logback-site/src/site/pages/reasonsToSwitch.html index ed2bcd3..3e7592b 100644 --- a/logback-site/src/site/pages/reasonsToSwitch.html +++ b/logback-site/src/site/pages/reasonsToSwitch.html @@ -71,8 +71,8 @@ file. Most of the examples in the documentation use this XML syntax. However, as of logback version 0.9.22, configuration files written in - Groovy are also supported. Compared to XML, groovy style - configuration is more intuitive, consistent and have a much + Groovy are also supported. Compared to XML, Groovy-style + configuration is more intuitive, consistent and has a much shorter syntax.

    @@ -83,7 +83,7 @@ logback.groovy.

    -

    We also plan to support configration files written in +

    We also plan to support configuration files written in Scala.

    @@ -129,7 +129,7 @@

    Developers often need to juggle between several logback configuration files targeting different environments such as development, testing and production. These configuration files - have substantial parts in common differing only in a few + have substantial parts in common, differing only in a few places. To avoid duplication, logback supports conditional processing of configuration files with the help of @@ -217,12 +217,12 @@ java.lang.Exception: 99 is invalid at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:417) [jetty-6.1.12.jar:6.1.12] at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230) [jetty-6.1.12.jar:6.1.12] -

    From the above, you can recognize that the applicaiton is using +

    From the above, you can recognize that the application is using Struts version 1.2.9 and was deployed under jetty version 6.1.12. Thus, stack traces will quickly inform the reader about the classes invervening in the exception but also the package and package versions they belong to. When your customers send you a - stack trace, as a developper you will no longer need to ask them + stack trace, as a developer you will no longer need to ask them to send you information about the versions of packages they are using. The information will be part of the stack trace. See "%xThrowable" conversion @@ -245,7 +245,7 @@ java.lang.Exception: 99 is invalid or SizeAndTimeBasedFNATP, you can control the maximum number of archived files. If your - rolling policy calls for monthly rollover and you wish to keep 1 + rolling policy calls for monthly rollover and you wish to keep one year's worth of logs, simply set the maxHistory property to 12. Archived log files older than 12 months will be automatically removed. @@ -260,7 +260,7 @@ java.lang.Exception: 99 is invalid logback distribution, integrates with Servlet containers such as Jetty or Tomcat to provide rich and powerful HTTP-access log functionality. Since logback-access was part of the initial - design, all the logback-classic features you came love are + design, all the logback-classic features you love are available in logback-access as well.

    In summary

    @@ -273,4 +273,4 @@ java.lang.Exception: 99 is invalid - \ No newline at end of file + diff --git a/logback-site/src/site/pages/recipes/index.html b/logback-site/src/site/pages/recipes/index.html index 8c5f5a1..9988ee0 100644 --- a/logback-site/src/site/pages/recipes/index.html +++ b/logback-site/src/site/pages/recipes/index.html @@ -22,12 +22,12 @@

    Real-world inspired logback recipes

    -

    Here is a list of logback-related recipes inpired by +

    Here is a list of logback-related recipes inspired by real-world use cases:

    @@ -41,4 +41,3 @@
    - \ No newline at end of file diff --git a/logback-site/src/site/pages/repos.html b/logback-site/src/site/pages/repos.html index 22f323c..7a1e2e2 100644 --- a/logback-site/src/site/pages/repos.html +++ b/logback-site/src/site/pages/repos.html @@ -26,10 +26,10 @@

    We store the project's source code in a revision control system called Git. Developers have write access to the repository, enabling them to make changes to the source code. Everyone else - has read-access to the repository. Thus, anyone can check out + has read-access to the repository. Thus, anyone can check out the latest development version of the software. Note that the latest - version in the repository may not work as expected. It may even - not compile. If you are looking for a stable release, then + version in the repository may not work as expected. It may not + even compile. If you are looking for a stable release, then download an official distribution.

    diff --git a/logback-site/src/site/pages/setup.html b/logback-site/src/site/pages/setup.html index 2922563..7ec3047 100644 --- a/logback-site/src/site/pages/setup.html +++ b/logback-site/src/site/pages/setup.html @@ -66,7 +66,7 @@

    Please edit the script in order to adapt the LB_HOME variable to match your local environment.

    -

    Please be aware that many examples will launch java classes +

    Please be aware that many examples will launch Java classes along with configuration files. To access these files by using the same commands as written in the documentation, you will need to issue the commands from within the @@ -93,13 +93,13 @@

    Evaluators and more - specifically JaninoEvantEvaluator require + specifically JaninoEventEvaluator require Janino

    The evaluator examples which are mostly based on - JaninoEvantEvaluator require JaninoEventEvaluator require Janino - version 2.5.10 or later. Once you downloaded Janino, you need to + version 2.5.10 or later. Once you have downloaded Janino, you need to place janino.jar on your class path.

    ----------------------------------------------------------------------- Summary of changes: logback-site/src/site/pages/access.html | 10 +- logback-site/src/site/pages/bugreport.html | 2 +- logback-site/src/site/pages/codes.html | 6 +- logback-site/src/site/pages/consolePlugin.html | 33 +++--- logback-site/src/site/pages/demo.html | 102 ++++++++-------- logback-site/src/site/pages/documentation.html | 2 +- logback-site/src/site/pages/download.html | 12 +- logback-site/src/site/pages/faq.html | 14 +- logback-site/src/site/pages/index.html | 2 +- logback-site/src/site/pages/license.html | 10 +- logback-site/src/site/pages/mailinglist.html | 8 +- logback-site/src/site/pages/manual/appenders.html | 90 +++++++------- .../src/site/pages/manual/architecture.html | 28 +++--- .../src/site/pages/manual/configuration.html | 122 ++++++++++---------- logback-site/src/site/pages/manual/encoders.html | 14 +- logback-site/src/site/pages/manual/filters.html | 88 +++++++------- logback-site/src/site/pages/manual/groovy.html | 52 ++++---- logback-site/src/site/pages/manual/index.html | 6 +- .../src/site/pages/manual/introduction.html | 22 ++-- logback-site/src/site/pages/manual/jmxConfig.html | 50 ++++---- logback-site/src/site/pages/manual/layouts.html | 77 ++++++------ .../src/site/pages/manual/loggingSeparation.html | 26 ++-- logback-site/src/site/pages/manual/mdc.html | 10 +- .../src/site/pages/manual/migrationFromLog4j.html | 12 +- logback-site/src/site/pages/manual/onJoran.html | 72 ++++++------ logback-site/src/site/pages/news.html | 6 +- logback-site/src/site/pages/reasonsToSwitch.html | 18 ++-- logback-site/src/site/pages/recipes/index.html | 5 +- logback-site/src/site/pages/repos.html | 6 +- logback-site/src/site/pages/setup.html | 8 +- 30 files changed, 455 insertions(+), 458 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From git-noreply at pixie.qos.ch Tue Dec 21 18:00:14 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Tue, 21 Dec 2010 18:00:14 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-47-gc1ba67d Message-ID: <20101221170015.0619D317156@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via c1ba67d938b0cfb24275fae4f7829d97ee7c96cd (commit) from 4556c00a26f4aaee2d44d9d3fdff642297c32ffa (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=c1ba67d938b0cfb24275fae4f7829d97ee7c96cd http://github.com/ceki/logback/commit/c1ba67d938b0cfb24275fae4f7829d97ee7c96cd commit c1ba67d938b0cfb24275fae4f7829d97ee7c96cd Author: Ceki Gulcu Date: Tue Dec 21 17:58:24 2010 +0100 - merged OptionTokenizer into TokenStream in order to lift the requirement of escaping '}' in options. You can't have multiple tokenizers within the same DSL. diff --git a/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java b/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java index 43590ed..d702bd5 100644 --- a/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java +++ b/logback-access/src/main/java/ch/qos/logback/access/PatternLayout.java @@ -43,6 +43,7 @@ import ch.qos.logback.access.pattern.ServerNameConverter; import ch.qos.logback.access.pattern.StatusCodeConverter; import ch.qos.logback.access.spi.AccessEvent; import ch.qos.logback.core.pattern.PatternLayoutBase; +import ch.qos.logback.core.pattern.parser.Parser; /** *

    @@ -70,6 +71,7 @@ public class PatternLayout extends PatternLayoutBase { public static String COMBINED_PATTERN_NAME = "combined"; static { + defaultConverterMap.putAll(Parser.DEFAULT_COMPOSITE_CONVERTER_MAP); defaultConverterMap.put("a", RemoteIPAddressConverter.class.getName()); defaultConverterMap.put("remoteIP", RemoteIPAddressConverter.class diff --git a/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegate.groovy b/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegate.groovy index c1dfacb..8feb3cd 100644 --- a/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegate.groovy +++ b/logback-classic/src/main/groovy/ch/qos/logback/classic/gaffer/ConfigurationDelegate.groovy @@ -137,7 +137,6 @@ public class ConfigurationDelegate extends ContextAwareBase { appenderDelegate.metaClass."${newName}" = appender.&"$oldName" } } - } void turboFilter(Class clazz, Closure closure = null) { diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java b/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java index 3a6442d..35a8b86 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/PatternLayout.java @@ -40,6 +40,7 @@ import ch.qos.logback.classic.pattern.ThrowableProxyConverter; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.CoreConstants; import ch.qos.logback.core.pattern.PatternLayoutBase; +import ch.qos.logback.core.pattern.parser.Parser; /** *

    @@ -58,6 +59,7 @@ public class PatternLayout extends PatternLayoutBase { public static final Map defaultConverterMap = new HashMap(); static { + defaultConverterMap.putAll(Parser.DEFAULT_COMPOSITE_CONVERTER_MAP); defaultConverterMap.put("d", DateConverter.class.getName()); defaultConverterMap.put("date", DateConverter.class.getName()); diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java index fad905e..34b2ce6 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java @@ -25,6 +25,7 @@ import java.util.List; import ch.qos.logback.core.status.Status; import ch.qos.logback.core.util.StatusPrinter; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import ch.qos.logback.classic.joran.JoranConfigurator; @@ -147,23 +148,6 @@ public class PatternLayoutTest extends AbstractPatternLayoutBaseTest sla = (StringListAppender) root.getAppender("LIST"); + assertNotNull(sla); + assertEquals(1, sla.strList.size()); + assertEquals("And the number is XXXX, expiring on 12/2010", sla.strList.get(0)); + } + } diff --git a/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java b/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java index d654f9b..181da69 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java +++ b/logback-core/src/main/java/ch/qos/logback/core/CoreConstants.java @@ -74,6 +74,14 @@ public class CoreConstants { public static final char LEFT_PARENTHESIS_CHAR = '('; public static final char RIGHT_PARENTHESIS_CHAR = ')'; + public static final char ESCAPE_CHAR = '\\'; + public static final char CURLY_LEFT = '{'; + public static final char CURLY_RIGHT = '}'; + public static final char COMMA_CHAR = ','; + public static final char DOUBLE_QUOTE_CHAR = '"'; + public static final char SINGLE_QUOTE_CHAR = '\''; + + /** * Number of rows before in an HTML table before, * we close the table and create a new one diff --git a/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java b/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java index af16edf..5ee84d0 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/html/HTMLLayoutBase.java @@ -83,7 +83,7 @@ public abstract class HTMLLayoutBase extends LayoutBase { Parser p = new Parser(pattern); p.setContext(getContext()); Node t = p.parse(); - this.head = p.compile(t, getEffectiveConverterMap(), Parser.DEFAULT_COMPOSITE_CONVERTER_MAP); + this.head = p.compile(t, getEffectiveConverterMap()); ConverterUtil.startConverters(this.head); } catch (ScanException ex) { addError("Incorrect pattern found", ex); diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java index e60ee6f..d507887 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/PatternLayoutBase.java @@ -81,7 +81,7 @@ abstract public class PatternLayoutBase extends LayoutBase { p.setContext(getContext()); } Node t = p.parse(); - this.head = p.compile(t, getEffectiveConverterMap(), Parser.DEFAULT_COMPOSITE_CONVERTER_MAP); + this.head = p.compile(t, getEffectiveConverterMap()); if (postCompileProcessor != null) { postCompileProcessor.process(head); } diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java index 9bcb1a6..2f807f7 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Compiler.java @@ -26,12 +26,10 @@ class Compiler extends ContextAwareBase { Converter tail; final Node top; final Map converterMap; - final Map compositeConverterMap; - Compiler(final Node top, final Map converterMap, Map compositeConverterMap) { + Compiler(final Node top, final Map converterMap) { this.top = top; this.converterMap = converterMap; - this.compositeConverterMap = compositeConverterMap; } Converter compile() { @@ -47,7 +45,7 @@ class Compiler extends ContextAwareBase { compositeConverter.setFormattingInfo(cn.getFormatInfo()); compositeConverter.setOptionList(cn.getOptions()); Compiler childCompiler = new Compiler(cn.getChildNode(), - converterMap, compositeConverterMap); + converterMap); childCompiler.setContext(context); Converter childConverter = childCompiler.compile(); compositeConverter.setChildConverter(childConverter); @@ -122,7 +120,7 @@ class Compiler extends ContextAwareBase { @SuppressWarnings("unchecked") CompositeConverter createCompiteConverter(CompositeNode cn) { String keyword = (String) cn.getValue(); - String converterClassStr = (String) compositeConverterMap.get(keyword); + String converterClassStr = (String) converterMap.get(keyword); if (converterClassStr != null) { try { diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java index 369a67f..63f53bf 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/OptionTokenizer.java @@ -20,111 +20,130 @@ import ch.qos.logback.core.pattern.util.AsIsEscapeUtil; import ch.qos.logback.core.pattern.util.IEscapeUtil; import ch.qos.logback.core.pattern.util.RegularEscapeUtil; +import static ch.qos.logback.core.CoreConstants.CURLY_RIGHT; + + +import static ch.qos.logback.core.CoreConstants.ESCAPE_CHAR; +import static ch.qos.logback.core.CoreConstants.COMMA_CHAR; +import static ch.qos.logback.core.CoreConstants.SINGLE_QUOTE_CHAR; +import static ch.qos.logback.core.CoreConstants.DOUBLE_QUOTE_CHAR; + + +import ch.qos.logback.core.pattern.parser.TokenStream.TokenizerState; + public class OptionTokenizer { private final static int EXPECTING_STATE = 0; - private final static int COLLECTING_STATE = 1; + private final static int RAW_COLLECTING_STATE = 1; private final static int QUOTED_COLLECTING_STATE = 2; - private static final char ESCAPE_CHAR = '\\'; - private static final char COMMA_CHAR = ','; - private static final char DOUBLE_QUOTE_CHAR = '"'; - private static final char SINGLE_QUOTE_CHAR = '\''; + final IEscapeUtil escapeUtil; + final TokenStream tokenStream; final String pattern; final int patternLength; - final IEscapeUtil escapeUtil; - + char quoteChar; - int pointer = 0; int state = EXPECTING_STATE; - /** - * This variant is used in tests - * @param pattern - */ - OptionTokenizer(String pattern) { - this(pattern, new AsIsEscapeUtil()); + OptionTokenizer(TokenStream tokenStream) { + this(tokenStream, new AsIsEscapeUtil()); } - - OptionTokenizer(String pattern, IEscapeUtil escapeUtil) { - this.pattern = pattern; - patternLength = pattern.length(); + + OptionTokenizer(TokenStream tokenStream, IEscapeUtil escapeUtil) { + this.tokenStream = tokenStream; + this.pattern = tokenStream.pattern; + this.patternLength = tokenStream.patternLength; this.escapeUtil = escapeUtil; } - List tokenize() throws ScanException { - List tokenList = new ArrayList(); + void tokenize(char firstChar, List tokenList) throws ScanException { StringBuffer buf = new StringBuffer(); + List optionList = new ArrayList(); + char c = firstChar; - while (pointer < patternLength) { - char c = pattern.charAt(pointer); - pointer++; - + while (tokenStream.pointer < patternLength) { switch (state) { - case EXPECTING_STATE: - switch (c) { - case ' ': - case '\t': - case '\r': - case '\n': + case EXPECTING_STATE: + switch (c) { + case ' ': + case '\t': + case '\r': + case '\n': + break; + case COMMA_CHAR: + break; + case SINGLE_QUOTE_CHAR: + case DOUBLE_QUOTE_CHAR: + state = QUOTED_COLLECTING_STATE; + quoteChar = c; + break; + case CURLY_RIGHT: + emitOptionToken(tokenList, optionList); + return; + default: + buf.append(c); + state = RAW_COLLECTING_STATE; + } break; - case COMMA_CHAR: + case RAW_COLLECTING_STATE: + switch (c) { + case COMMA_CHAR: + optionList.add(buf.toString().trim()); + buf.setLength(0); + state = EXPECTING_STATE; + break; + case CURLY_RIGHT: + optionList.add(buf.toString().trim()); + emitOptionToken(tokenList, optionList); + return; + default: + buf.append(c); + } break; - case SINGLE_QUOTE_CHAR: - case DOUBLE_QUOTE_CHAR: - state = QUOTED_COLLECTING_STATE; - quoteChar = c; - break; - default: - buf.append(c); - state = COLLECTING_STATE; - } - break; - case COLLECTING_STATE: - switch (c) { - case COMMA_CHAR: - tokenList.add(buf.toString().trim()); - buf.setLength(0); - state = EXPECTING_STATE; + case QUOTED_COLLECTING_STATE: + if (c == quoteChar) { + optionList.add(buf.toString()); + buf.setLength(0); + state = EXPECTING_STATE; + } else if (c == ESCAPE_CHAR) { + escape(String.valueOf(quoteChar), buf); + } else { + buf.append(c); + } + break; - default: - buf.append(c); - } - break; - case QUOTED_COLLECTING_STATE: - if (c == quoteChar) { - tokenList.add(buf.toString()); - buf.setLength(0); - state = EXPECTING_STATE; - } else if (c == ESCAPE_CHAR) { - escape(String.valueOf(quoteChar), buf); - } else { - buf.append(c); - } - - break; } + + c = pattern.charAt(tokenStream.pointer); + tokenStream.pointer++; } + // EOS - switch (state) { - case EXPECTING_STATE: - break; - case COLLECTING_STATE: - tokenList.add(buf.toString().trim()); - break; - default: - throw new ScanException("Unexpected end of pattern string"); + if (c == CURLY_RIGHT) { + if(state == EXPECTING_STATE) { + emitOptionToken(tokenList, optionList); + } else if(state == RAW_COLLECTING_STATE){ + optionList.add(buf.toString().trim()); + emitOptionToken(tokenList, optionList); + } else { + throw new ScanException("Unexpected end of pattern string in OptionTokenizer"); + } + } else { + throw new ScanException("Unexpected end of pattern string in OptionTokenizer"); } + } - return tokenList; + void emitOptionToken( List tokenList, List optionList) { + tokenList.add(new Token(Token.OPTION, optionList)); + tokenStream.state = TokenizerState.LITERAL_STATE; } void escape(String escapeChars, StringBuffer buf) { - if ((pointer < patternLength)) { - char next = pattern.charAt(pointer++); - escapeUtil.escape(escapeChars, buf, next, pointer); + if ((tokenStream.pointer < patternLength)) { + char next = pattern.charAt(tokenStream.pointer++); + escapeUtil.escape(escapeChars, buf, next, tokenStream.pointer); } } } \ No newline at end of file diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java index dff1bf8..0d30413 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Parser.java @@ -44,13 +44,12 @@ import ch.qos.logback.core.spi.ContextAwareBase; public class Parser extends ContextAwareBase { public final static Map DEFAULT_COMPOSITE_CONVERTER_MAP = new HashMap(); - public final static String REPLACER_CONVERTER_WORD = "replace"; + public final static String REPLACE_CONVERTER_WORD = "replace"; static { DEFAULT_COMPOSITE_CONVERTER_MAP.put(Token.BARE_COMPOSITE_KEYWORD_TOKEN.getValue().toString(), IdentityCompositeConverter.class.getName()); - DEFAULT_COMPOSITE_CONVERTER_MAP.put(REPLACER_CONVERTER_WORD, + DEFAULT_COMPOSITE_CONVERTER_MAP.put(REPLACE_CONVERTER_WORD, ReplacingCompositeConverter.class.getName()); - } final List tokenList; @@ -82,8 +81,8 @@ public class Parser extends ContextAwareBase { * @return * @throws ScanException */ - public Converter compile(final Node top, Map converterMap, Map compositeConverterMap) { - Compiler compiler = new Compiler(top, converterMap, compositeConverterMap); + public Converter compile(final Node top, Map converterMap) { + Compiler compiler = new Compiler(top, converterMap); compiler.setContext(context); //compiler.setStatusManager(statusManager); return compiler.compile(); @@ -176,7 +175,7 @@ public class Parser extends ContextAwareBase { Token ot = getCurentToken(); if (ot != null && ot.getType() == Token.OPTION) { - List optionList = new OptionTokenizer((String) ot.getValue()).tokenize(); + List optionList = (List) ot.getValue(); keywordNode.setOptions(optionList); advanceTokenPointer(); } @@ -202,7 +201,7 @@ public class Parser extends ContextAwareBase { } Token ot = getCurentToken(); if (ot != null && ot.getType() == Token.OPTION) { - List optionList = new OptionTokenizer((String) ot.getValue()).tokenize(); + List optionList = (List) ot.getValue(); compositeNode.setOptions(optionList); advanceTokenPointer(); } diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java index 1e8a385..63ece70 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/Token.java @@ -15,6 +15,7 @@ package ch.qos.logback.core.pattern.parser; class Token { + static final int PERCENT = 37; //static final int LEFT_PARENTHESIS = 40; static final int RIGHT_PARENTHESIS = 41; @@ -22,6 +23,7 @@ class Token { static final int DOT = 46; static final int CURLY_LEFT = 123; static final int CURLY_RIGHT = 125; + static final int LITERAL = 1000; static final int FORMAT_MODIFIER = 1002; static final int SIMPLE_KEYWORD = 1004; diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java index 085947a..c3b3ad5 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/parser/TokenStream.java @@ -17,6 +17,9 @@ import java.util.List; import java.util.ArrayList; import ch.qos.logback.core.CoreConstants; +import static ch.qos.logback.core.CoreConstants.CURLY_LEFT; +import static ch.qos.logback.core.CoreConstants.ESCAPE_CHAR; + import ch.qos.logback.core.pattern.util.IEscapeUtil; import ch.qos.logback.core.pattern.util.RegularEscapeUtil; import ch.qos.logback.core.pattern.util.RestrictedEscapeUtil; @@ -42,15 +45,7 @@ import ch.qos.logback.core.pattern.util.RestrictedEscapeUtil; */ class TokenStream { - private static final char ESCAPE_CHAR = '\\'; - private static final char CURLY_LEFT = '{'; - private static final char CURLY_RIGHT = '}'; - - private static final int LITERAL_STATE = 0; - private static final int FORMAT_MODIFIER_STATE = 1; - private static final int KEYWORD_STATE = 2; - private static final int OPTION_STATE = 3; - private static final int RIGHT_PARENTHESIS_STATE = 4; + enum TokenizerState { LITERAL_STATE, FORMAT_MODIFIER_STATE, KEYWORD_STATE, OPTION_STATE, RIGHT_PARENTHESIS_STATE} final String pattern; final int patternLength; @@ -58,7 +53,7 @@ class TokenStream { final IEscapeUtil optionEscapeUtil = new RestrictedEscapeUtil(); - int state = LITERAL_STATE; + TokenizerState state = TokenizerState.LITERAL_STATE; int pointer = 0; // this variant should be used for testing purposes only @@ -92,7 +87,7 @@ class TokenStream { handleFormatModifierState(c, tokenList, buf); break; case OPTION_STATE: - handleOptionState(c, tokenList, buf); + processOption(c, tokenList, buf); break; case KEYWORD_STATE: handleKeywordState(c, tokenList, buf); @@ -131,40 +126,31 @@ class TokenStream { case CoreConstants.RIGHT_PARENTHESIS_CHAR: break; case CURLY_LEFT: - state = OPTION_STATE; + state = TokenizerState.OPTION_STATE; break; case ESCAPE_CHAR: escape("%{}", buf); - state = LITERAL_STATE; + state = TokenizerState.LITERAL_STATE; break; default: buf.append(c); - state = LITERAL_STATE; + state = TokenizerState.LITERAL_STATE; } } - private void handleOptionState(char c, List tokenList, StringBuffer buf) { - switch (c) { - case CURLY_RIGHT: - addValuedToken(Token.OPTION, buf, tokenList); - state = LITERAL_STATE; - break; - case ESCAPE_CHAR: - optionEscape("}", buf); - break; - default: - buf.append(c); - } + private void processOption(char c, List tokenList, StringBuffer buf) throws ScanException { + OptionTokenizer ot = new OptionTokenizer(this); + ot.tokenize(c, tokenList); } private void handleFormatModifierState(char c, List tokenList, StringBuffer buf) { if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) { addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList); tokenList.add(Token.BARE_COMPOSITE_KEYWORD_TOKEN); - state = LITERAL_STATE; + state = TokenizerState.LITERAL_STATE; } else if (Character.isJavaIdentifierStart(c)) { addValuedToken(Token.FORMAT_MODIFIER, buf, tokenList); - state = KEYWORD_STATE; + state = TokenizerState.KEYWORD_STATE; buf.append(c); } else { buf.append(c); @@ -180,12 +166,12 @@ class TokenStream { case CoreConstants.PERCENT_CHAR: addValuedToken(Token.LITERAL, buf, tokenList); tokenList.add(Token.PERCENT_TOKEN); - state = FORMAT_MODIFIER_STATE; + state = TokenizerState.FORMAT_MODIFIER_STATE; break; case CoreConstants.RIGHT_PARENTHESIS_CHAR: addValuedToken(Token.LITERAL, buf, tokenList); - state = RIGHT_PARENTHESIS_STATE; + state = TokenizerState.RIGHT_PARENTHESIS_STATE; break; default: @@ -199,17 +185,17 @@ class TokenStream { buf.append(c); } else if (c == CURLY_LEFT) { addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList); - state = OPTION_STATE; + state = TokenizerState.OPTION_STATE; } else if (c == CoreConstants.LEFT_PARENTHESIS_CHAR) { addValuedToken(Token.COMPOSITE_KEYWORD, buf, tokenList); - state = LITERAL_STATE; + state = TokenizerState.LITERAL_STATE; } else if (c == CoreConstants.PERCENT_CHAR) { addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList); tokenList.add(Token.PERCENT_TOKEN); - state = FORMAT_MODIFIER_STATE; + state = TokenizerState.FORMAT_MODIFIER_STATE; } else if (c == CoreConstants.RIGHT_PARENTHESIS_CHAR) { addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList); - state = RIGHT_PARENTHESIS_STATE; + state = TokenizerState.RIGHT_PARENTHESIS_STATE; } else { addValuedToken(Token.SIMPLE_KEYWORD, buf, tokenList); if (c == ESCAPE_CHAR) { @@ -220,7 +206,7 @@ class TokenStream { } else { buf.append(c); } - state = LITERAL_STATE; + state = TokenizerState.LITERAL_STATE; } } diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java index be3c8b5..88adfe6 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/FileNamePattern.java @@ -66,7 +66,7 @@ public class FileNamePattern extends ContextAwareBase { Parser p = new Parser(patternForParsing, new AlmostAsIsEscapeUtil()); p.setContext(context); Node t = p.parse(); - this.headTokenConverter = p.compile(t, CONVERTER_MAP, Parser.DEFAULT_COMPOSITE_CONVERTER_MAP); + this.headTokenConverter = p.compile(t, CONVERTER_MAP); } catch (ScanException sce) { addError("Failed to parse pattern \"" + pattern + "\".", sce); diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java index 39bb596..a548a6f 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/CompilerTest.java @@ -39,6 +39,7 @@ public class CompilerTest { @Before public void setUp() { converterMap.put("OTT", Converter123.class.getName()); converterMap.put("hello", ConverterHello.class.getName()); + converterMap.putAll(Parser.DEFAULT_COMPOSITE_CONVERTER_MAP); } @@ -56,7 +57,7 @@ public class CompilerTest { public void testLiteral() throws Exception { Parser p = new Parser("hello"); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("hello", result); } @@ -67,7 +68,7 @@ public class CompilerTest { Parser p = new Parser("abc %hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("abc Hello", result); } @@ -75,7 +76,7 @@ public class CompilerTest { Parser p = new Parser("abc %hello %OTT"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("abc Hello 123", result); } @@ -87,7 +88,7 @@ public class CompilerTest { Parser p = new Parser("abc %7hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("abc Hello", result); } @@ -96,7 +97,7 @@ public class CompilerTest { Parser p = new Parser("abc %-7hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("abc Hello ", result); } @@ -105,7 +106,7 @@ public class CompilerTest { Parser p = new Parser("abc %.3hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("abc llo", result); } @@ -114,7 +115,7 @@ public class CompilerTest { Parser p = new Parser("abc %.-3hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("abc Hel", result); } @@ -123,7 +124,7 @@ public class CompilerTest { Parser p = new Parser("abc %4.5OTT"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("abc 123", result); } @@ -131,7 +132,7 @@ public class CompilerTest { Parser p = new Parser("abc %-4.5OTT"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("abc 123 ", result); } @@ -139,7 +140,7 @@ public class CompilerTest { Parser p = new Parser("abc %3.4hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("abc ello", result); } @@ -147,7 +148,7 @@ public class CompilerTest { Parser p = new Parser("abc %-3.-4hello"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("abc Hell", result); } @@ -168,7 +169,7 @@ public class CompilerTest { Parser p = new Parser("%(ABC %hello)"); p.setContext(c); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); StatusPrinter.print(c); assertEquals("ABC Hello", result); @@ -177,7 +178,7 @@ public class CompilerTest { Parser p = new Parser("%(ABC %hello)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap,DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("ABC Hello", result); } @@ -189,7 +190,7 @@ public class CompilerTest { Parser p = new Parser("xyz %4.10(ABC)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("xyz ABC", result); } @@ -198,7 +199,7 @@ public class CompilerTest { Parser p = new Parser("xyz %-4.10(ABC)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("xyz ABC ", result); } @@ -207,7 +208,7 @@ public class CompilerTest { Parser p = new Parser("xyz %.2(ABC %hello)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("xyz lo", result); } @@ -216,7 +217,7 @@ public class CompilerTest { Parser p = new Parser("xyz %.-2(ABC)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("xyz AB", result); } @@ -225,7 +226,7 @@ public class CompilerTest { Parser p = new Parser("xyz %30.30(ABC %20hello)"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("xyz ABC Hello", result); } @@ -236,7 +237,7 @@ public class CompilerTest { Parser p = new Parser("%unknown"); p.setContext(context); Node t = p.parse(); - p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + p.compile(t, converterMap); StatusChecker chercker = new StatusChecker(context.getStatusManager()); assertTrue(chercker .containsMatch("\\[unknown] is not a valid conversion word")); @@ -248,7 +249,7 @@ public class CompilerTest { Parser p = new Parser("xyz %hello\\_world"); p.setContext(context); Node t = p.parse(); - Converter head = p.compile(t, converterMap, DEFAULT_COMPOSITE_CONVERTER_MAP); + Converter head = p.compile(t, converterMap); String result = write(head, new Object()); assertEquals("xyz Helloworld", result); } diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java index bd23c5a..e8b7e2f 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/OptionTokenizerTest.java @@ -23,117 +23,123 @@ import org.junit.Test; public class OptionTokenizerTest { @Test - public void testEmpty() throws ScanException { - { - List ol = new OptionTokenizer("").tokenize(); - List witness = new ArrayList(); - assertEquals(witness, ol); - } + public void testEmpty() { - { - List ol = new OptionTokenizer(" ").tokenize(); - List witness = new ArrayList(); - assertEquals(witness, ol); - } - } - - @Test - public void testSimple() throws ScanException { - { - List ol = new OptionTokenizer("abc").tokenize(); - List witness = new ArrayList(); - witness.add("abc"); - assertEquals(witness, ol); - } - } - - @Test - public void testSingleQuote() throws ScanException { - { - List ol = new OptionTokenizer("' '").tokenize(); - List witness = new ArrayList(); - witness.add(" "); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("' x\t'").tokenize(); - List witness = new ArrayList(); - witness.add(" x\t"); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("' x\\t'").tokenize(); - List witness = new ArrayList(); - witness.add(" x\\t"); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("' x\\''").tokenize(); - List witness = new ArrayList(); - witness.add(" x\\'"); - assertEquals(witness, ol); - } - } - - - - @Test - public void testDoubleQuote() throws ScanException { - { - List ol = new OptionTokenizer("\" \"").tokenize(); - List witness = new ArrayList(); - witness.add(" "); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("\" x\t\"").tokenize(); - List witness = new ArrayList(); - witness.add(" x\t"); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("\" x\\t\"").tokenize(); - List witness = new ArrayList(); - witness.add(" x\\t"); - assertEquals(witness, ol); - } - - { - List ol = new OptionTokenizer("\" x\\\"\"").tokenize(); - List witness = new ArrayList(); - witness.add(" x\\\""); - assertEquals(witness, ol); - } - } - - @Test - public void testMultiple() throws ScanException { - { - List ol = new OptionTokenizer("a, b").tokenize(); - List witness = new ArrayList(); - witness.add("a"); - witness.add("b"); - assertEquals(witness, ol); - } - { - List ol = new OptionTokenizer("'a', b").tokenize(); - List witness = new ArrayList(); - witness.add("a"); - witness.add("b"); - assertEquals(witness, ol); - } - { - List ol = new OptionTokenizer("'', b").tokenize(); - List witness = new ArrayList(); - witness.add(""); - witness.add("b"); - assertEquals(witness, ol); - } } +// +// @Test +// public void testEmpty() throws ScanException { +// { +// List ol = new OptionTokenizer("").tokenize(); +// List witness = new ArrayList(); +// assertEquals(witness, ol); +// } +// +// { +// List ol = new OptionTokenizer(" ").tokenize(); +// List witness = new ArrayList(); +// assertEquals(witness, ol); +// } +// } +// +// @Test +// public void testSimple() throws ScanException { +// { +// List ol = new OptionTokenizer("abc").tokenize(); +// List witness = new ArrayList(); +// witness.add("abc"); +// assertEquals(witness, ol); +// } +// } +// +// @Test +// public void testSingleQuote() throws ScanException { +// { +// List ol = new OptionTokenizer("' '").tokenize(); +// List witness = new ArrayList(); +// witness.add(" "); +// assertEquals(witness, ol); +// } +// +// { +// List ol = new OptionTokenizer("' x\t'").tokenize(); +// List witness = new ArrayList(); +// witness.add(" x\t"); +// assertEquals(witness, ol); +// } +// +// { +// List ol = new OptionTokenizer("' x\\t'").tokenize(); +// List witness = new ArrayList(); +// witness.add(" x\\t"); +// assertEquals(witness, ol); +// } +// +// { +// List ol = new OptionTokenizer("' x\\''").tokenize(); +// List witness = new ArrayList(); +// witness.add(" x\\'"); +// assertEquals(witness, ol); +// } +// } +// +// +// +// @Test +// public void testDoubleQuote() throws ScanException { +// { +// List ol = new OptionTokenizer("\" \"").tokenize(); +// List witness = new ArrayList(); +// witness.add(" "); +// assertEquals(witness, ol); +// } +// +// { +// List ol = new OptionTokenizer("\" x\t\"").tokenize(); +// List witness = new ArrayList(); +// witness.add(" x\t"); +// assertEquals(witness, ol); +// } +// +// { +// List ol = new OptionTokenizer("\" x\\t\"").tokenize(); +// List witness = new ArrayList(); +// witness.add(" x\\t"); +// assertEquals(witness, ol); +// } +// +// { +// List ol = new OptionTokenizer("\" x\\\"\"").tokenize(); +// List witness = new ArrayList(); +// witness.add(" x\\\""); +// assertEquals(witness, ol); +// } +// } +// +// @Test +// public void testMultiple() throws ScanException { +// { +// List ol = new OptionTokenizer("a, b").tokenize(); +// List witness = new ArrayList(); +// witness.add("a"); +// witness.add("b"); +// assertEquals(witness, ol); +// } +// { +// List ol = new OptionTokenizer("'a', b").tokenize(); +// List witness = new ArrayList(); +// witness.add("a"); +// witness.add("b"); +// assertEquals(witness, ol); +// } +// { +// List ol = new OptionTokenizer("'', b").tokenize(); +// List witness = new ArrayList(); +// witness.add(""); +// witness.add("b"); +// assertEquals(witness, ol); +// } +// } +// } \ No newline at end of file diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java index e220964..58f7f52 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/ParserTest.java @@ -138,7 +138,7 @@ public class ParserTest { } } - + @Test public void testNested() throws Exception { { @@ -203,41 +203,39 @@ public class ParserTest { } @Test - public void testOptions() throws Exception { - { - Parser p = new Parser("%45x{'test '}"); - Node t = p.parse(); - SimpleKeywordNode witness = new SimpleKeywordNode("x"); - witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE)); - List ol = new ArrayList(); - ol.add("test "); - witness.setOptions(ol); - assertEquals(witness, t); - } + public void testOptions0() throws Exception { + Parser p = new Parser("%45x{'test '}"); + Node t = p.parse(); + SimpleKeywordNode witness = new SimpleKeywordNode("x"); + witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE)); + List ol = new ArrayList(); + ol.add("test "); + witness.setOptions(ol); + assertEquals(witness, t); + } - { - Parser p = new Parser("%45x{a, b}"); - Node t = p.parse(); - SimpleKeywordNode witness = new SimpleKeywordNode("x"); - witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE)); - List ol = new ArrayList(); - ol.add("a"); - ol.add("b"); - witness.setOptions(ol); - assertEquals(witness, t); - } + @Test + public void testOptions1() throws Exception { + Parser p = new Parser("%45x{a, b}"); + Node t = p.parse(); + SimpleKeywordNode witness = new SimpleKeywordNode("x"); + witness.setFormatInfo(new FormatInfo(45, Integer.MAX_VALUE)); + List ol = new ArrayList(); + ol.add("a"); + ol.add("b"); + witness.setOptions(ol); + assertEquals(witness, t); } // see http://jira.qos.ch/browse/LBCORE-180 @Test public void keywordGluedToLitteral() throws Exception { - { - Parser p = new Parser("%x{}a"); - Node t = p.parse(); - SimpleKeywordNode witness = new SimpleKeywordNode("x"); - witness.next = new Node(Node.LITERAL, "a"); - assertEquals(witness, t); - } + Parser p = new Parser("%x{}a"); + Node t = p.parse(); + SimpleKeywordNode witness = new SimpleKeywordNode("x"); + witness.setOptions(new ArrayList()); + witness.next = new Node(Node.LITERAL, "a"); + assertEquals(witness, t); } @Test @@ -257,15 +255,15 @@ public class ParserTest { assertEquals(witness, t); } } - + @Test public void empty() { try { - Parser p = new Parser(""); - p.parse(); + Parser p = new Parser(""); + p.parse(); fail(""); - } catch(ScanException e) { - + } catch (ScanException e) { + } } } \ No newline at end of file diff --git a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java index 751f515..f695205 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/pattern/parser/TokenStreamTest.java @@ -108,7 +108,9 @@ public class TokenStreamTest { List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.SIMPLE_KEYWORD, "d")); - witness.add(new Token(Token.OPTION, "1234")); + List ol = new ArrayList(); + ol.add("1234"); + witness.add(new Token(Token.OPTION, ol)); witness.add(new Token(Token.LITERAL, " [")); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.FORMAT_MODIFIER, "34.-67")); @@ -198,7 +200,9 @@ public class TokenStreamTest { List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); - witness.add(new Token(Token.OPTION, "t")); + List ol = new ArrayList(); + ol.add("t"); + witness.add(new Token(Token.OPTION, ol)); assertEquals(witness, tl); } @@ -207,7 +211,10 @@ public class TokenStreamTest { List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); - witness.add(new Token(Token.OPTION, "t,y")); + List ol = new ArrayList(); + ol.add("t"); + ol.add("y"); + witness.add(new Token(Token.OPTION, ol)); assertEquals(witness, tl); } @@ -216,16 +223,21 @@ public class TokenStreamTest { List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); - witness.add(new Token(Token.OPTION, "\"hello world.\", \"12y \"")); + List ol = new ArrayList(); + ol.add("hello world."); + ol.add("12y "); + witness.add(new Token(Token.OPTION, ol)); assertEquals(witness, tl); } { - List tl = new TokenStream("%x{opt\\}}").tokenize(); + List tl = new TokenStream("%x{'opt}'}").tokenize(); List witness = new ArrayList(); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.SIMPLE_KEYWORD, "x")); - witness.add(new Token(Token.OPTION, "opt}")); + List ol = new ArrayList(); + ol.add("opt}"); + witness.add(new Token(Token.OPTION, ol)); assertEquals(witness, tl); } } @@ -239,7 +251,9 @@ public class TokenStreamTest { witness.add(new Token(Token.LITERAL, "hello ")); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.SIMPLE_KEYWORD, "class")); - witness.add(new Token(Token.OPTION, ".4?")); + List ol = new ArrayList(); + ol.add(".4?"); + witness.add(new Token(Token.OPTION, ol)); witness.add(Token.RIGHT_PARENTHESIS_TOKEN); assertEquals(witness, tl); } @@ -258,7 +272,9 @@ public class TokenStreamTest { witness.add(new Token(Token.LITERAL, "hello ")); witness.add(Token.PERCENT_TOKEN); witness.add(new Token(Token.SIMPLE_KEYWORD, "class")); - witness.add(new Token(Token.OPTION, ".4?")); + List ol = new ArrayList(); + ol.add(".4?"); + witness.add(new Token(Token.OPTION, ol)); witness.add(Token.RIGHT_PARENTHESIS_TOKEN); assertEquals(witness, tl); } @@ -366,6 +382,7 @@ public class TokenStreamTest { assertEquals(witness, tl); } } + @Test public void compositedKeywordFollowedByOptions() throws ScanException { { @@ -376,7 +393,9 @@ public class TokenStreamTest { witness.add(new Token(Token.COMPOSITE_KEYWORD, "d")); witness.add(new Token(Token.LITERAL, "A")); witness.add(Token.RIGHT_PARENTHESIS_TOKEN); - witness.add(new Token(Token.OPTION, "o")); + List ol = new ArrayList(); + ol.add("o"); + witness.add(new Token(Token.OPTION, ol)); assertEquals(witness, tl); } diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java index 02bc719..759a2fa 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithArchiveRemovalTest.java @@ -213,7 +213,7 @@ public class TimeBasedRollingWithArchiveRemovalTest { void waitForCompression(TimeBasedRollingPolicy tbrp) throws InterruptedException, ExecutionException, TimeoutException { if (tbrp.future != null && !tbrp.future.isDone()) { - tbrp.future.get(200, TimeUnit.MILLISECONDS); + tbrp.future.get(800, TimeUnit.MILLISECONDS); } } diff --git a/logback-site/src/site/pages/manual/appenders.html b/logback-site/src/site/pages/manual/appenders.html index 6e87946..c527c4f 100644 --- a/logback-site/src/site/pages/manual/appenders.html +++ b/logback-site/src/site/pages/manual/appenders.html @@ -1693,10 +1693,12 @@ public interface TriggeringPolicy<E> extends LifeCycle {

    - + - + diff --git a/logback-site/src/site/pages/manual/layouts.html b/logback-site/src/site/pages/manual/layouts.html index 3cb8333..6399a4b 100644 --- a/logback-site/src/site/pages/manual/layouts.html +++ b/logback-site/src/site/pages/manual/layouts.html @@ -999,8 +999,28 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38) omitted, the returned value will be "Property_HAS_NO_KEY", expliciting the error condition.

    -

    + +

    + + + + + @@ -1208,12 +1228,10 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38)

    Conversion word options

    -

    - A conversion specifier can be followed by options. The are - always declared between braces. We have already seen some of the - possibilities offered by options, for instance in conjunction - with the MDC conversion specifier, as in: - %mdc{someKey}. +

    A conversion specifier can be followed by options. The are + always declared between braces. We have already seen some of the + possibilities offered by options, for instance in conjunction with + the MDC conversion specifier, as in: %mdc{someKey}.

    A conversion specifier might have more than one option. For @@ -1221,14 +1239,24 @@ Caller+2 at mainPackage.ConfigTester.main(ConfigTester.java:38) which will be covered soon, may add evaluator names to the option list, as shown below:

    -
    -  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    -    <layout class="ch.qos.logback.classic.PatternLayout"> 
    -      <param name="Pattern" value="%-4relative [%thread] %-5level - %msg%n \
    -        %caller{2, DISP_CALLER_EVAL, OTHER_EVAL_NAME, THIRD_EVAL_NAME}" /> 
    -    </layout>
    -  </appender>
    +
    <pattern>%-4relative [%thread] %-5level - %msg%n \
    +  %caller{2, DISP_CALLER_EVAL, OTHER_EVAL_NAME, THIRD_EVAL_NAME}</pattern>
    +

    If the option includes special characters such as a braces, spaces or + commas, you can enclose it between single or double quotes. For + example, consider the next pattern.

    + +
    <pattern>%-5level - %replace(%msg){'\d{14,16}', 'XXXX'}%n</pattern>
    + + +

    We pass the options \d{16} and XXXX + to the replace conversion word. It replaces any + sequence of 14, 15 or 16 digits contained in the message with XXXX + effectively obfuscating credit card numbers. Note that "\d" which + is a shorthand for a single digit in regular expressions. The + "{14,16\}" is interpreted as "{14, 16}", that is, repeat the + previous item at least 14 but at most 16 times. +

    Parentheses are special

    diff --git a/logback-site/src/site/pages/news.html b/logback-site/src/site/pages/news.html index dadd9f7..55138ef 100644 --- a/logback-site/src/site/pages/news.html +++ b/logback-site/src/site/pages/news.html @@ -30,6 +30,13 @@

    xxx, 2010 - Release of version 0.9.27

    +

    PatternLayout now supports compound conversion + words of which "%replace" is one example. +

    + +

    The to option of SMTPAppender now admits a + pattern and is evaluated dynamically.

    TeeServletInputStream no longer chokes on input over 8K in size. This fixes This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via 2d5659a6ad57e8daf536f6263a274d1e0bc430ff (commit) from c1ba67d938b0cfb24275fae4f7829d97ee7c96cd (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=2d5659a6ad57e8daf536f6263a274d1e0bc430ff http://github.com/ceki/logback/commit/2d5659a6ad57e8daf536f6263a274d1e0bc430ff commit 2d5659a6ad57e8daf536f6263a274d1e0bc430ff Author: Ceki Gulcu Date: Tue Dec 21 19:08:15 2010 +0100 ongoing docs edits diff --git a/logback-site/src/site/pages/recipes/emailPerTransaction.html b/logback-site/src/site/pages/recipes/emailPerTransaction.html index 87a7861..68d9837 100644 --- a/logback-site/src/site/pages/recipes/emailPerTransaction.html +++ b/logback-site/src/site/pages/recipes/emailPerTransaction.html @@ -154,21 +154,23 @@ public class PrimeAction extends Action { </configuration> - -

    Transaction isolation

    -

    -

    +

    Transaction isolation

    + +

    While the previous configuration file will trigger an outgoing + email message whenenver an event is marked with "SMTP_TRIGGER", the + contents of the message will lump together messag +

    <configuration scan="true" scanPeriod="3 seconds">
     
    -  <!-- always a good idea to have an OnConsoleStatusListener -->
    +  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
     
       <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
    -    <SMTPHost>NAME_OF_SMTP_HOST</SMTPHost>
    -    <To>com</To>
    -    <From></From>
    +    <smtpHost>NAME_OF_SMTP_HOST</smtpHost>
    +    <to>name at some.smtp.host</to>
    +    <from>testing at ...</from>
         <layout class="ch.qos.logback.classic.html.HTMLLayout">
            <pattern>%date%level%logger{24}%msg</pattern>
         </layout>
    @@ -193,11 +195,10 @@ public class PrimeAction extends Action {
           
     
       

    Selective triggering & Transaction isolation

    -
    <configuration scan="true" scanPeriod="3 seconds">
     
    -  <!-- always a good idea to have an OnConsoleStatusListener -->
    +  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
     
       <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
         <SMTPHost>NAME_OF_SMTP_HOST</SMTPHost>
    
    -----------------------------------------------------------------------
    
    Summary of changes:
     .../site/pages/recipes/emailPerTransaction.html    |   21 ++++++++++---------
     1 files changed, 11 insertions(+), 10 deletions(-)
    
    
    hooks/post-receive
    -- 
    Logback: the generic, reliable, fast and flexible logging framework.
    
    From git-noreply at pixie.qos.ch  Tue Dec 21 20:15:13 2010
    From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo)
    Date: Tue, 21 Dec 2010 20:15:13 +0100 (CET)
    Subject: [logback-dev] [GIT] Logback: the generic, reliable,
    	fast and flexible logging framework. branch, master,
    	updated. v_0.9.25-49-gf1db404
    Message-ID: <20101221191513.76572317292@pixie.qos.ch>
    
    This is an automated email from the git hooks/post-receive script. It was
    generated because a ref change was pushed to the repository containing
    the project "Logback: the generic, reliable, fast and flexible logging framework.".
    
    The branch, master has been updated
           via  f1db4042a372249765b52d6b430b7f33dcbf410b (commit)
          from  2d5659a6ad57e8daf536f6263a274d1e0bc430ff (commit)
    
    Those revisions listed above that are new to this repository have
    not appeared on any other notification email; so we list those
    revisions in full, below.
    
    - Log -----------------------------------------------------------------
    http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=f1db4042a372249765b52d6b430b7f33dcbf410b
    http://github.com/ceki/logback/commit/f1db4042a372249765b52d6b430b7f33dcbf410b
    
    commit f1db4042a372249765b52d6b430b7f33dcbf410b
    Author: Ceki Gulcu 
    Date:   Tue Dec 21 20:12:54 2010 +0100
    
        add missing file
    
    diff --git a/logback-classic/src/test/input/joran/pattern/replace0.xml b/logback-classic/src/test/input/joran/pattern/replace0.xml
    new file mode 100644
    index 0000000..dbdfd4a
    --- /dev/null
    +++ b/logback-classic/src/test/input/joran/pattern/replace0.xml
    @@ -0,0 +1,15 @@
    +
    +
    +  
    +
    +  
    +    
    +      %replace(%msg){'\d{14,16}', 'XXXX'}
    +    
    +  
    +
    +  
    +    
    +  
    +
    \ No newline at end of file
    diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
    index 55ef3ff..6542a44 100644
    --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
    +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java
    @@ -44,7 +44,6 @@ public class ReplacingCompositeConverter extends CompositeConverter {
         //.matcher(this).replaceAll(replacement);
     
         replacement = optionList.get(1);
    -    System.out.println("regex="+regex);
         super.start();
       }
     
    diff --git a/logback-site/src/site/pages/recipes/emailPerTransaction.html b/logback-site/src/site/pages/recipes/emailPerTransaction.html
    index 68d9837..a13a167 100644
    --- a/logback-site/src/site/pages/recipes/emailPerTransaction.html
    +++ b/logback-site/src/site/pages/recipes/emailPerTransaction.html
    @@ -136,6 +136,7 @@ public class PrimeAction extends Action {
         <SMTPHost>NAME_OF_SMTP_HOST</SMTPHost>
         <to>...</to>                                         
         <from>...</from>
    +    <subject>Prime - %mdc{number}</subject>
         <layout class="ch.qos.logback.classic.html.HTMLLayout">
           <pattern>%date%level%logger{24}%msg</pattern>
         </layout>
    @@ -159,7 +160,11 @@ public class PrimeAction extends Action {
     
        

    While the previous configuration file will trigger an outgoing email message whenenver an event is marked with "SMTP_TRIGGER", the - contents of the message will lump together messag + contents of the message will contain events generated by different + transactions. With a little effort, we can actually seperate events + belonging to different transactions so that the outgoing email + triggeed at the end of the transaction contains logs from that + transaction and only that one.

    @@ -171,6 +176,7 @@ public class PrimeAction extends Action { <smtpHost>NAME_OF_SMTP_HOST</smtpHost> <to>name at some.smtp.host</to> <from>testing at ...</from> + <subject>Prime - %mdc{number}</subject> <layout class="ch.qos.logback.classic.html.HTMLLayout"> <pattern>%date%level%logger{24}%msg</pattern> </layout> @@ -202,8 +208,10 @@ public class PrimeAction extends Action { <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender"> <SMTPHost>NAME_OF_SMTP_HOST</SMTPHost> - <To>com</To> - <From></From> + <to>com</to> + <from></from> + <subject>Prime - %mdc{number}</subject> + <layout class="ch.qos.logback.classic.html.HTMLLayout"> <pattern>%date%level%logger{24}%msg</pattern> </layout> ----------------------------------------------------------------------- Summary of changes: .../patternLayout0.xml => pattern/replace0.xml} | 2 +- .../core/pattern/ReplacingCompositeConverter.java | 1 - .../site/pages/recipes/emailPerTransaction.html | 14 +++++++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) copy logback-classic/src/test/input/joran/{conversionRule/patternLayout0.xml => pattern/replace0.xml} (82%) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From git-noreply at pixie.qos.ch Tue Dec 21 22:58:58 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Tue, 21 Dec 2010 22:58:58 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-50-g072bbae Message-ID: <20101221215858.9A0A131729B@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via 072bbaef8e8d0508e1660cc5d49b3e8c7112e881 (commit) from f1db4042a372249765b52d6b430b7f33dcbf410b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=072bbaef8e8d0508e1660cc5d49b3e8c7112e881 http://github.com/ceki/logback/commit/072bbaef8e8d0508e1660cc5d49b3e8c7112e881 commit 072bbaef8e8d0508e1660cc5d49b3e8c7112e881 Author: Ceki Gulcu Date: Tue Dec 21 22:56:38 2010 +0100 ongoing edits diff --git a/logback-site/src/site/resources/recipes/images/factorEmail0.png b/logback-site/src/site/resources/recipes/images/factorEmail0.png new file mode 100644 index 0000000..0680367 Binary files /dev/null and b/logback-site/src/site/resources/recipes/images/factorEmail0.png differ ----------------------------------------------------------------------- Summary of changes: .../site/resources/recipes/images/factorEmail0.png | Bin 0 -> 51648 bytes 1 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 logback-site/src/site/resources/recipes/images/factorEmail0.png hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From git-noreply at pixie.qos.ch Tue Dec 21 23:01:17 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Tue, 21 Dec 2010 23:01:17 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-51-g20c3ef5 Message-ID: <20101221220118.0B9DF3172BC@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via 20c3ef5ec9336719396f67866630e3a5807afa34 (commit) from 072bbaef8e8d0508e1660cc5d49b3e8c7112e881 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=20c3ef5ec9336719396f67866630e3a5807afa34 http://github.com/ceki/logback/commit/20c3ef5ec9336719396f67866630e3a5807afa34 commit 20c3ef5ec9336719396f67866630e3a5807afa34 Author: Ceki Gulcu Date: Tue Dec 21 22:58:57 2010 +0100 more edits diff --git a/logback-site/src/site/pages/recipes/emailPerTransaction.html b/logback-site/src/site/pages/recipes/emailPerTransaction.html index a13a167..9573605 100644 --- a/logback-site/src/site/pages/recipes/emailPerTransaction.html +++ b/logback-site/src/site/pages/recipes/emailPerTransaction.html @@ -133,10 +133,10 @@ public class PrimeAction extends Action { <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" /> <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender"> - <SMTPHost>NAME_OF_SMTP_HOST</SMTPHost> + <smtpHost>NAME_OF_SMTP_HOST</smtpHost> <to>...</to> <from>...</from> - <subject>Prime - %mdc{number}</subject> + <subject>Prime - %mdc{number} by %mdc{userid} </subject> <layout class="ch.qos.logback.classic.html.HTMLLayout"> <pattern>%date%level%logger{24}%msg</pattern> </layout> @@ -164,9 +164,50 @@ public class PrimeAction extends Action { transactions. With a little effort, we can actually seperate events belonging to different transactions so that the outgoing email triggeed at the end of the transaction contains logs from that - transaction and only that one. + transaction and only that transaction.

    +

    To isolate a given transaction, there must first be a way to + distinguish it from other transactions. Typically this would be + accomplished by putting the unique identifier of the transaction + into the the MDC. +

    + +
    String transactionId = ...; // extract id from transaction 
    +MDC.put("txId", transactionId); 
    + +

    In the UserServletFilter + class, this is done by retreiving the id of the session and putting + it into the MDC under the key "txId".

    + + +
    public class UserServletFilter implements Filter {
    +
    +   public void doFilter(ServletRequest request, ServletResponse response,
    +                       FilterChain chain) throws IOException, ServletException {
    +
    +    HttpServletRequest req = (HttpServletRequest) request;
    +    HttpSession session = req.getSession();
    +    MDC.put("txId", session.getId());
    +    ...
    +    try {
    +      // invoke subsequent filters
    +      chain.doFilter(request, response);
    +    } finally {
    +      // always clear the MDC at the end of the request
    +      MDC.clear();
    +    }
    +  }
    +}
    + + +

    By setting an appropriate discriminator in SMTPAppender, you can + can scatter incoming events into different buffers according to the + value returned by the discriminator. Given that each request session + is placed under the MDC key "txId", we can use an MDC-based + discriminator to isolate the logs generated by each transaction. +

    <configuration scan="true" scanPeriod="3 seconds">
     
    @@ -174,33 +215,73 @@ public class PrimeAction extends Action {
     
       <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
         <smtpHost>NAME_OF_SMTP_HOST</smtpHost>
    +    <to>...</to>                                         
    +    <from>...</from>
    +
    +    <smtpHost>NAME_OF_SMTP_HOST</smtpHost>
         <to>name at some.smtp.host</to>
         <from>testing at ...</from>
    -    <subject>Prime - %mdc{number}</subject>
    +    <subject>Prime - %mdc{number} by %mdc{userid} </subject>
         <layout class="ch.qos.logback.classic.html.HTMLLayout">
            <pattern>%date%level%logger{24}%msg</pattern>
         </layout>
     
    -    <discriminator class="ch.qos.logback.classic.sift.MDCBasedDiscriminator">
    -      <key>uuid</key>
    -      <defaultValue>default</defaultValue>
    -    </discriminator>
    -
         <evaluator class="ch.qos.logback.classic.boolex.JaninoEventEvaluator">
           <expression>
             marker != null && marker.contains("SMTP_TRIGGER") 
           </expression>
         </evaluator>
     
    -    <discriminator class="ch.qos.logback.classic.sift.MDCBasedDiscriminator">
    -      <key>uuid</key>
    -      <defaultValue>default</defaultValue>
    -    </discriminator>
    +    <discriminator class="ch.qos.logback.classic.sift.MDCBasedDiscriminator">
    +      <key>txId</key>
    +      <defaultValue>default</defaultValue>
    +    </discriminator>
     
       </appender>  
    + +

    After starting the logback-demo web-application with the above + configuration file (with smtpHost and + to options adapted for my environment) + on localhost and then visiting the Prime + number page to factoize the number 123, I received the + following email: +

    + + selective email0 +

    Note that the above email contains the logs generated by the + factorization of the number 123, without log pollution from any + other "transaction". +

    -

    Selective triggering & Transaction isolation

    +

    Selective triggering & recipient addressing with transaction isolation

    + +

    In a real world scenario, receiving isolated transactions is not + enough. You would need to trigger outgoing emails only for certain + users, typically QA engineers such as Dave and Carol. Moreover, you + would want the emails generated by transaction made by Carol to + Carol's mailbox and those generated by Dave to Dave's mailbox.

    + +

    Selective triggering and addressing are two distinct + problems. Depending on the exact circumstances, there are many ways + of tackling these two issues. However, for the sake of simplicity, + let us assume that the SMTP server at Fooware.com accepts address + tags. Such an SMTP server treats an incoming message sent to + username+xyz at fooware.com as if it were addressed to + username at fooware.com, effectively stripping the +xyz part.

    + +

    Let us further assume that we can somehow extract the email + address of the user from the contents of her transaction, via a + database lookup or perhaps some other means. The extracted email + addressed is placed into the MDC under the key "txEmail". +

    + +

    Upon a logging event marked as SMTP_TRIGGER, the following + confugration file will trigger an email message addressed to the + value of "%mdc{txEmail}" but only if it contains the string "+log". +

    <configuration scan="true" scanPeriod="3 seconds">
     
    @@ -208,7 +289,7 @@ public class PrimeAction extends Action {
     
       <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
         <SMTPHost>NAME_OF_SMTP_HOST</SMTPHost>
    -    <to>com</to>
    +    <to>%mdc{txEmail}</to>
         <from></from>
         <subject>Prime - %mdc{number}</subject>
     
    @@ -223,9 +304,9 @@ public class PrimeAction extends Action {
     
         <evaluator class="ch.qos.logback.classic.boolex.JaninoEventEvaluator">
           <expression>
    -        (mdc != null && mdc.get("txUser") != null && 
    -             ((String) mdc.get("txUser")).contains("Mickey") )
    -        &&
    +        (mdc != null &amp;&amp; mdc.get("txEmail") != null &amp;&amp; 
    +            ((String) mdc.get("txEmail")).contains("+log") )
    +        &amp;&amp;
             (marker != null  && marker.contains("SMTP_TRIGGER") )
           </expression>
         </evaluator>
    
    -----------------------------------------------------------------------
    
    Summary of changes:
     .../site/pages/recipes/emailPerTransaction.html    |  117 +++++++++++++++++---
     1 files changed, 99 insertions(+), 18 deletions(-)
    
    
    hooks/post-receive
    -- 
    Logback: the generic, reliable, fast and flexible logging framework.
    
    From git-noreply at pixie.qos.ch  Wed Dec 22 18:13:07 2010
    From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo)
    Date: Wed, 22 Dec 2010 18:13:07 +0100 (CET)
    Subject: [logback-dev] [GIT] Logback: the generic, reliable,
    	fast and flexible logging framework. branch, master,
    	updated. v_0.9.25-52-g8f3f521
    Message-ID: <20101222171307.A55F3317300@pixie.qos.ch>
    
    This is an automated email from the git hooks/post-receive script. It was
    generated because a ref change was pushed to the repository containing
    the project "Logback: the generic, reliable, fast and flexible logging framework.".
    
    The branch, master has been updated
           via  8f3f52105b1f95909cb48be721fe3046473b2a4b (commit)
          from  20c3ef5ec9336719396f67866630e3a5807afa34 (commit)
    
    Those revisions listed above that are new to this repository have
    not appeared on any other notification email; so we list those
    revisions in full, below.
    
    - Log -----------------------------------------------------------------
    http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=8f3f52105b1f95909cb48be721fe3046473b2a4b
    http://github.com/ceki/logback/commit/8f3f52105b1f95909cb48be721fe3046473b2a4b
    
    commit 8f3f52105b1f95909cb48be721fe3046473b2a4b
    Author: Ceki Gulcu 
    Date:   Wed Dec 22 18:12:51 2010 +0100
    
        - Improved testing of CyclicBufferTracker. Added support for immediate
        removal of buffer if requested by the user.
    
    diff --git a/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java b/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java
    index 4584e4f..7b1d60c 100644
    --- a/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java
    +++ b/logback-access/src/main/java/ch/qos/logback/access/net/SMTPAppender.java
    @@ -63,7 +63,7 @@ public class SMTPAppender extends SMTPAppenderBase {
       protected void fillBuffer(CyclicBuffer cb, StringBuffer sbuf) {
         int len = cb.length();
         for (int i = 0; i < len; i++) {
    -      // sbuf.append(MimeUtility.encodeText(layout.format(cb.get())));
    +      // sbuf.append(MimeUtility.encodeText(layout.format(cb.getOrCreate())));
           AccessEvent event = (AccessEvent) cb.get();
           sbuf.append(layout.doLayout(event));
         }
    @@ -86,5 +86,8 @@ public class SMTPAppender extends SMTPAppenderBase {
         return pl;
       }
     
    +  protected boolean isEventMarkedForBufferRemoval(AccessEvent eventObject) {
    +    return false;
    +  }
     
     }
    diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java b/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java
    index 193a31d..2972d2d 100644
    --- a/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java
    +++ b/logback-classic/src/main/java/ch/qos/logback/classic/ClassicConstants.java
    @@ -13,6 +13,9 @@
      */
     package ch.qos.logback.classic;
     
    +import org.slf4j.Marker;
    +import org.slf4j.MarkerFactory;
    +
     public class ClassicConstants {
       static public final String USER_MDC_KEY = "user";
     
    @@ -41,4 +44,6 @@ public class ClassicConstants {
       public final static String REQUEST_X_FORWARDED_FOR = "req.xForwardedFor";
     
       public final static String GAFFER_CONFIGURATOR_FQCN = "ch.qos.logback.classic.gaffer.GafferConfigurator";
    +
    +  public final static Marker FINALIZE_SESSION_MARKER = MarkerFactory.getMarker("FINALIZE_SESSION");
     }
    diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java
    index 262bd91..faa1580 100644
    --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java
    +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/SMTPAppender.java
    @@ -13,6 +13,7 @@
      */
     package ch.qos.logback.classic.net;
     
    +import ch.qos.logback.classic.ClassicConstants;
     import ch.qos.logback.classic.PatternLayout;
     import ch.qos.logback.classic.boolex.OnErrorEvaluator;
     import ch.qos.logback.classic.spi.ILoggingEvent;
    @@ -20,6 +21,7 @@ import ch.qos.logback.core.Layout;
     import ch.qos.logback.core.boolex.EventEvaluator;
     import ch.qos.logback.core.helpers.CyclicBuffer;
     import ch.qos.logback.core.net.SMTPAppenderBase;
    +import org.slf4j.Marker;
     
     /**
      * Send an e-mail when a specific logging event occurs, typically on errors or
    @@ -86,6 +88,15 @@ public class SMTPAppender extends SMTPAppenderBase {
         }
       }
     
    +  protected boolean isEventMarkedForBufferRemoval(ILoggingEvent eventObject) {
    +    Marker marker = eventObject.getMarker();
    +    if(marker == null)
    +      return false;
    +
    +    return marker.contains(ClassicConstants.FINALIZE_SESSION_MARKER);
    +  }
    +
    +
       @Override
       protected Layout makeSubjectLayout(String subjectStr) {
         if(subjectStr == null) {
    @@ -102,6 +113,7 @@ public class SMTPAppender extends SMTPAppenderBase {
         return pl;
       }
     
    +
       protected PatternLayout makeNewToPatternLayout(String toPattern) {
         PatternLayout pl = new PatternLayout();
         pl.setPattern(toPattern+"%nopex");
    diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java
    index 53bbc0c..abb5102 100644
    --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java
    +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/DilutedSMTPAppenderTest.java
    @@ -52,7 +52,7 @@ public class DilutedSMTPAppenderTest {
         appender.addTo("sebastien.nospam at qos.ch");
         appender.start();
         cbTracker = appender.getCyclicBufferTracker();
    -    cb = cbTracker.get("", 0);
    +    cb = cbTracker.getOrCreate("", 0);
     
       }
     
    diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java
    index 01f9dbe..a835638 100644
    --- a/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java
    +++ b/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java
    @@ -175,7 +175,7 @@ public abstract class SMTPAppenderBase extends AppenderBase {
     
         String key = discriminator.getDiscriminatingValue(eventObject);
         long now = System.currentTimeMillis();
    -    CyclicBuffer cb = cbTracker.get(key, now);
    +    CyclicBuffer cb = cbTracker.getOrCreate(key, now);
         subAppend(cb, eventObject);
     
         try {
    @@ -188,7 +188,16 @@ public abstract class SMTPAppenderBase extends AppenderBase {
             addError("SMTPAppender's EventEvaluator threw an Exception-", ex);
           }
         }
    +
    +
    +    if(isEventMarkedForBufferRemoval(eventObject)) {
    +      cbTracker.removeBuffer(key);
    +    }
    +
         cbTracker.clearStaleBuffers(now);
    +
    +
    +
         if (lastTrackerStatusPrint + delayBetweenStatusMessages < now) {
           addInfo("SMTPAppender [" + name + "] is tracking [" + cbTracker.size() + "] buffers");
           lastTrackerStatusPrint = now;
    @@ -199,6 +208,8 @@ public abstract class SMTPAppenderBase extends AppenderBase {
         }
       }
     
    +  abstract protected boolean isEventMarkedForBufferRemoval(E eventObject);
    +
       abstract protected void subAppend(CyclicBuffer cb, E eventObject);
     
       /**
    diff --git a/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicyBase.java b/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicyBase.java
    index d5d4129..5328db7 100644
    --- a/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicyBase.java
    +++ b/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedFileNamingAndTriggeringPolicyBase.java
    @@ -30,9 +30,7 @@ abstract public class TimeBasedFileNamingAndTriggeringPolicyBase extends
       protected String elapsedPeriodsFileName;
       protected RollingCalendar rc;
     
    -  protected long currentTime;
    -  // indicate whether the time has been forced or not
    -  protected boolean isTimeForced = false;
    +  protected long currentTime = -1;
       protected Date dateInCurrentPeriod = null;
     
       protected long nextCheck;
    @@ -102,12 +100,11 @@ abstract public class TimeBasedFileNamingAndTriggeringPolicyBase extends
     
       public void setCurrentTime(long timeInMillis) {
         currentTime = timeInMillis;
    -    isTimeForced = true;
       }
     
       public long getCurrentTime() {
         // if time is forced return the time set by user
    -    if (isTimeForced) {
    +    if (currentTime >= 0) {
           return currentTime;
         } else {
           return System.currentTimeMillis();
    diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java b/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java
    index 4f1ab45..0c9fe80 100644
    --- a/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java
    +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java
    @@ -54,7 +54,12 @@ public interface CyclicBufferTracker {
        * @param timestamp
        * @return
        */
    -  CyclicBuffer get(String key, long timestamp);
    +  CyclicBuffer getOrCreate(String key, long timestamp);
    +
    +  /**
    +   * Remove a cyclic buffer identified by its key.
    +   */
    +  void removeBuffer(String key);
     
       /**
        * Clear (and detach) buffers which are stale.
    diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTrackerImpl.java b/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTrackerImpl.java
    index a32a934..be788b1 100644
    --- a/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTrackerImpl.java
    +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTrackerImpl.java
    @@ -13,7 +13,6 @@
      */
     package ch.qos.logback.core.spi;
     
    -import ch.qos.logback.core.Appender;
     import ch.qos.logback.core.CoreConstants;
     import ch.qos.logback.core.helpers.CyclicBuffer;
     
    @@ -65,7 +64,7 @@ public class CyclicBufferTrackerImpl implements CyclicBufferTracker {
         this.maxNumBuffers = maxNumBuffers;
       }
     
    -  public CyclicBuffer get(String key, long timestamp) {
    +  public CyclicBuffer getOrCreate(String key, long timestamp) {
         Entry existing = map.get(key);
         if (existing == null) {
           CyclicBuffer cb = processNewEntry(key, timestamp);
    @@ -77,12 +76,25 @@ public class CyclicBufferTrackerImpl implements CyclicBufferTracker {
         }
       }
     
    +  public void removeBuffer(String key) {
    +    Entry existing = map.get(key);
    +    if (existing != null) {
    +      bufferCount--;
    +      map.remove(key);
    +      unlink(existing);
    +      CyclicBuffer cb = existing.value;
    +      if(cb != null) {
    +        cb.clear();
    +      }
    +    }
    +  }
    +
       private CyclicBuffer processNewEntry(String key, long timestamp) {
         CyclicBuffer cb = new CyclicBuffer(bufferSize);
         Entry entry = new Entry(key, cb, timestamp);
         map.put(key, entry);
         bufferCount++;
    -    rearrangeTailLinks(entry);
    +    linkBeforeTail(entry);
         if (bufferCount >= maxNumBuffers) {
           removeHead();
         }
    @@ -101,11 +113,11 @@ public class CyclicBufferTrackerImpl implements CyclicBufferTracker {
       }
     
       private void moveToTail(Entry e) {
    -    rearrangePreexistingLinks(e);
    -    rearrangeTailLinks(e);
    +    unlink(e);
    +    linkBeforeTail(e);
       }
     
    -  private void rearrangePreexistingLinks(Entry e) {
    +  private void unlink(Entry e) {
         if (e.prev != null) {
           e.prev.next = e.next;
         }
    @@ -125,8 +137,6 @@ public class CyclicBufferTrackerImpl implements CyclicBufferTracker {
         lastCheck = now;
     
         while (head.value != null && isEntryStale(head, now)) {
    -      CyclicBuffer cb = head.value;
    -      cb.clear();
           removeHead();
         }
       }
    @@ -149,7 +159,7 @@ public class CyclicBufferTrackerImpl implements CyclicBufferTracker {
         return result;
       }
     
    -  private void rearrangeTailLinks(Entry e) {
    +  private void linkBeforeTail(Entry e) {
         if (head == tail) {
           head = e;
         }
    diff --git a/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTrackerImplTest.java b/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTrackerImplTest.java
    index 6b9ee28..2b64b88 100644
    --- a/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTrackerImplTest.java
    +++ b/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTrackerImplTest.java
    @@ -22,25 +22,45 @@ public class CyclicBufferTrackerImplTest {
         long now = 3000;
         tracker.clearStaleBuffers(now);
         assertEquals(0, tracker.keyList().size());
    +    assertEquals(0, tracker.bufferCount);
       }
     
    -    @Test
    +  @Test
       public void empty1() {
         long now = 3000;
    -    assertNotNull(tracker.get(key, now++));
    -    now += CyclicBufferTracker.THRESHOLD+1000;
    +    assertNotNull(tracker.getOrCreate(key, now++));
    +    now += CyclicBufferTracker.THRESHOLD + 1000;
         tracker.clearStaleBuffers(now);
         assertEquals(0, tracker.keyList().size());
    -    assertNotNull(tracker.get(key, now++));
    +    assertEquals(0, tracker.bufferCount);
    +
    +    assertNotNull(tracker.getOrCreate(key, now++));
       }
     
       @Test
       public void smoke() {
         long now = 3000;
    -    CyclicBuffer cb = tracker.get(key, now);
    -    assertEquals(cb, tracker.get(key, now++));
    -    now += AppenderTrackerImpl.THRESHOLD+1000;
    +    CyclicBuffer cb = tracker.getOrCreate(key, now);
    +    assertEquals(cb, tracker.getOrCreate(key, now++));
    +    now += AppenderTrackerImpl.THRESHOLD + 1000;
         tracker.clearStaleBuffers(now);
         assertEquals(0, tracker.keyList().size());
    +    assertEquals(0, tracker.bufferCount);
       }
    +
    +  @Test
    +  public void destroy() {
    +    long now = 3000;
    +    CyclicBuffer cb = tracker.getOrCreate(key, now);
    +    cb.add(new Object());
    +    assertEquals(1, cb.length());
    +    tracker.removeBuffer(key);
    +    assertEquals(0, tracker.keyList().size());
    +    assertEquals(0, tracker.bufferCount);
    +    assertEquals(0, cb.length());
    +  }
    +
    +
    +
    +
     }
    diff --git a/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTrackerSimulator.java b/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTrackerSimulator.java
    index 3d3e000..ff9dd98 100644
    --- a/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTrackerSimulator.java
    +++ b/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTrackerSimulator.java
    @@ -20,14 +20,16 @@ import java.util.*;
      */
     public class CyclicBufferTrackerSimulator {
     
    -  CyclicBufferTrackerImpl realAppenderTracker = new CyclicBufferTrackerImpl();
    -  CyclicBufferTrackerImpl t_appenderTracker = new CyclicBufferTrackerImpl();
    +  CyclicBufferTrackerImpl realCBTracker = new CyclicBufferTrackerImpl();
    +  CyclicBufferTracker_TImpl t_CBTracker = new CyclicBufferTracker_TImpl();
     
       List scenario = new ArrayList();
       List keySpace = new ArrayList();
       int maxTimestampInc;
       Random randomKeyGen = new Random(100);
    -  Random random = new Random(11234);
    +  Random simulatorRandom = new Random(11234);
    +
    +  int deleteToInsertRatio = 10;
     
       CyclicBufferTrackerSimulator(int keySpaceLen, int maxTimestampInc) {
         this.maxTimestampInc = maxTimestampInc;
    @@ -35,7 +37,7 @@ public class CyclicBufferTrackerSimulator {
         for (int i = 0; i < keySpaceLen; i++) {
           String k = getRandomKeyStr();
           if (checkMap.containsKey(k)) {
    -        System.out.println("random key collision occured");
    +        System.out.println("random key collision occurred");
             k += "" + i;
           }
           keySpace.add(k);
    @@ -54,10 +56,15 @@ public class CyclicBufferTrackerSimulator {
         long timestamp = 30000;
         int keySpaceLen = keySpace.size();
         for (int i = 0; i < simLen; i++) {
    -      int index = random.nextInt(keySpaceLen);
    -      timestamp += random.nextInt(maxTimestampInc);
    +      int index = simulatorRandom.nextInt(keySpaceLen);
    +      timestamp += simulatorRandom.nextInt(maxTimestampInc);
    +      EventType eventType = EventType.INSERT;
    +      if (simulatorRandom.nextInt(deleteToInsertRatio) == 0) {
    +        eventType = EventType.DELETE;
    +      }
    +
           String key = keySpace.get(index);
    -      scenario.add(new SimulationEvent(key, timestamp));
    +      scenario.add(new SimulationEvent(eventType, key, timestamp));
         }
       }
     
    @@ -72,23 +79,36 @@ public class CyclicBufferTrackerSimulator {
                 CyclicBufferTracker tracker) {
         String key = simulationEvent.key;
         long timestamp = simulationEvent.timestamp;
    -    tracker.get(key, timestamp);
    +    EventType eventType = simulationEvent.eventType;
    +    switch (eventType) {
    +      case INSERT:
    +        tracker.getOrCreate(key, timestamp);
    +        break;
    +      case DELETE:
    +        tracker.removeBuffer(key);
    +        break;
    +    }
       }
     
       public void simulate() {
         for (SimulationEvent simeEvent : scenario) {
    -      play(simeEvent, realAppenderTracker);
    -      play(simeEvent, t_appenderTracker);
    +      play(simeEvent, realCBTracker);
    +      play(simeEvent, t_CBTracker);
         }
       }
     
       // =========================================================================
    +  enum EventType {
    +    INSERT, DELETE;
    +  }
     
       class SimulationEvent {
         final public String key;
         final public long timestamp;
    +    final EventType eventType;
     
    -    public SimulationEvent(String key, long timestamp) {
    +    public SimulationEvent(EventType eventType, String key, long timestamp) {
    +      this.eventType = eventType;
           this.key = key;
           this.timestamp = timestamp;
         }
    diff --git a/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTracker_TImpl.java b/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTracker_TImpl.java
    index 553104d..1d564a5 100644
    --- a/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTracker_TImpl.java
    +++ b/logback-core/src/test/java/ch/qos/logback/core/spi/CyclicBufferTracker_TImpl.java
    @@ -16,8 +16,6 @@ public class CyclicBufferTracker_TImpl implements CyclicBufferTracker {
     
       int bufferSize = DEFAULT_BUFFER_SIZE;
       int maxNumBuffers = DEFAULT_NUMBER_OF_BUFFERS;
    -  int bufferCount = 0;
    -
     
       List entryList = new LinkedList();
       long lastCheck = 0;
    @@ -47,12 +45,27 @@ public class CyclicBufferTracker_TImpl implements CyclicBufferTracker {
         return null;
       }
     
    -  public CyclicBuffer get(String key, long timestamp) {
    +  List keyList() {
    +    Collections.sort(entryList);
    +
    +    List result = new LinkedList();
    +    for (int i = 0; i < entryList.size(); i++) {
    +      TEntry te = entryList.get(i);
    +      result.add(te.key);
    +    }
    +    return result;
    +  }
    +
    +
    +  public CyclicBuffer getOrCreate(String key, long timestamp) {
         TEntry te = getEntry(key);
         if (te == null) {
           CyclicBuffer cb = new CyclicBuffer(bufferSize);
           te = new TEntry(key, cb, timestamp);
           entryList.add(te);
    +      if (entryList.size() >= maxNumBuffers) {
    +        entryList.remove(0);
    +      }
           return cb;
         } else {
           te.timestamp = timestamp;
    @@ -62,6 +75,16 @@ public class CyclicBufferTracker_TImpl implements CyclicBufferTracker {
     
       }
     
    +  public void removeBuffer(String k) {
    +    for (int i = 0; i < entryList.size(); i++) {
    +      TEntry te = entryList.get(i);
    +      if (te.key.equals(k)) {
    +        entryList.remove(i);
    +        return;
    +      }
    +    }
    +  }
    +
       final private boolean isEntryStale(TEntry entry, long now) {
         return ((entry.timestamp + THRESHOLD) < now);
       }
    diff --git a/logback-core/src/test/java/ch/qos/logback/core/spi/ScenarioBasedCyclicBufferTrackerTest.java b/logback-core/src/test/java/ch/qos/logback/core/spi/ScenarioBasedCyclicBufferTrackerTest.java
    index e48e4df..3fe7abd 100644
    --- a/logback-core/src/test/java/ch/qos/logback/core/spi/ScenarioBasedCyclicBufferTrackerTest.java
    +++ b/logback-core/src/test/java/ch/qos/logback/core/spi/ScenarioBasedCyclicBufferTrackerTest.java
    @@ -26,9 +26,9 @@ public class ScenarioBasedCyclicBufferTrackerTest {
     
       CyclicBufferTrackerSimulator simulator;
     
    -   void verify() {
    -    CyclicBufferTrackerImpl at = simulator.realAppenderTracker;
    -    CyclicBufferTrackerImpl t_at = simulator.t_appenderTracker;
    +  void verify() {
    +    CyclicBufferTrackerImpl at = simulator.realCBTracker;
    +    CyclicBufferTracker_TImpl t_at = simulator.t_CBTracker;
         assertEquals(t_at.keyList(), at.keyList());
       }
     
    @@ -48,7 +48,7 @@ public class ScenarioBasedCyclicBufferTrackerTest {
         verify();
       }
     
    -    @Test
    +  @Test
       public void longTest() {
         simulator = new CyclicBufferTrackerSimulator(128, CyclicBufferTracker.THRESHOLD / 2);
         simulator.buildScenario(200000);
    diff --git a/logback-site/src/site/pages/recipes/emailPerTransaction.html b/logback-site/src/site/pages/recipes/emailPerTransaction.html
    index 9573605..5eb054b 100644
    --- a/logback-site/src/site/pages/recipes/emailPerTransaction.html
    +++ b/logback-site/src/site/pages/recipes/emailPerTransaction.html
    @@ -170,7 +170,7 @@ public class PrimeAction extends Action {
       

    To isolate a given transaction, there must first be a way to distinguish it from other transactions. Typically this would be accomplished by putting the unique identifier of the transaction - into the the MDC. + into the MDC.

    String transactionId = ...; // extract id from transaction 
    @@ -236,8 +236,12 @@ MDC.put("txId", transactionId); 
    <key>txId</key> <defaultValue>default</defaultValue> </discriminator> + </appender> - </appender> + <root level="DEBUG"> + <appender-ref ref="SMTP" /> + </root> +</configuration>

    After starting the logback-demo web-application with the above configuration file (with smtpHost and @@ -315,8 +319,12 @@ MDC.put("txId", transactionId); <key>uuid</key> <defaultValue>default</defaultValue> </discriminator> + </appender> - </appender> + <root level="DEBUG"> + <appender-ref ref="SMTP" /> + </root> +</configuration> ----------------------------------------------------------------------- Summary of changes: .../ch/qos/logback/access/net/SMTPAppender.java | 5 ++- .../ch/qos/logback/classic/ClassicConstants.java | 5 ++ .../ch/qos/logback/classic/net/SMTPAppender.java | 12 ++++++ .../classic/net/DilutedSMTPAppenderTest.java | 2 +- .../ch/qos/logback/core/net/SMTPAppenderBase.java | 13 ++++++- ...TimeBasedFileNamingAndTriggeringPolicyBase.java | 7 +-- .../qos/logback/core/spi/CyclicBufferTracker.java | 7 +++- .../logback/core/spi/CyclicBufferTrackerImpl.java | 28 +++++++++---- .../core/spi/CyclicBufferTrackerImplTest.java | 34 +++++++++++++--- .../core/spi/CyclicBufferTrackerSimulator.java | 42 ++++++++++++++----- .../core/spi/CyclicBufferTracker_TImpl.java | 29 ++++++++++++- .../spi/ScenarioBasedCyclicBufferTrackerTest.java | 8 ++-- .../site/pages/recipes/emailPerTransaction.html | 14 +++++- 13 files changed, 160 insertions(+), 46 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From git-noreply at pixie.qos.ch Wed Dec 22 22:53:04 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Wed, 22 Dec 2010 22:53:04 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-53-g668e446 Message-ID: <20101222215304.9D5E7317319@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via 668e4464586c07ebe59c578406c3e7799508d46f (commit) from 8f3f52105b1f95909cb48be721fe3046473b2a4b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=668e4464586c07ebe59c578406c3e7799508d46f http://github.com/ceki/logback/commit/668e4464586c07ebe59c578406c3e7799508d46f commit 668e4464586c07ebe59c578406c3e7799508d46f Author: Ceki Gulcu Date: Wed Dec 22 22:50:31 2010 +0100 - doc improvements - minor indentation changes diff --git a/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java b/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java index a835638..f3bb08c 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java +++ b/logback-core/src/main/java/ch/qos/logback/core/net/SMTPAppenderBase.java @@ -59,18 +59,14 @@ import ch.qos.logback.core.util.OptionHelper; */ public abstract class SMTPAppenderBase extends AppenderBase { - static InternetAddress[] EMPTY_IA_ARRAY = new InternetAddress[0]; + static InternetAddress[] EMPTY_IA_ARRAY = new InternetAddress[0]; // ~ 14 days static final int MAX_DELAY_BETWEEN_STATUS_MESSAGES = 1228800 * CoreConstants.MILLIS_IN_ONE_SECOND; long lastTrackerStatusPrint = 0; int delayBetweenStatusMessages = 300 * CoreConstants.MILLIS_IN_ONE_SECOND; - - - protected Layout subjectLayout; - protected Layout layout; private List> toPatternLayoutList = new ArrayList>(); @@ -110,7 +106,7 @@ public abstract class SMTPAppenderBase extends AppenderBase { */ public void start() { - if(cbTracker == null) { + if (cbTracker == null) { cbTracker = new CyclicBufferTrackerImpl(); } @@ -189,15 +185,13 @@ public abstract class SMTPAppenderBase extends AppenderBase { } } - - if(isEventMarkedForBufferRemoval(eventObject)) { + // immediately remove the buffer if asked by the user + if (isEventMarkedForBufferRemoval(eventObject)) { cbTracker.removeBuffer(key); } cbTracker.clearStaleBuffers(now); - - if (lastTrackerStatusPrint + delayBetweenStatusMessages < now) { addInfo("SMTPAppender [" + name + "] is tracking [" + cbTracker.size() + "] buffers"); lastTrackerStatusPrint = now; @@ -268,14 +262,14 @@ public abstract class SMTPAppenderBase extends AppenderBase { try { PatternLayoutBase emailPL = toPatternLayoutList.get(i); String email = emailPL.doLayout(event); - if(email == null || email.length() == 0) { + if (email == null || email.length() == 0) { continue; } InternetAddress[] tmp = InternetAddress.parse(email, true); // one element should contain one email address iaList.add(tmp[0]); } catch (AddressException e) { - addError("Could not parse email address for [" + toPatternLayoutList.get(i) + "] for event ["+event+"]", e); + addError("Could not parse email address for [" + toPatternLayoutList.get(i) + "] for event [" + event + "]", e); return iaList; } } @@ -325,12 +319,12 @@ public abstract class SMTPAppenderBase extends AppenderBase { charsetEncoding); } - List destinationAddresses = parseAddress(lastEventObject); - if(destinationAddresses.isEmpty()) { - addInfo("Empty destination address. Aborting email transmission"); - return; - } - mimeMsg.setRecipients(Message.RecipientType.TO, destinationAddresses.toArray(EMPTY_IA_ARRAY)); + List destinationAddresses = parseAddress(lastEventObject); + if (destinationAddresses.isEmpty()) { + addInfo("Empty destination address. Aborting email transmission"); + return; + } + mimeMsg.setRecipients(Message.RecipientType.TO, destinationAddresses.toArray(EMPTY_IA_ARRAY)); String contentType = layout.getContentType(); @@ -352,8 +346,6 @@ public abstract class SMTPAppenderBase extends AppenderBase { } } - - abstract protected void fillBuffer(CyclicBuffer cb, StringBuffer sbuf); /** @@ -388,6 +380,7 @@ public abstract class SMTPAppenderBase extends AppenderBase { /** * Alias for smtpHost + * * @param smtpHost */ public void setSMTPHost(String smtpHost) { @@ -422,7 +415,7 @@ public abstract class SMTPAppenderBase extends AppenderBase { * @param port */ public void setSMTPPort(int port) { - setSmtpPort(port); + setSmtpPort(port); } /** @@ -436,13 +429,16 @@ public abstract class SMTPAppenderBase extends AppenderBase { /** * Alias for {@link #getSmtpPort} + * * @return - */ + */ public int getSMTPPort() { return getSmtpPort(); } + /** * See {@link #setSmtpPort} + * * @return */ public int getSmtpPort() { @@ -466,27 +462,27 @@ public abstract class SMTPAppenderBase extends AppenderBase { } public void addTo(String to) { - if(to == null || to.length() == 0) { - throw new IllegalArgumentException("Null or empty property"); - } - PatternLayoutBase plb = makeNewToPatternLayout(to.trim()); - plb.setContext(context); - plb.start(); - this.toPatternLayoutList.add(plb); + if (to == null || to.length() == 0) { + throw new IllegalArgumentException("Null or empty property"); + } + PatternLayoutBase plb = makeNewToPatternLayout(to.trim()); + plb.setContext(context); + plb.start(); + this.toPatternLayoutList.add(plb); } abstract protected PatternLayoutBase makeNewToPatternLayout(String toPattern); - public List getToAsListOfString() { - List toList = new ArrayList(); - for(PatternLayoutBase plb: toPatternLayoutList) { - toList.add(plb.getPattern()); - } - return toList; - } + public List getToAsListOfString() { + List toList = new ArrayList(); + for (PatternLayoutBase plb : toPatternLayoutList) { + toList.add(plb.getPattern()); + } + return toList; + } // for testing purpose only - public Message getMessage() { + public Message getMessage() { return mimeMsg; } diff --git a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java index 6542a44..40d1eae 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/pattern/ReplacingCompositeConverter.java @@ -40,9 +40,6 @@ public class ReplacingCompositeConverter extends CompositeConverter { } regex = optionList.get(0); pattern = Pattern.compile(regex); - - //.matcher(this).replaceAll(replacement); - replacement = optionList.get(1); super.start(); } diff --git a/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java b/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java index 0c9fe80..83cc39f 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java +++ b/logback-core/src/main/java/ch/qos/logback/core/spi/CyclicBufferTracker.java @@ -31,8 +31,6 @@ public interface CyclicBufferTracker { public int getBufferSize(); public void setBufferSize(int size); - - public int getMaxNumberOfBuffers(); /** diff --git a/logback-site/src/site/pages/manual/appenders.html b/logback-site/src/site/pages/manual/appenders.html index c527c4f..a37f67c 100644 --- a/logback-site/src/site/pages/manual/appenders.html +++ b/logback-site/src/site/pages/manual/appenders.html @@ -1695,10 +1695,11 @@ public interface TriggeringPolicy<E> extends LifeCycle {

    - + @@ -1818,8 +1819,8 @@ public interface TriggeringPolicy<E> extends LifeCycle { href="../xref/ch/qos/logback/core/spi/CyclicBufferTrackerImpl.html">CyclicBufferTrackerImpl will be automatically created. By default, this instance will keep events in a cyclic buffer of size 256. You may - change the size with the help of the BufferSize - option.

    + change the size with the help of the bufferSize option (see below).

    @@ -2369,6 +2370,45 @@ logger.error(notifyAdmin, host, greatly facilitating problem diagnosis.

    +

    On buffer + management in very busy systems

    + +

    Internally, each distinct value returned by the disciminator + will cause the creation of a new cyclic buffer. However, at most + maxNumberOfBuffers (by default 64) + will be maintained. Whenever the number of buffers rises above + maxNumberOfBuffers, the least recently + updated buffer is automatically discarded. As a second safety + measure, any buffer which has not been updated in the last 30 + minutes will be automatically discarded as well.

    + +

    On systems serving a large number of transactions per minute, + allowing only a small number for maxNumberOfBuffers (by default 64) will + often cause the number of events in the outgoing email to be + unnecessarily small. Indeed, in the presence of a large number of + transactions, there will be more than one buffer associated with + the same transaction as buffers will be killed and re-born in + succession for the same discriminator value (or transaction). Note + that in even such very busy systems, the maximum number of cyclic + buffers is capped by maxNumberOfBuffers. +

    + +

    To avoid such yo-yo effects, SMTPAppender will + release the buffer associated with a given discriminator key as + soon as it sees an event marked as "FINALIZE_SESSION". This will + cause the appropriate buffer to be discarded at the end of each + transaction. You can then safely increase the value of maxNumberOfBuffers to a larger value such as + 512 or 1024 without risking running out of memory. +

    + +

    Thuse reare three distinct but complementary mechanisms working + together to manage cyclic buffers. They ensure that only relevant + buffers are kept alive at any given moment, even in very busy + systems.

    + diff --git a/logback-site/src/site/pages/news.html b/logback-site/src/site/pages/news.html index 55138ef..99f8e53 100644 --- a/logback-site/src/site/pages/news.html +++ b/logback-site/src/site/pages/news.html @@ -28,10 +28,14 @@
    -

    xxx, 2010 - Release of version 0.9.27

    +

    December 22nd, 2010 - Release of version 0.9.27

    -

    PatternLayout now supports compound conversion - words of which "%replace" is one example. +

    Added a new section in the documentation about real-world inspired recipes.

    + +

    PatternLayout now supports + compound conversion words of which "%replace" is one example.

    The

    -

    Triggering an email containing the isoloated logs of selected +

    Triggering an email containing the isolated logs of selected transactions

    Let Dave and Carol be software QA engineers working at a @@ -86,7 +86,7 @@ import javax.servlet.http.HttpServletResponse; public class PrimeAction extends Action { Logger logger = LoggerFactory.getLogger(PrimeAction.class); - Marker SMTP_TRIGGER = MarkerFactory.getMarker("SMTP_TRIGGER"); + static Marker SMTP_TRIGGER = MarkerFactory.getMarker("SMTP_TRIGGER"); public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest request, @@ -302,7 +302,7 @@ MDC.put("txId", transactionId); </layout> <discriminator class="ch.qos.logback.classic.sift.MDCBasedDiscriminator"> - <key>uuid</key> + <key>txId</key> <defaultValue>default</defaultValue> </discriminator> @@ -314,18 +314,131 @@ MDC.put("txId", transactionId); (marker != null && marker.contains("SMTP_TRIGGER") ) </expression> </evaluator> + </appender> + + <root level="DEBUG"> + <appender-ref ref="SMTP" /> + </root> +</configuration> + +

    If your particular SMTP server does not handle address tags, + you can still use them within the evaluator but remove them in + the recipient address with the help of the %replace conversion + word. Here is the relevant configuraton snippet:

    + +
    <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
    +  <to>%replace(%mdc{txEmail}){'\+log', ''}</to>
    +  ...
    +</appender>
    + +

    This replaces any occurrence of the string "+log" within the + string returned by %mdc{txEmail} with the empty string, + effectively erasing +log from the recipient address.

    + +

    Buffer management in very busy systems

    + +

    The solution described so far provides an amazingly flexible + solution to the initial problem. Indeed, any QA-engineer at + Fooware.com, say Carol, can have the logs generated by requests + she makes to Buscrit sent to her automatically by email. All she + has to do is to suffix the user part in her email address with + "+log" when she registers with Buscrit. +

    + +

    By default SMTPAppender will cap the number of + buffers it maintains to the value of the maxNumberOfBuffers option (64 by default) + and automatically discards buffers untouched for at least 30 + minutes. While this approach will work nicely in a test + environment with few transactions, in a very busy production + system, these buffer management mechanims will cause Carol to + receive truncated log + buffers.

    + +

    To deal with this problem, we instruct SMTPAppender to discard + apprioate buffer at the end of each transaction. This is done by + logging an event marked as "FINALIZE_SESSION". Here is a modified + version of PrimeAction which marks the end of a + transaction with "FINALIZE_SESSION". +

    + +
    package ch.qos.logback.demo.prime;
    +
    +import static ch.qos.logback.classic.ClassicConstants.FINALIZE_SESSION_MARKER;
    +
    +public class PrimeAction extends Action {
    +
    +  Logger logger = LoggerFactory.getLogger(PrimeAction.class);
    +  static Marker SMTP_TRIGGER = MarkerFactory.getMarker("SMTP_TRIGGER");
    +  static {
    +     // markers can hold references to other markers
    +     SMTP_TRIGGER.add(FINALIZE_SESSION_MARKER);
    +  }
    +
    +  public ActionForward execute(ActionMapping actionMapping, ... ) throws Exception {
    +
    +    Long number = form.getNumber();
    +    try {
    +      ...
    +    } finally {
    +      logger.info(SMTP_TRIGGER, "Prime computation ended");
    +      MDC.put("txId", null); // clear txId asap to avoid accidental rebirth
    +    }
    +  }
    +} 
    + + +

    Not that at the end of each transaction the appropriate buffer + is discarded, we can incrase the value of maxNumberOfBuffers as shown in the next + configuration file.. +

    + +
    <configuration scan="true" scanPeriod="3 seconds">
    +
    +  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
    +
    +  <appender name="SMTP" class="ch.qos.logback.classic.net.SMTPAppender">
    +    <SMTPHost>NAME_OF_SMTP_HOST</SMTPHost>
    +    <to>%mdc{txEmail}</to>
    +    <from></from>
    +    <subject>Prime - %mdc{number}</subject>
    +
    +    <layout class="ch.qos.logback.classic.html.HTMLLayout">
    +       <pattern>%date%level%logger{24}%msg</pattern>
    +    </layout>
     
         <discriminator class="ch.qos.logback.classic.sift.MDCBasedDiscriminator">
    -      <key>uuid</key>
    +      <key>txId</key>
           <defaultValue>default</defaultValue>
         </discriminator>
    -  </appender>
    +
    +    <cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTrackerImpl">
    +      <maxNumberOfBuffers>512</maxNumberOfBuffers>
    +    </cyclicBufferTracker>
    +
    +    <evaluator class="ch.qos.logback.classic.boolex.JaninoEventEvaluator">
    +      <expression>
    +        (mdc != null &amp;&amp; mdc.get("txEmail") != null &amp;&amp;
    +            ((String) mdc.get("txEmail")).contains("+log") )
    +        &amp;&amp;
    +        (marker != null  && marker.contains("SMTP_TRIGGER") )
    +      </expression>
    +    </evaluator>
     
       <root level="DEBUG">
         <appender-ref ref="SMTP" /> 
       </root>
     </configuration>  
    - + +

    With these latest changes, we can selectively send isolated + logs for selected transactions to the concerned recipient, even in + very busy production systems without excessive memory consumption. +

    + +
    ----------------------------------------------------------------------- Summary of changes: .../ch/qos/logback/core/net/SMTPAppenderBase.java | 70 +++++------ .../core/pattern/ReplacingCompositeConverter.java | 3 - .../qos/logback/core/spi/CyclicBufferTracker.java | 2 - logback-site/src/site/pages/manual/appenders.html | 52 +++++++- logback-site/src/site/pages/news.html | 10 +- .../site/pages/recipes/emailPerTransaction.html | 125 +++++++++++++++++++- 6 files changed, 205 insertions(+), 57 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From ceki at qos.ch Wed Dec 22 23:08:57 2010 From: ceki at qos.ch (=?ISO-8859-1?Q?Ceki_G=FClc=FC?=) Date: Wed, 22 Dec 2010 23:08:57 +0100 Subject: [logback-dev] Release of logback v0.9.27 Message-ID: <4D1276F9.9070903@qos.ch> Hello all, I am happy to announce the release of logback version 0.9.27. Please refer to the news page for precise details. http://logback.qos.ch/news.html You can download logback, including full source code, class files and documentation on our download page, shown below. http://logback.qos.ch/download.html You can receive logback related announcements by subscribing to the QOS.ch announce mailing list. To subscribe to QOS.ch announce list, please visit the following URL. http://www.qos.ch/mailman/listinfo/announce Enjoy, -- Ceki From git-noreply at pixie.qos.ch Wed Dec 22 23:13:21 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Wed, 22 Dec 2010 23:13:21 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.25-54-gc6c098f Message-ID: <20101222221321.59B6731739D@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via c6c098ff63d8af47d10da2bb5a90f6aaea011c59 (commit) from 668e4464586c07ebe59c578406c3e7799508d46f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=c6c098ff63d8af47d10da2bb5a90f6aaea011c59 http://github.com/ceki/logback/commit/c6c098ff63d8af47d10da2bb5a90f6aaea011c59 commit c6c098ff63d8af47d10da2bb5a90f6aaea011c59 Author: Ceki Gulcu Date: Wed Dec 22 22:54:38 2010 +0100 - minor edits to news.html - preparing release 0.9.27 diff --git a/logback-access/pom.xml b/logback-access/pom.xml index b0e7ab3..11bb3db 100644 --- a/logback-access/pom.xml +++ b/logback-access/pom.xml @@ -7,7 +7,7 @@ ch.qos.logback logback-parent - 0.9.27-SNAPSHOT + 0.9.27 logback-access diff --git a/logback-classic/pom.xml b/logback-classic/pom.xml index f5dbbcb..7eea5e8 100644 --- a/logback-classic/pom.xml +++ b/logback-classic/pom.xml @@ -7,7 +7,7 @@ ch.qos.logback logback-parent - 0.9.27-SNAPSHOT + 0.9.27 logback-classic diff --git a/logback-core/pom.xml b/logback-core/pom.xml index d8b6207..ec015b0 100644 --- a/logback-core/pom.xml +++ b/logback-core/pom.xml @@ -7,7 +7,7 @@ ch.qos.logback logback-parent - 0.9.27-SNAPSHOT + 0.9.27 logback-core diff --git a/logback-examples/pom.xml b/logback-examples/pom.xml index 50fd2a0..2428f24 100644 --- a/logback-examples/pom.xml +++ b/logback-examples/pom.xml @@ -5,7 +5,7 @@ ch.qos.logback logback-parent - 0.9.27-SNAPSHOT + 0.9.27 4.0.0 diff --git a/logback-site/pom.xml b/logback-site/pom.xml index d4a317c..2c2b192 100644 --- a/logback-site/pom.xml +++ b/logback-site/pom.xml @@ -3,7 +3,7 @@ ch.qos.logback logback-parent - 0.9.27-SNAPSHOT + 0.9.27 4.0.0 diff --git a/logback-site/src/site/pages/news.html b/logback-site/src/site/pages/news.html index 99f8e53..4144b5d 100644 --- a/logback-site/src/site/pages/news.html +++ b/logback-site/src/site/pages/news.html @@ -33,9 +33,13 @@

    Added a new section in the documentation about real-world inspired recipes.

    -

    PatternLayout now supports - compound conversion words of which "%replace" is one example. +

    PatternLayout now supports compound conversion + words of which "%replace" is one + example. This change involved a significant re-write of the + pattern tokenizer, the pattern parser and the pattern + compiler. However, the changes should be backward compatible as far + as users are concerned.

    The ch.qos.logback logback-parent - 0.9.27-SNAPSHOT + 0.9.27 pom Logback-Parent ----------------------------------------------------------------------- Summary of changes: logback-access/pom.xml | 2 +- logback-classic/pom.xml | 2 +- logback-core/pom.xml | 2 +- logback-examples/pom.xml | 2 +- logback-site/pom.xml | 2 +- logback-site/src/site/pages/news.html | 10 +++++++--- pom.xml | 2 +- 7 files changed, 13 insertions(+), 9 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From git-noreply at pixie.qos.ch Wed Dec 22 23:14:07 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Wed, 22 Dec 2010 23:14:07 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. annotated tag, v_0.9.27, created. v_0.9.27 Message-ID: <20101222221407.3212131739F@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The annotated tag, v_0.9.27 has been created at ee40f0381308f61d040c28ccb534af9abf829871 (tag) tagging c6c098ff63d8af47d10da2bb5a90f6aaea011c59 (commit) replaces v_0.9.25 tagged by Ceki Gulcu on Wed Dec 22 23:11:30 2010 +0100 - Log ----------------------------------------------------------------- tagging release 0.9.27 Ceki Gulcu (54): start work on next version typo fixes fix LBCORE-114 trying to hunt down LBCLASSIC-223 logback-classic should be based on the latest SLF4J... InetAdress.canonicalHostName is not necessarily the same as InetHost.hostname patial fix for LBCLASSIC-183. It helps if the ThreadLoacal class is Solve LBCLASSIC-183. Use InheritableThreadLocal instead of editing ongoing work OnConsoleStatusListener now retrospectively prints status messages minor refactoring Fix LBCLASSIC-226 - fix LBCORE-170 start work on 0.9.27 added link to XtremeMP project adding recipes on going work on th emailPerTransaction recipe working on the documentation avoid output on folders outside target/test-output avoid polluting the output for default additity, added a test case Fix LBCLASSIC-231 blurb in the news ongoing work on the docs fix LBCORE-174 documenation in relation with LBCLASSIC-212 minor editing - Ongoing work on LBCORE-180 and LBCLASSIC-232 minor editing TeeFilter now takes include and exclude parameters so that it can be minor edit - pom.xml clean up - minor edits news about LBACCESS-15 ongoing work on the documentation ongoing edits ow minor edits logback-access documentaiton improvements logback-access documentation improvements add support for dynamic destination address computation in SMTPAppender adding support for composite keywords ongoing work on compound conversion words working version of compound keywords doc improvements applied Inigo Surguy's proof reading patch - merged OptionTokenizer into TokenStream in order to lift the ongoing docs edits add missing file ongoing edits more edits - Improved testing of CyclicBufferTracker. Added support for immediate - doc improvements - minor edits to news.html ----------------------------------------------------------------------- hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From noreply-jira at qos.ch Thu Dec 23 19:43:52 2010 From: noreply-jira at qos.ch (Favio DeMarco (JIRA)) Date: Thu, 23 Dec 2010 19:43:52 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBCLASSIC-113) Nullpointer In-Reply-To: <2013629426.1236766750850.JavaMail.ceki@pixie> Message-ID: <1687696757.1293129832438.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCLASSIC-113?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11917#action_11917 ] Favio DeMarco commented on LBCLASSIC-113: ----------------------------------------- I have a similar issue with 0.9.26: java.lang.NullPointerException: null at ch.qos.logback.classic.Logger.callTurboFilters(Logger.java:803) ~[logback-classic-0.9.26.jar:na] at ch.qos.logback.classic.Logger.isDebugEnabled(Logger.java:521) ~[logback-classic-0.9.26.jar:na] at ch.qos.logback.classic.Logger.isDebugEnabled(Logger.java:517) ~[logback-classic-0.9.26.jar:na] at net.sf.ehcache.distribution.RMICachePeer.put(RMICachePeer.java:175) ~[ehcache-core-2.3.0.jar:na] And, like LBCLASSIC-74, it starts when a webapp is redeployed in Tomcat 5.5.30, but I can't reproduce it with minimalwebapp. I'll try to reproduce it with a simpler configuration. > Nullpointer > ----------- > > Key: LBCLASSIC-113 > URL: http://jira.qos.ch/browse/LBCLASSIC-113 > Project: logback-classic > Issue Type: Bug > Components: Other > Reporter: Mathias Bogaert > Assignee: Logback dev list > Priority: Critical > > java.lang.NullPointerException > at ch.qos.logback.classic.Logger.callTurboFilters(Logger.java:769) [logback-classic-0.9.15.jar:na] > at ch.qos.logback.classic.Logger.isTraceEnabled(Logger.java:641) [logback-classic-0.9.15.jar:na] > at ch.qos.logback.classic.Logger.isTraceEnabled(Logger.java:637) [logback-classic-0.9.15.jar:na] > at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:198) [hibernate-core-3.3.0.SP1.jar:3.3.0.SP1] > at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:126) [hibernate-core-3.3.0.SP1.jar:3.3.0.SP1] > at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:905) [hibernate-core-3.3.0.SP1.jar:3.3.0.SP1] > Hibernate calls if ( log.isTraceEnabled() ). -- 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 From noreply-jira at qos.ch Mon Dec 27 08:37:52 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Mon, 27 Dec 2010 08:37:52 +0100 (CET) Subject: [logback-dev] [JIRA] Updated: (LBCORE-187) TimestampAction should base current time or LoggerContext birthtime field In-Reply-To: <1028159143.1292604771281.JavaMail.ceki@pixie> Message-ID: <1207213168.1293435472281.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-187?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu updated LBCORE-187: ------------------------------ Summary: TimestampAction should base current time or LoggerContext birthtime field (was: TimestampAction should base current time on LoggerContext birthtime field) > TimestampAction should base current time or LoggerContext birthtime field > ------------------------------------------------------------------------- > > Key: LBCORE-187 > URL: http://jira.qos.ch/browse/LBCORE-187 > Project: logback-core > Issue Type: Bug > Affects Versions: 0.9.26 > Reporter: Ceki Gulcu > Assignee: Ceki Gulcu > > As things stand currently, TimestampAction uses the date of invocation of the config file as the value to format and place as a property. Under certain circumstances, it might be useful to take the context's birth date as input value. -- 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 From ceki at qos.ch Mon Dec 27 11:52:58 2010 From: ceki at qos.ch (Ceki Gulcu) Date: Mon, 27 Dec 2010 11:52:58 +0100 Subject: [logback-dev] Moving some tests to Scala Message-ID: <4D18700A.9010206@qos.ch> Hello all, In light of the large code base in logback dealing with tests, I started moving some of the test to Scala. As you are probably aware, Scala has a number serious advantages over java. It has some serious disadvantages as well. It's all still very experimental. I'll let you know how it goes. Cheers, -- Ceki From noreply-jira at qos.ch Mon Dec 27 13:55:51 2010 From: noreply-jira at qos.ch (Artyom Kalita (JIRA)) Date: Mon, 27 Dec 2010 13:55:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBCORE-189) DBAppender swallow NullPointerException Message-ID: <1833168732.1293454551272.JavaMail.ceki@pixie> DBAppender swallow NullPointerException --------------------------------------- Key: LBCORE-189 URL: http://jira.qos.ch/browse/LBCORE-189 Project: logback-core Issue Type: Bug Components: Appender Affects Versions: 0.9.26 Reporter: Artyom Kalita Assignee: Logback dev list Priority: Minor logback.xml : com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/mrb root admin Java code (using DBAppender): Date dateFrom = null; log.info("Processing code {}; code type is {}; request date {}; record from date {}",new Object[] { code, codeType, new Date(), dateFrom }); DBAppender had null pointer exception on 141 line because of dateFrom, but this exception is swallowed and not shown. -- 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 From noreply-jira at qos.ch Mon Dec 27 16:17:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Mon, 27 Dec 2010 16:17:51 +0100 (CET) Subject: [logback-dev] [JIRA] Assigned: (LBCORE-189) DBAppender swallow NullPointerException In-Reply-To: <1833168732.1293454551272.JavaMail.ceki@pixie> Message-ID: <1634856515.1293463071350.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-189?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu reassigned LBCORE-189: --------------------------------- Assignee: Ceki Gulcu (was: Logback dev list) > DBAppender swallow NullPointerException > --------------------------------------- > > Key: LBCORE-189 > URL: http://jira.qos.ch/browse/LBCORE-189 > Project: logback-core > Issue Type: Bug > Components: Appender > Affects Versions: 0.9.26 > Reporter: Artyom Kalita > Assignee: Ceki Gulcu > Priority: Minor > > logback.xml : > > > > com.mysql.jdbc.Driver > jdbc:mysql://localhost:3306/mrb > root > admin > > > Java code (using DBAppender): > Date dateFrom = null; > log.info("Processing code {}; code type is {}; request date {}; record from date {}",new Object[] { code, codeType, new Date(), dateFrom }); > DBAppender had null pointer exception on 141 line because of dateFrom, but this exception is swallowed and not shown. -- 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 From git-noreply at pixie.qos.ch Mon Dec 27 17:17:24 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Mon, 27 Dec 2010 17:17:24 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.27-1-g4a792d8 Message-ID: <20101227161724.DEA3E3173FD@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via 4a792d8efd47548dedbf838ef5d32531e9a928c8 (commit) from c6c098ff63d8af47d10da2bb5a90f6aaea011c59 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=4a792d8efd47548dedbf838ef5d32531e9a928c8 http://github.com/ceki/logback/commit/4a792d8efd47548dedbf838ef5d32531e9a928c8 commit 4a792d8efd47548dedbf838ef5d32531e9a928c8 Author: Ceki Gulcu Date: Mon Dec 27 17:17:35 2010 +0100 moving various tests to scala diff --git a/logback-access/pom.xml b/logback-access/pom.xml index 11bb3db..dcfeb31 100644 --- a/logback-access/pom.xml +++ b/logback-access/pom.xml @@ -7,7 +7,7 @@ ch.qos.logback logback-parent - 0.9.27 + 0.9.28-SNAPSHOT logback-access diff --git a/logback-classic/pom.xml b/logback-classic/pom.xml index 7eea5e8..ed392a5 100644 --- a/logback-classic/pom.xml +++ b/logback-classic/pom.xml @@ -7,7 +7,7 @@ ch.qos.logback logback-parent - 0.9.27 + 0.9.28-SNAPSHOT logback-classic diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java index 546a653..f080e50 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java @@ -179,7 +179,7 @@ public class ReconfigureOnChangeTest { // we can't have the test succeed under JDK 1.5, punt and require 1.6+ if (Env.isJDK6OrHigher()) { assertTrue(failMsg, - (effectiveResets * 1.4) >= (expectedReconfigurations * 1.0)); + (effectiveResets * 1.5) >= (expectedReconfigurations * 1.0)); } } diff --git a/logback-core/pom.xml b/logback-core/pom.xml index ec015b0..4c2f517 100644 --- a/logback-core/pom.xml +++ b/logback-core/pom.xml @@ -1,167 +1,193 @@ - - 4.0.0 - - - ch.qos.logback - logback-parent - 0.9.27 - - - logback-core - jar - Logback Core Module - - http://logback.qos.ch - - - Logback: the generic, reliable, fast and flexible logging library for Java. - - - - - Eclipse Public License - v 1.0 - http://www.eclipse.org/legal/epl-v10.html - - - - GNU Lesser General Public License - http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html - - - - - - janino - janino - compile - true - - - - org.codehaus.groovy - groovy-all - compile - true - - - - - javax.mail - mail - compile - true - - - org.apache.geronimo.specs - geronimo-jms_1.1_spec - compile - true - - - - org.easymock - easymock - 2.4 - test - - - - javax.servlet - servlet-api - compile - true - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - - - - - org.apache.maven.plugins - maven-surefire-plugin - - once - plain - false - - **/All*Test.java - **/PackageTest.java - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - ${project.build.outputDirectory}/META-INF/MANIFEST.MF - - - - - bundle-test-jar - package - - jar - test-jar - - - - - - - org.apache.felix - maven-bundle-plugin - true - - - bundle-manifest - process-classes - - manifest - - - - - - ch.qos.logback.core.* - - javax.*;resolution:=optional, - org.xml.*;resolution:=optional, - org.codehaus.janino;resolution:=optional, - * - - J2SE-1.5 - - - - - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + 4.0.0 + + + ch.qos.logback + logback-parent + 0.9.28-SNAPSHOT + + + logback-core + jar + Logback Core Module + + http://logback.qos.ch + + + Logback: the generic, reliable, fast and flexible logging library for Java. + + + + + Eclipse Public License - v 1.0 + http://www.eclipse.org/legal/epl-v10.html + + + + GNU Lesser General Public License + http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html + + + + + + janino + janino + compile + true + + + + org.codehaus.groovy + groovy-all + compile + true + + + + + javax.mail + mail + compile + true + + + org.apache.geronimo.specs + geronimo-jms_1.1_spec + compile + true + + + + org.easymock + easymock + 2.4 + test + + + + javax.servlet + servlet-api + compile + true + + + + org.scala-lang + scala-library + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + + org.scala-tools + maven-scala-plugin + 2.14.3 + + src/test/scala + + + + scala-test-compile + process-test-resources + + testCompile + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + once + plain + false + + **/All*Test.java + **/PackageTest.java + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + bundle-test-jar + package + + jar + test-jar + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + ch.qos.logback.core.* + + javax.*;resolution:=optional, + org.xml.*;resolution:=optional, + org.codehaus.janino;resolution:=optional, + * + + J2SE-1.5 + + + + + \ No newline at end of file diff --git a/logback-core/src/test/scala/ch/qos/logback/core/rolling/A.scala b/logback-core/src/test/scala/ch/qos/logback/core/rolling/A.scala new file mode 100644 index 0000000..b446737 --- /dev/null +++ b/logback-core/src/test/scala/ch/qos/logback/core/rolling/A.scala @@ -0,0 +1,41 @@ +package ch.qos.logback.core.rolling + +import collection.mutable.ListBuffer +import org.junit.Test + +/** + * Created by IntelliJ IDEA. + * User: ceki + * Date: 27.12.10 + * Time: 14:19 + * To change this template use File | Settings | File Templates. + */ + +class A { + + + val initial = List(1,2, 3, 5) + def mon[B](f: Int => B): List[B] = { + val b = new ListBuffer[B] + var these = initial + while (!these.isEmpty) { + var that = f(these.head) + b += that + these = these.tail + } + b.toList + } + + def asString(in: Any):String = { + "-"+ in.toString; + } + + @Test + def doTest() { + val res: List[String] = mon(asString); + println(res) + + + } + +} \ No newline at end of file diff --git a/logback-core/src/test/scala/ch/qos/logback/core/rolling/RollingScaffolding.scala b/logback-core/src/test/scala/ch/qos/logback/core/rolling/RollingScaffolding.scala new file mode 100644 index 0000000..ed78e3e --- /dev/null +++ b/logback-core/src/test/scala/ch/qos/logback/core/rolling/RollingScaffolding.scala @@ -0,0 +1,85 @@ +/** + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2010, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ +package ch.qos.logback.core.rolling + +import ch.qos.logback.core.{ContextBase, Context} +import ch.qos.logback.core.util.CoreTestConstants +import ch.qos.logback.core.testUtil.RandomUtil +import java.util.{Date, Calendar} +import java.util.concurrent.TimeUnit +import java.text.SimpleDateFormat + +trait RollingScaffolding { + final val DATE_PATTERN_WITH_SECONDS = "yyyy-MM-dd_HH_mm_ss" + final val SDF = new SimpleDateFormat(DATE_PATTERN_WITH_SECONDS) + private[rolling] var context: Context = new ContextBase + private[rolling] var diff: Int = RandomUtil.getPositiveInt + protected var currentTime: Long = 0L + protected var randomOutputDir: String = CoreTestConstants.OUTPUT_DIR_PREFIX + diff + "/" + private[rolling] var cal: Calendar = Calendar.getInstance + protected var nextRolloverThreshold: Long = 0; + protected var expectedFilenameList: List[String] = Nil + + def setUpScaffolding: Unit = { + context.setName("test") + cal.set(Calendar.MILLISECOND, 333) + currentTime = cal.getTimeInMillis + nextRolloverThreshold = recomputeRolloverThreshold(currentTime) + } + + protected def incCurrentTime(increment: Long): Unit = { + currentTime += increment + } + + protected def getDateOfCurrentPeriodsStart: Date = { + var delta: Long = currentTime % 1000 + return new Date(currentTime - delta) + } + + protected def addExpectedFileName_ByDate(outputDir: String, testId: String, date: Date, gzExtension: Boolean): Unit = { + var fn: String = outputDir + testId + "-" + SDF.format(date) + if (gzExtension) { + fn += ".gz" + } + expectedFilenameList += fn + + } + + protected def addExpectedFileNamedIfItsTime_ByDate(outputDir: String, testId: String, gzExtension: Boolean): Unit = { + if (passThresholdTime(nextRolloverThreshold)) { + addExpectedFileName_ByDate(outputDir, testId, getDateOfCurrentPeriodsStart, gzExtension) + nextRolloverThreshold = recomputeRolloverThreshold(currentTime) + } + } + + protected def passThresholdTime(nextRolloverThreshold: Long): Boolean = { + return currentTime >= nextRolloverThreshold + } + + protected def recomputeRolloverThreshold(ct: Long): Long = { + var delta: Long = ct % 1000 + (ct - delta) + 1000 + } + + private[rolling] def addGZIfNotLast(i: Int, suff: String): String = { + var lastIndex: Int = expectedFilenameList.size - 1 + if (i != lastIndex) suff else "" + } + + private[rolling] def waitForCompression(tbrp: TimeBasedRollingPolicy[AnyRef]): Unit = { + if (tbrp.future != null && !tbrp.future.isDone) { + tbrp.future.get(200, TimeUnit.MILLISECONDS) + } + } + } \ No newline at end of file diff --git a/logback-core/src/test/scala/ch/qos/logback/core/rolling/TimeBasedRolling2Test.scala b/logback-core/src/test/scala/ch/qos/logback/core/rolling/TimeBasedRolling2Test.scala new file mode 100644 index 0000000..06bd4af --- /dev/null +++ b/logback-core/src/test/scala/ch/qos/logback/core/rolling/TimeBasedRolling2Test.scala @@ -0,0 +1,104 @@ +/** + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2010, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ +package ch.qos.logback.core.rolling + +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import ch.qos.logback.core.util.Compare +import ch.qos.logback.core.util.CoreTestConstants +import ch.qos.logback.core.encoder.EchoEncoder + +class TimeBasedRolling2Test extends RollingScaffolding { + + private[rolling] var rfa1: RollingFileAppender[AnyRef] = new RollingFileAppender[AnyRef] + private[rolling] var tbrp1: TimeBasedRollingPolicy[AnyRef] = new TimeBasedRollingPolicy[AnyRef] + private[rolling] var encoder: EchoEncoder[AnyRef] = new EchoEncoder[AnyRef] + + @Before + def setUp: Unit = { + setUpScaffolding + } + + private[rolling] def initRFA(rfa: RollingFileAppender[AnyRef], filename: String): Unit = { + rfa.setContext(context) + rfa.setEncoder(encoder) + if (filename != null) { + rfa.setFile(filename) + } + } + + private[rolling] def initTRBP(rfa: RollingFileAppender[AnyRef], tbrp: TimeBasedRollingPolicy[AnyRef], filenamePattern: String, givenTime: Long): Unit = { + tbrp.setContext(context) + tbrp.setFileNamePattern(filenamePattern) + tbrp.setParent(rfa) + tbrp.timeBasedFileNamingAndTriggeringPolicy = new DefaultTimeBasedFileNamingAndTriggeringPolicy[AnyRef] + tbrp.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(givenTime) + rfa.setRollingPolicy(tbrp) + tbrp.start + rfa.start + } + + def genericTest(testId: String, compressionSuffix: String): Unit = { + val withCompression = compressionSuffix.length > 0 + initRFA(rfa1, null); + println(randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}" + compressionSuffix ) + + initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + + DATE_PATTERN_WITH_SECONDS + "}" + compressionSuffix, currentTime); + + // compute the current filename + addExpectedFileName_ByDate(randomOutputDir, testId, getDateOfCurrentPeriodsStart, withCompression); + + incCurrentTime(1100); + tbrp1.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(currentTime); + + for (i <- 0 until 3) { + rfa1.doAppend("Hello---" + i); + addExpectedFileNamedIfItsTime_ByDate(randomOutputDir, testId, withCompression && (i !=2)) + incCurrentTime(500); + tbrp1.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(currentTime) + if(withCompression) + waitForCompression(tbrp1) + } + + var i = 0; + for (fn <- expectedFilenameList) { + val suffix: String = if(withCompression) addGZIfNotLast(i, compressionSuffix) else "" + val witnessFileName: String = CoreTestConstants.TEST_DIR_PREFIX + "witness/rolling/tbr-" + testId + "." + i.toString + suffix + assertTrue(Compare.compare(fn, witnessFileName)); + i += 1 + } + + } + + /** + * Test rolling without compression, file option left blank, no stop/start + */ + @Test + def noCompression_FileBlank_NoRestart_1 = { + genericTest("test1", "") + } + + /** + * With compression, file option left blank, no stop/restart + */ + @Test + def withCompression_FileBlank_NoRestart_2 = { + genericTest("test2", ".gz"); + } + + +} \ No newline at end of file diff --git a/logback-examples/pom.xml b/logback-examples/pom.xml index 2428f24..48b65ba 100644 --- a/logback-examples/pom.xml +++ b/logback-examples/pom.xml @@ -5,7 +5,7 @@ ch.qos.logback logback-parent - 0.9.27 + 0.9.28-SNAPSHOT 4.0.0 diff --git a/logback-site/pom.xml b/logback-site/pom.xml index 2c2b192..a1707da 100644 --- a/logback-site/pom.xml +++ b/logback-site/pom.xml @@ -3,7 +3,7 @@ ch.qos.logback logback-parent - 0.9.27 + 0.9.28-SNAPSHOT 4.0.0 diff --git a/logback-site/src/site/pages/documentation.html b/logback-site/src/site/pages/documentation.html index bdfcf72..5c07e09 100644 --- a/logback-site/src/site/pages/documentation.html +++ b/logback-site/src/site/pages/documentation.html @@ -90,12 +90,8 @@

  • SLF4J - and Logback projects, by C. Gülcü and S. Pennec - (Jazoon presentation with audio). If the previous link does not - work, please try the back - up. + href="http://beta.parleys.com/#id=1701&st=5&sl=1">Devoxx-2009 + video presentation, by C. Gülcü
  • +

    January xx, 2011 - Release of version 0.9.28

    + +
    +

    December 22nd, 2010 - Release of version 0.9.27

    Added a new section in the documentation about ch.qos.logback logback-parent - 0.9.27 + 0.9.28-SNAPSHOT pom Logback-Parent @@ -34,7 +34,7 @@ 1.6.1 4.7 2.5.10 - + 2.7.7 1.1.0 @@ -154,10 +154,17 @@ 1.0 - javax.servlet - servlet-api - 2.5 + javax.servlet + servlet-api + 2.5 + + + org.scala-lang + scala-library + ${scala.version} + + @@ -225,6 +232,7 @@ target/site/dist/ + diff --git a/src/main/header.txt b/src/main/header.txt index 56d0e7b..cf0e315 100644 --- a/src/main/header.txt +++ b/src/main/header.txt @@ -1,6 +1,6 @@ Logback: the generic, reliable, fast and flexible logging framework. -Copyright (C) 1999-2009, QOS.ch. All rights reserved. +Copyright (C) 1999-2010, QOS.ch. All rights reserved. This program and the accompanying materials are dual-licensed under either the terms of the Eclipse Public License v1.0 as published by ----------------------------------------------------------------------- Summary of changes: logback-access/pom.xml | 2 +- logback-classic/pom.xml | 2 +- .../classic/turbo/ReconfigureOnChangeTest.java | 2 +- logback-core/pom.xml | 354 +++++++++++--------- .../test/scala/ch/qos/logback/core/rolling/A.scala | 41 +++ .../logback/core/rolling/RollingScaffolding.scala | 85 +++++ .../core/rolling/TimeBasedRolling2Test.scala | 104 ++++++ logback-examples/pom.xml | 2 +- logback-site/pom.xml | 2 +- logback-site/src/site/pages/documentation.html | 8 +- logback-site/src/site/pages/news.html | 4 + pom.xml | 18 +- src/main/header.txt | 2 +- 13 files changed, 445 insertions(+), 181 deletions(-) create mode 100644 logback-core/src/test/scala/ch/qos/logback/core/rolling/A.scala create mode 100644 logback-core/src/test/scala/ch/qos/logback/core/rolling/RollingScaffolding.scala create mode 100644 logback-core/src/test/scala/ch/qos/logback/core/rolling/TimeBasedRolling2Test.scala hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From noreply-jira at qos.ch Tue Dec 28 18:59:52 2010 From: noreply-jira at qos.ch (Jeff Jensen (JIRA)) Date: Tue, 28 Dec 2010 18:59:52 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBCORE-188) Log Rotation/Gzip process leaving .tmp files behind In-Reply-To: <1972951794.1292615931253.JavaMail.ceki@pixie> Message-ID: <347158247.1293559192347.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-188?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11918#action_11918 ] Jeff Jensen commented on LBCORE-188: ------------------------------------ I also see the .tmp files at my current customer. > Log Rotation/Gzip process leaving .tmp files behind > --------------------------------------------------- > > Key: LBCORE-188 > URL: http://jira.qos.ch/browse/LBCORE-188 > Project: logback-core > Issue Type: Bug > Components: Rolling > Affects Versions: 0.9.26 > Reporter: Bert B-L > Assignee: Logback dev list > > We are seeing logback leave .tmp files behind in the log directory, presumably due to a hiccup during log rotation or gzip. > Size > 2365956 Dec 11 00:00 statsreceiver.log.2010-12-10.gz > 2679618 Dec 12 00:01 statsreceiver.log.2010-12-11.gz > 9190879942 Dec 12 04:00 statsreceiver-debug.log23124507802228260.tmp > 2542799 Dec 13 00:00 statsreceiver.log.2010-12-12.gz > 9137740366 Dec 13 04:00 statsreceiver-debug.log23210907242250260.tmp > 543937393 Dec 13 20:07 statsreceiver-debug.log.2010-12-13_19:00.gz > 548781049 Dec 13 22:07 statsreceiver-debug.log.2010-12-13_21:00.gz > 2284216 Dec 14 00:00 statsreceiver.log.2010-12-13.gz > 8127562 Dec 15 00:00 statsreceiver.log.2010-12-14.gz > 19067117496 Dec 15 13:00 statsreceiver-debug.log23416102512001260.tmp > 18177324477 Dec 15 16:00 statsreceiver-debug.log23426920509229260.tmp > 2257423 Dec 15 23:00 statsreceiver-debug.log.2010-12-15_22:00.gz > The logback jar versions are: > WEB-INF/lib/logback-classic-0.9.26.jar > WEB-INF/lib/logback-core-0.9.26.jar > There is only a single application writing to those files, though it is conceivable that the .tmp droppings correlate to restarts of that application. > If this is expected on application restarts, could logback start gzip'ing them again when it comes back? > Here is the logback.xml file: > > > > ${logdir:-.}/${prog:-unknown}.log > true > > > warn > > > > ${logdir:-.}/${prog:-unknown}.log.%d{yyyy-MM-dd}.gz > 7 > > > %-30(%d{yyyy-MM-dd HH:mm:ss} %.-1level :) %m Context:[%X{GTNDC_INFO}]%n > > > > ${logdir:-.}/${prog:-unknown}-debug.log > true > > > debug > > > > ${logdir:-.}/${prog:-unknown}-debug.log.%d{yyyy-MM-dd_HH:00}.gz > 36 > > > %-60(%d{yyyy-MM-dd HH:mm:ss} [%thread] %.-1level :) %m Context:[%X{GTNDC_INFO}]%n > > > > > > > > -- 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 From git-noreply at pixie.qos.ch Tue Dec 28 19:36:26 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Tue, 28 Dec 2010 19:36:26 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.27-2-ga0a585a Message-ID: <20101228183627.79A7931746C@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via a0a585a04d230d2fd8d3f3a68c2faf40dafdabe9 (commit) from 4a792d8efd47548dedbf838ef5d32531e9a928c8 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=a0a585a04d230d2fd8d3f3a68c2faf40dafdabe9 http://github.com/ceki/logback/commit/a0a585a04d230d2fd8d3f3a68c2faf40dafdabe9 commit a0a585a04d230d2fd8d3f3a68c2faf40dafdabe9 Author: Ceki Gulcu Date: Tue Dec 28 19:36:44 2010 +0100 scala version of TimeBasedRollingTest now passes diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingTest.java index 2cf9201..d327a28 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingTest.java @@ -230,7 +230,10 @@ public class TimeBasedRollingTest extends ScaffoldingForRollingTests { tbrp2.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(currentTime); } + System.out.println("Before "+expectedFilenameList); massageExpectedFilesToCorresponToCurrentTarget("test4.log"); + System.out.println("After "+expectedFilenameList); + int i = 0; for (String fn : expectedFilenameList) { diff --git a/logback-core/src/test/scala/ch/qos/logback/core/rolling/RollingScaffolding.scala b/logback-core/src/test/scala/ch/qos/logback/core/rolling/RollingScaffolding.scala index ed78e3e..6b68d2d 100644 --- a/logback-core/src/test/scala/ch/qos/logback/core/rolling/RollingScaffolding.scala +++ b/logback-core/src/test/scala/ch/qos/logback/core/rolling/RollingScaffolding.scala @@ -31,6 +31,10 @@ trait RollingScaffolding { protected var nextRolloverThreshold: Long = 0; protected var expectedFilenameList: List[String] = Nil + val FILE_OPTION_SET = true + val FILE_OPTION_BLANK = false + + def setUpScaffolding: Unit = { context.setName("test") cal.set(Calendar.MILLISECOND, 333) @@ -78,8 +82,21 @@ trait RollingScaffolding { } private[rolling] def waitForCompression(tbrp: TimeBasedRollingPolicy[AnyRef]): Unit = { - if (tbrp.future != null && !tbrp.future.isDone) { - tbrp.future.get(200, TimeUnit.MILLISECONDS) - } + if (tbrp.future != null && !tbrp.future.isDone) { + tbrp.future.get(200, TimeUnit.MILLISECONDS) } - } \ No newline at end of file + } + + private[rolling] def testId2FileName(testId: String): String = { + return randomOutputDir + testId + ".log" + } + + // ========================================================================= + // utility methods + // ========================================================================= + private[rolling] def massageExpectedFilesToCorresponToCurrentTarget(file: String): Unit = { + expectedFilenameList = expectedFilenameList.dropRight(1) + expectedFilenameList += (randomOutputDir + file) + } + +} \ No newline at end of file diff --git a/logback-core/src/test/scala/ch/qos/logback/core/rolling/TimeBasedRolling2Test.scala b/logback-core/src/test/scala/ch/qos/logback/core/rolling/TimeBasedRolling2Test.scala index 06bd4af..6a90b50 100644 --- a/logback-core/src/test/scala/ch/qos/logback/core/rolling/TimeBasedRolling2Test.scala +++ b/logback-core/src/test/scala/ch/qos/logback/core/rolling/TimeBasedRolling2Test.scala @@ -19,11 +19,15 @@ import org.junit.Test import ch.qos.logback.core.util.Compare import ch.qos.logback.core.util.CoreTestConstants import ch.qos.logback.core.encoder.EchoEncoder +import java.io.File class TimeBasedRolling2Test extends RollingScaffolding { private[rolling] var rfa1: RollingFileAppender[AnyRef] = new RollingFileAppender[AnyRef] private[rolling] var tbrp1: TimeBasedRollingPolicy[AnyRef] = new TimeBasedRollingPolicy[AnyRef] + private[rolling] var rfa2: RollingFileAppender[AnyRef] = new RollingFileAppender[AnyRef] + private[rolling] var tbrp2: TimeBasedRollingPolicy[AnyRef] = new TimeBasedRollingPolicy[AnyRef] + private[rolling] var encoder: EchoEncoder[AnyRef] = new EchoEncoder[AnyRef] @Before @@ -50,11 +54,10 @@ class TimeBasedRolling2Test extends RollingScaffolding { rfa.start } - def genericTest(testId: String, compressionSuffix: String): Unit = { + def genericTest(testId: String, compressionSuffix: String, fileOptionIsSet: Boolean, waitDuration: Int): Unit = { val withCompression = compressionSuffix.length > 0 - initRFA(rfa1, null); - println(randomOutputDir + testId + "-%d{" - + DATE_PATTERN_WITH_SECONDS + "}" + compressionSuffix ) + val fileName = if (fileOptionIsSet) testId2FileName(testId) else null; + initRFA(rfa1, fileName); initTRBP(rfa1, tbrp1, randomOutputDir + testId + "-%d{" + DATE_PATTERN_WITH_SECONDS + "}" + compressionSuffix, currentTime); @@ -67,16 +70,25 @@ class TimeBasedRolling2Test extends RollingScaffolding { for (i <- 0 until 3) { rfa1.doAppend("Hello---" + i); - addExpectedFileNamedIfItsTime_ByDate(randomOutputDir, testId, withCompression && (i !=2)) + addExpectedFileNamedIfItsTime_ByDate(randomOutputDir, testId, withCompression && (i != 2)) incCurrentTime(500); tbrp1.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(currentTime) - if(withCompression) + if (withCompression) waitForCompression(tbrp1) } + rfa1.stop + + if (waitDuration != 0) { + doRestart(testId, fileOptionIsSet, waitDuration); + } + + if (fileOptionIsSet) { + massageExpectedFilesToCorresponToCurrentTarget(testId + ".log") + } var i = 0; for (fn <- expectedFilenameList) { - val suffix: String = if(withCompression) addGZIfNotLast(i, compressionSuffix) else "" + val suffix: String = if (withCompression) addGZIfNotLast(i, compressionSuffix) else "" val witnessFileName: String = CoreTestConstants.TEST_DIR_PREFIX + "witness/rolling/tbr-" + testId + "." + i.toString + suffix assertTrue(Compare.compare(fn, witnessFileName)); i += 1 @@ -84,21 +96,65 @@ class TimeBasedRolling2Test extends RollingScaffolding { } - /** - * Test rolling without compression, file option left blank, no stop/start - */ + def doRestart(testId: String, fileOptionIsSet: Boolean, waitDuration: Int) { + // change the timestamp of the currently actively file + var activeFile: File = new File(rfa1.getFile) + activeFile.setLastModified(currentTime) + + incCurrentTime(waitDuration) + + val fileName = if (fileOptionIsSet) testId2FileName(testId) else null; + initRFA(rfa2, fileName) + initTRBP(rfa2, tbrp2, randomOutputDir + testId + "-%d{" + DATE_PATTERN_WITH_SECONDS + "}", currentTime) + for (i <- 0 until 3) { + rfa2.doAppend("World---" + i) + addExpectedFileNamedIfItsTime_ByDate(randomOutputDir, testId, false) + incCurrentTime(100) + tbrp2.timeBasedFileNamingAndTriggeringPolicy.setCurrentTime(currentTime) + } + } + + val NO_RESTART = 0 + val WITH_RESTART = 1 + val WITH_RESTART_AND_LONG_WAIT = 2000 + @Test def noCompression_FileBlank_NoRestart_1 = { - genericTest("test1", "") + genericTest("test1", "", FILE_OPTION_BLANK, NO_RESTART) } - /** - * With compression, file option left blank, no stop/restart - */ @Test def withCompression_FileBlank_NoRestart_2 = { - genericTest("test2", ".gz"); + genericTest("test2", ".gz", FILE_OPTION_BLANK, NO_RESTART); + } + + @Test + def noCompression_FileBlank_StopRestart_3 = { + genericTest("test3", "", FILE_OPTION_BLANK, WITH_RESTART); + } + + @Test + def noCompression_FileSet_StopRestart_4 = { + genericTest("test4", "", FILE_OPTION_SET, WITH_RESTART); + } + + @Test + def noCompression_FileSet_StopRestart_WithLongWait_4B = { + genericTest("test4B", "", FILE_OPTION_SET, WITH_RESTART_AND_LONG_WAIT); } + @Test + def noCompression_FileSet_NoRestart_5 = { + genericTest("test5", "", FILE_OPTION_SET, NO_RESTART); + } + @Test + def withCompression_FileSet_NoRestart_6 = { + genericTest("test6", ".gz", FILE_OPTION_SET, NO_RESTART); + } + + @Test + def withMissingTargetDir = { + genericTest("missingTargetDir", "", FILE_OPTION_SET, NO_RESTART); + } } \ No newline at end of file diff --git a/logback-core/src/test/witness/rolling/tbr-missingTargetDir.0 b/logback-core/src/test/witness/rolling/tbr-missingTargetDir.0 new file mode 100644 index 0000000..e69de29 diff --git a/logback-core/src/test/witness/rolling/tbr-missingTargetDir.1 b/logback-core/src/test/witness/rolling/tbr-missingTargetDir.1 new file mode 100644 index 0000000..aea23e8 --- /dev/null +++ b/logback-core/src/test/witness/rolling/tbr-missingTargetDir.1 @@ -0,0 +1,2 @@ +Hello---0 +Hello---1 \ No newline at end of file diff --git a/logback-core/src/test/witness/rolling/tbr-missingTargetDir.2 b/logback-core/src/test/witness/rolling/tbr-missingTargetDir.2 new file mode 100644 index 0000000..c32a130 --- /dev/null +++ b/logback-core/src/test/witness/rolling/tbr-missingTargetDir.2 @@ -0,0 +1 @@ +Hello---2 ----------------------------------------------------------------------- Summary of changes: .../logback/core/rolling/TimeBasedRollingTest.java | 3 + .../logback/core/rolling/RollingScaffolding.scala | 25 +++++- .../core/rolling/TimeBasedRolling2Test.scala | 86 ++++++++++++++++---- .../{tbr-test1.0 => tbr-missingTargetDir.0} | 0 .../{tbr-test4B.1 => tbr-missingTargetDir.1} | 0 .../{tbr-test1.2 => tbr-missingTargetDir.2} | 0 6 files changed, 95 insertions(+), 19 deletions(-) copy logback-core/src/test/witness/rolling/{tbr-test1.0 => tbr-missingTargetDir.0} (100%) copy logback-core/src/test/witness/rolling/{tbr-test4B.1 => tbr-missingTargetDir.1} (100%) copy logback-core/src/test/witness/rolling/{tbr-test1.2 => tbr-missingTargetDir.2} (100%) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From noreply-jira at qos.ch Wed Dec 29 14:16:52 2010 From: noreply-jira at qos.ch (Joern Huxhorn (JIRA)) Date: Wed, 29 Dec 2010 14:16:52 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBCORE-160) TimeBasedRollingWithArchiveRemovalTest keeps failing In-Reply-To: <231922236.1280239037460.JavaMail.ceki@pixie> Message-ID: <1990096372.1293628612345.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-160?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11919#action_11919 ] Joern Huxhorn commented on LBCORE-160: -------------------------------------- The last few builds didn't fail anymore but I'd like to keep this issue open for some time since the failing wasn't very reliable anyway. I'll keep an eye on this and will let you know how this develops... > TimeBasedRollingWithArchiveRemovalTest keeps failing > ---------------------------------------------------- > > Key: LBCORE-160 > URL: http://jira.qos.ch/browse/LBCORE-160 > Project: logback-core > Issue Type: Bug > Components: Appender > Affects Versions: unspecified > Environment: Apache Maven 2.2.1 (r801777; 2009-08-06 21:16:01+0200) > Java version: 1.6.0_20 > Java home: /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home > Default locale: en_US, platform encoding: MacRoman > OS name: "mac os x" version: "10.6.4" arch: "x86_64" Family: "mac" > Reporter: Joern Huxhorn > Assignee: Logback dev list > > Revision: 15b5239b5d583a86877b79e77336729317cf2dc0 > The following error happens every time I try to build Logback: > dailySizeBasedRollover(ch.qos.logback.core.rolling.TimeBasedRollingWithArchiveRemovalTest) Time elapsed: 0.443 sec <<< ERROR! > java.util.concurrent.TimeoutException > at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228) > at java.util.concurrent.FutureTask.get(FutureTask.java:91) > at ch.qos.logback.core.rolling.TimeBasedRollingWithArchiveRemovalTest.waitForCompression(TimeBasedRollingWithArchiveRemovalTest.java:216) > at ch.qos.logback.core.rolling.TimeBasedRollingWithArchiveRemovalTest.doRollover(TimeBasedRollingWithArchiveRemovalTest.java:206) > at ch.qos.logback.core.rolling.TimeBasedRollingWithArchiveRemovalTest.dailySizeBasedRollover(TimeBasedRollingWithArchiveRemovalTest.java:146) > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) > at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) > at java.lang.reflect.Method.invoke(Method.java:597) > at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) > at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) > at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) > at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) > at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) > at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) > at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) > at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) > at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) > at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) > at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) > at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) > at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) > at org.junit.runners.ParentRunner.run(ParentRunner.java:236) > at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62) > at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140) > at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127) > at org.apache.maven.surefire.Surefire.run(Surefire.java:177) > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) > at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) > at java.lang.reflect.Method.invoke(Method.java:597) > at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345) > at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009) -- 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 From jhuxhorn at googlemail.com Wed Dec 29 15:08:26 2010 From: jhuxhorn at googlemail.com (Joern Huxhorn) Date: Wed, 29 Dec 2010 15:08:26 +0100 Subject: [logback-dev] How about switching build to Gradle? Message-ID: I've recently switched the build of sulky and Lilith from Maven to Gradle and it's a real pleasure to use. Hibernate and parts of Spring have switched, too. Take a look at http://blogs.jfrog.org/2010/07/to-build-or-not-to-be-seminar-videos.html and/or http://vimeo.com/16571738 for a nice introduction into Gradle. http://github.com/huxi/sulky contains the following 5 files: build.gradle config.gradle dependencyDefinitions.gradle projectDependencies.gradle settings.gradle build.gradle is the actual build file and simply includes dependencyDefinitions.gradle, projectDependencies.gradle and config.gradle. dependencyDefinitions.gradle contains the definitions of all external dependencies - comparable to a dependencyManagement section in a parent pom. projectDependencies.gradle contains the basic definition of the sub-modules (and should probably be renamed accordingly ;)), including the dependencies of each sub-module. config.gradle contains the actual configuration of the build, i.e. anything that isn't already handled by the default Gradle build, including everything necessary to perform a release into oss.sonatype.org maven repository. settings.gradle is a currently mandatory file that defines all sub-modules in a multi-module project. http://github.com/huxi/lilith contains the same general structures but is handling more complex tasks, e.g. sub-sub-modules, fatjar... I'm not saying that this is a perfect setup. You have much more freedom in Gradle than in Maven about the way you are structuring your build. It's merely meant as a functional example of a non-trivial multi-module project. Gradle offers major improvements in build speed (very intelligent up-to-date detection that makes clean unnecessary, vastly improved test execution) and saves a lot of time during release. In contrast to Maven you only have to change a single file instead of one pom in each sub-module. I'm currently still keeping the Maven build in place but I do this only because Gradle isn't yet supported by Sonar, something that is supposed to change with Sonar 2.6 due in february. See (and vote) http://jira.codehaus.org/browse/GRADLE-888 . I'd also like to point out that Gradle doesn't offer something like the Maven site plugin, yet. Beside that, using Gradle is pure pleasure. The switch wasn't always easy, mainly because PGP signing was still missing (so I wrote a plugin to support it ;)), but the people on the #gradle channel over at irc.codehaus.org are very, very helpful. Let me know what you think. I'd certainly offer help migrating SLF4J & Logback if needed. Cheers, Joern. From git-noreply at pixie.qos.ch Wed Dec 29 19:24:12 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Wed, 29 Dec 2010 19:24:12 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.27-3-g8c7ac8c Message-ID: <20101229182413.168043174A1@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via 8c7ac8c165d45d2de55c7f0122a19d573717e512 (commit) from a0a585a04d230d2fd8d3f3a68c2faf40dafdabe9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=8c7ac8c165d45d2de55c7f0122a19d573717e512 http://github.com/ceki/logback/commit/8c7ac8c165d45d2de55c7f0122a19d573717e512 commit 8c7ac8c165d45d2de55c7f0122a19d573717e512 Author: Ceki Gulcu Date: Wed Dec 29 19:18:42 2010 +0100 trying to paralleize tests diff --git a/logback-classic/pom.xml b/logback-classic/pom.xml index ed392a5..b939132 100644 --- a/logback-classic/pom.xml +++ b/logback-classic/pom.xml @@ -296,9 +296,11 @@ org.apache.maven.plugins maven-surefire-plugin + ${surefire.version} once + classes plain false diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java b/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java index a84c9e2..fadaec3 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java @@ -17,7 +17,10 @@ import ch.qos.logback.core.util.CoreTestConstants; public class ClassicTestConstants { final static public String ISO_REGEX = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2},\\d{3}"; - final static public String NAKED_MAIN_REGEX = "[mM]ain(\\sThread)?"; + final static public String NAKED_MAIN_REGEX = "([mM]ain|pool-\\d-)([Tt]hread)?"; + + //pool-1-thread-47] + final static public String MAIN_REGEX = "\\[" + NAKED_MAIN_REGEX + "\\]"; final static public String INPUT_PREFIX = "src/test/input/"; final static public String JORAN_INPUT_PREFIX = INPUT_PREFIX + "joran/"; diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java index 34b2ce6..2c1762f 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/PatternLayoutTest.java @@ -82,10 +82,11 @@ public class PatternLayoutTest extends AbstractPatternLayoutBaseTest rulesMap = new HashMap(); rulesMap.put(new Pattern("x"), new NOPAction()); rulesMap.put(new Pattern("x/include"), new IncludeAction()); - rulesMap.put(new Pattern("x/stack"), new StackAction()); + rulesMap.put(new Pattern("x/stack"), stackAction); tc = new TrivialConfigurator(rulesMap); tc.setContext(context); @@ -100,7 +102,7 @@ public class IncludeActionTest { System.clearProperty(INCLUDE_KEY); System.clearProperty(SECOND_FILE_KEY); System.clearProperty(SUB_FILE_KEY); - StackAction.reset(); + //StackAction.reset(); } @Test @@ -195,7 +197,7 @@ public class IncludeActionTest { witness.push("a"); witness.push("b"); witness.push("c"); - assertEquals(witness, StackAction.stack); + assertEquals(witness, stackAction.getStack()); } @Test @@ -209,7 +211,7 @@ public class IncludeActionTest { void verifyConfig(String[] expected) { Stack witness = new Stack(); witness.addAll(Arrays.asList(expected)); - assertEquals(witness, StackAction.stack); + assertEquals(witness, stackAction.getStack()); } } diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/StackAction.java b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/StackAction.java index e198345..eb4701e 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/StackAction.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/action/ext/StackAction.java @@ -22,19 +22,23 @@ import ch.qos.logback.core.joran.action.Action; import ch.qos.logback.core.joran.spi.InterpretationContext; - public class StackAction extends Action { - public static Stack stack = new Stack(); - public void begin(InterpretationContext ec, String name, Attributes attributes) { - stack.push(attributes.getValue("name")); - } + Stack stack = new Stack(); + + public Stack getStack() { + return stack; + } + + public void begin(InterpretationContext ec, String name, Attributes attributes) { + stack.push(attributes.getValue("name")); + } - public void end(InterpretationContext ec, String name) { - } + public void end(InterpretationContext ec, String name) { + } - static public void reset() { - stack.clear(); - } +// static public void reset() { +// stack.clear(); +// } } diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/conditional/IfThenElseAndIncludeCompositionTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/conditional/IfThenElseAndIncludeCompositionTest.java index c354999..5cd9447 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/conditional/IfThenElseAndIncludeCompositionTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/conditional/IfThenElseAndIncludeCompositionTest.java @@ -50,13 +50,15 @@ public class IfThenElseAndIncludeCompositionTest { static final String NESTED_INCLUDE_FILE = CONDITIONAL_DIR_PREFIX+"nestedInclude.xml"; static final String THEN_FILE_TO_INCLUDE = CONDITIONAL_DIR_PREFIX+"includedA.xml"; static final String ELSE_FILE_TO_INCLUDE = CONDITIONAL_DIR_PREFIX+"includedB.xml"; - + + StackAction stackAction = new StackAction(); + @Before public void setUp() throws Exception { HashMap rulesMap = new HashMap(); rulesMap.put(new Pattern("x"), new NOPAction()); - rulesMap.put(new Pattern("x/stack"), new StackAction()); + rulesMap.put(new Pattern("x/stack"), stackAction); rulesMap.put(new Pattern("*/if"), new IfAction()); rulesMap.put(new Pattern("*/if/then"), new ThenAction()); rulesMap.put(new Pattern("*/if/then/*"), new NOPAction()); @@ -72,7 +74,7 @@ public class IfThenElseAndIncludeCompositionTest { public void tearDown() throws Exception { StatusPrinter.printInCaseOfErrorsOrWarnings(context); context = null; - StackAction.reset(); + //StackAction.reset(); } @Test @@ -87,7 +89,7 @@ public class IfThenElseAndIncludeCompositionTest { void verifyConfig(String[] expected) { Stack witness = new Stack(); witness.addAll(Arrays.asList(expected)); - assertEquals(witness, StackAction.stack); + assertEquals(witness, stackAction.getStack()); } } diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/conditional/IfThenElseTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/conditional/IfThenElseTest.java index 3a414e8..8ab6af3 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/conditional/IfThenElseTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/conditional/IfThenElseTest.java @@ -46,12 +46,14 @@ public class IfThenElseTest { static final String CONDITIONAL_DIR_PREFIX = CoreTestConstants.JORAN_INPUT_PREFIX + "conditional/"; - + + StackAction stackAction = new StackAction(); + @Before public void setUp() throws Exception { HashMap rulesMap = new HashMap(); rulesMap.put(new Pattern("x"), new NOPAction()); - rulesMap.put(new Pattern("x/stack"), new StackAction()); + rulesMap.put(new Pattern("x/stack"), stackAction); rulesMap.put(new Pattern("*/if"), new IfAction()); rulesMap.put(new Pattern("*/if/then"), new ThenAction()); rulesMap.put(new Pattern("*/if/then/*"), new NOPAction()); @@ -65,7 +67,7 @@ public class IfThenElseTest { @After public void tearDown() throws Exception { StatusPrinter.printIfErrorsOccured(context); - StackAction.reset(); + //StackAction.reset(); } @Test @@ -107,7 +109,7 @@ public class IfThenElseTest { void verifyConfig(String[] expected) { Stack witness = new Stack(); witness.addAll(Arrays.asList(expected)); - assertEquals(witness, StackAction.stack); + assertEquals(witness, stackAction.getStack()); } diff --git a/pom.xml b/pom.xml index 992972d..6341755 100755 --- a/pom.xml +++ b/pom.xml @@ -32,9 +32,10 @@ 1.6.1 - 4.7 + 4.8.2 2.5.10 - 2.7.7 + 2.7.7 + 2.6 1.1.0 ----------------------------------------------------------------------- Summary of changes: logback-classic/pom.xml | 2 + .../qos/logback/classic/ClassicTestConstants.java | 5 +++- .../ch/qos/logback/classic/PatternLayoutTest.java | 3 +- logback-core/pom.xml | 4 +++ .../logback/core/appender/ConsoleAppenderTest.java | 6 ++-- .../core/joran/action/IncludeActionTest.java | 10 +++++--- .../logback/core/joran/action/ext/StackAction.java | 24 +++++++++++-------- .../IfThenElseAndIncludeCompositionTest.java | 10 +++++--- .../core/joran/conditional/IfThenElseTest.java | 10 +++++--- pom.xml | 5 ++- 10 files changed, 50 insertions(+), 29 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From git-noreply at pixie.qos.ch Thu Dec 30 01:19:46 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Thu, 30 Dec 2010 01:19:46 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.27-4-gd66cfee Message-ID: <20101230001946.635AC3174AF@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via d66cfee00547c4ca2b309dcae5f8e905f6f0a00d (commit) from 8c7ac8c165d45d2de55c7f0122a19d573717e512 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=d66cfee00547c4ca2b309dcae5f8e905f6f0a00d http://github.com/ceki/logback/commit/d66cfee00547c4ca2b309dcae5f8e905f6f0a00d commit d66cfee00547c4ca2b309dcae5f8e905f6f0a00d Author: Ceki Gulcu Date: Thu Dec 30 01:17:11 2010 +0100 parallelizing tests diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java b/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java index fadaec3..fa8a260 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/ClassicTestConstants.java @@ -17,9 +17,9 @@ import ch.qos.logback.core.util.CoreTestConstants; public class ClassicTestConstants { final static public String ISO_REGEX = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2},\\d{3}"; - final static public String NAKED_MAIN_REGEX = "([mM]ain|pool-\\d-)([Tt]hread)?"; + //pool-1-thread-47 + final static public String NAKED_MAIN_REGEX = "([mM]ain|pool-\\d-)([Tt]hread)?(-\\d{1,3})?"; - //pool-1-thread-47] final static public String MAIN_REGEX = "\\[" + NAKED_MAIN_REGEX + "\\]"; final static public String INPUT_PREFIX = "src/test/input/"; diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java index 45cf3b9..b5b6935 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertTrue; import java.util.Map; +import ch.qos.logback.core.testUtil.RandomUtil; import org.junit.Test; import org.slf4j.MDC; import org.slf4j.Marker; @@ -40,6 +41,9 @@ public class SocketAppenderTest { static final int SLEEP_AFTER_LOG = 100; int port = 4561; + int diff = RandomUtil.getPositiveInt(); + String mdcKey = "key"+diff; + LoggerContext lc = new LoggerContext(); LoggerContext serverLC = new LoggerContext(); ListAppender la = new ListAppender(); @@ -116,7 +120,7 @@ public class SocketAppenderTest { Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - MDC.put("key", "testValue"); + MDC.put(mdcKey, "testValue"); logger.debug("test msg"); Thread.sleep(SLEEP_AFTER_LOG); @@ -128,7 +132,7 @@ public class SocketAppenderTest { ILoggingEvent remoteEvent = la.list.get(0); Map MDCPropertyMap = remoteEvent.getMDCPropertyMap(); - assertEquals("testValue", MDCPropertyMap.get("key")); + assertEquals("testValue", MDCPropertyMap.get(mdcKey)); assertNull(remoteEvent.getCallerData()); } @@ -186,10 +190,10 @@ public class SocketAppenderTest { Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); - MDC.put("key", "testValue"); + MDC.put(mdcKey, "testValue"); logger.debug("test msg"); - MDC.put("key", "updatedTestValue"); + MDC.put(mdcKey, "updatedTestValue"); logger.debug("test msg 2"); Thread.sleep(SLEEP_AFTER_LOG); @@ -204,7 +208,7 @@ public class SocketAppenderTest { // the updated MDC property. ILoggingEvent remoteEvent = la.list.get(1); Map MDCPropertyMap = remoteEvent.getMDCPropertyMap(); - assertEquals("updatedTestValue", MDCPropertyMap.get("key")); + assertEquals("updatedTestValue", MDCPropertyMap.get(mdcKey)); } @Test diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java index f39f1f3..fa4dd7d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/pattern/ConverterTest.java @@ -100,6 +100,7 @@ public class ConverterTest { DynamicConverter converter = new ThreadConverter(); StringBuilder buf = new StringBuilder(); converter.write(buf, le); + System.out.println(buf.toString()); String regex = ClassicTestConstants.NAKED_MAIN_REGEX; assertTrue(buf.toString().matches(regex)); } ----------------------------------------------------------------------- Summary of changes: .../qos/logback/classic/ClassicTestConstants.java | 4 ++-- .../logback/classic/net/SocketAppenderTest.java | 14 +++++++++----- .../qos/logback/classic/pattern/ConverterTest.java | 1 + 3 files changed, 12 insertions(+), 7 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From noreply-jira at qos.ch Thu Dec 30 11:15:51 2010 From: noreply-jira at qos.ch (Robert Elliot (JIRA)) Date: Thu, 30 Dec 2010 11:15:51 +0100 (CET) Subject: [logback-dev] [JIRA] Created: (LBCLASSIC-238) GEventEvaluator cannot be started Message-ID: <1298881971.1293704151398.JavaMail.ceki@pixie> GEventEvaluator cannot be started --------------------------------- Key: LBCLASSIC-238 URL: http://jira.qos.ch/browse/LBCLASSIC-238 Project: logback-classic Issue Type: Bug Affects Versions: 0.9.27 Reporter: Robert Elliot Assignee: Logback dev list Priority: Critical GEventEvaluator is fundamentally broken, because it overrides the start() method on EventEvaluatorBase but never sets EventEvaluatorBase's started field to true, so the isStarted() method on EventEvaluatorBase always returns false resulting in EvaluatorFilter's decide method always returning NEUTRAL. -- 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 From noreply-jira at qos.ch Thu Dec 30 14:38:51 2010 From: noreply-jira at qos.ch (Robert Elliot (JIRA)) Date: Thu, 30 Dec 2010 14:38:51 +0100 (CET) Subject: [logback-dev] [JIRA] Updated: (LBCLASSIC-238) GEventEvaluator cannot be started In-Reply-To: <1298881971.1293704151398.JavaMail.ceki@pixie> Message-ID: <1412559965.1293716331323.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCLASSIC-238?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Robert Elliot updated LBCLASSIC-238: ------------------------------------ Attachment: GEventEvaluatorTest.java Failing JUnit test case demonstrating the problem > GEventEvaluator cannot be started > --------------------------------- > > Key: LBCLASSIC-238 > URL: http://jira.qos.ch/browse/LBCLASSIC-238 > Project: logback-classic > Issue Type: Bug > Affects Versions: 0.9.27 > Reporter: Robert Elliot > Assignee: Logback dev list > Priority: Critical > Attachments: GEventEvaluatorTest.java > > > GEventEvaluator is fundamentally broken, because it overrides the start() method on EventEvaluatorBase but never sets EventEvaluatorBase's started field to true, so the isStarted() method on EventEvaluatorBase always returns false resulting in EvaluatorFilter's decide method always returning NEUTRAL. -- 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 From noreply-jira at qos.ch Thu Dec 30 15:16:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Thu, 30 Dec 2010 15:16:51 +0100 (CET) Subject: [logback-dev] [JIRA] Assigned: (LBCLASSIC-238) GEventEvaluator cannot be started In-Reply-To: <1298881971.1293704151398.JavaMail.ceki@pixie> Message-ID: <1040107261.1293718611387.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCLASSIC-238?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu reassigned LBCLASSIC-238: ------------------------------------ Assignee: Ceki Gulcu (was: Logback dev list) > GEventEvaluator cannot be started > --------------------------------- > > Key: LBCLASSIC-238 > URL: http://jira.qos.ch/browse/LBCLASSIC-238 > Project: logback-classic > Issue Type: Bug > Affects Versions: 0.9.27 > Reporter: Robert Elliot > Assignee: Ceki Gulcu > Priority: Critical > Attachments: GEventEvaluatorTest.java > > > GEventEvaluator is fundamentally broken, because it overrides the start() method on EventEvaluatorBase but never sets EventEvaluatorBase's started field to true, so the isStarted() method on EventEvaluatorBase always returns false resulting in EvaluatorFilter's decide method always returning NEUTRAL. -- 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 From git-noreply at pixie.qos.ch Thu Dec 30 15:42:16 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Thu, 30 Dec 2010 15:42:16 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.27-5-g0ee73e6 Message-ID: <20101230144216.B53CD3174E1@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via 0ee73e69b47e35deeaa9dc02d8f003d12a2f2e72 (commit) from d66cfee00547c4ca2b309dcae5f8e905f6f0a00d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=0ee73e69b47e35deeaa9dc02d8f003d12a2f2e72 http://github.com/ceki/logback/commit/0ee73e69b47e35deeaa9dc02d8f003d12a2f2e72 commit 0ee73e69b47e35deeaa9dc02d8f003d12a2f2e72 Author: Ceki Gulcu Date: Thu Dec 30 15:36:08 2010 +0100 temporarily abandoning attempt to parellize tests in logback-classic diff --git a/logback-classic/pom.xml b/logback-classic/pom.xml index b939132..b61e6d6 100644 --- a/logback-classic/pom.xml +++ b/logback-classic/pom.xml @@ -221,6 +221,24 @@ + org.scala-tools + maven-scala-plugin + 2.14.3 + + src/test/scala + + + + scala-test-compile + process-test-resources + + testCompile + + + + + + org.apache.maven.plugins maven-jar-plugin @@ -300,7 +318,6 @@ once - classes plain false diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java index eb2ba4f..2679c2f 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/SimpleSocketServer.java @@ -53,7 +53,7 @@ public class SimpleSocketServer extends Thread { private boolean closed = false; private ServerSocket serverSocket; private List socketNodeList = new ArrayList(); - + public static void main(String argv[]) throws Exception { int port = -1; if (argv.length == 2) { @@ -81,6 +81,7 @@ public class SimpleSocketServer extends Thread { serverSocket = new ServerSocket(port); while (!closed) { logger.info("Waiting to accept a new client."); + signalAlmostReadiness(); Socket socket = serverSocket.accept(); logger.info("Connected to client at " + socket.getInetAddress()); logger.info("Starting new socket node."); @@ -89,7 +90,6 @@ public class SimpleSocketServer extends Thread { socketNodeList.add(newSocketNode); } new Thread(newSocketNode).start(); - signalSocketNodeCreation(); } } catch (Exception e) { if(closed) { @@ -104,7 +104,7 @@ public class SimpleSocketServer extends Thread { * Signal another thread that we have established a conneciton * This is useful for testing purposes. */ - void signalSocketNodeCreation() { + void signalAlmostReadiness() { synchronized(this) { this.notifyAll(); } diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketNode.java b/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketNode.java index 96f389e..f5a6f36 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketNode.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/net/SocketNode.java @@ -48,7 +48,7 @@ public class SocketNode implements Runnable { ObjectInputStream ois; SocketAddress remoteSocketAddress; - static Logger logger = (Logger) LoggerFactory.getLogger(SocketNode.class); + Logger logger; boolean closed = false; SimpleSocketServer socketServer; @@ -57,6 +57,8 @@ public class SocketNode implements Runnable { this.socket = socket; remoteSocketAddress = socket.getRemoteSocketAddress(); this.context = context; + logger = context.getLogger(SocketNode.class); + try { ois = new ObjectInputStream(new BufferedInputStream(socket .getInputStream())); diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java index c6723de..b050772 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java @@ -44,7 +44,7 @@ public class LoggerPerfTest { @Test public void durationOfDisabledLogsWith_1_NOPFilter() { double avg = computeDurationOfDisabledLogsWith_1_NOPFilter(1, - NORMAL_RUN_LENGTH); + NORMAL_RUN_LENGTH); System.out.println("durationOfDisabledLogsWith_1_NOPFilter=" + avg); long referencePerf = 60; @@ -52,7 +52,7 @@ public class LoggerPerfTest { } double computeDurationOfDisabledLogsWith_1_NOPFilter(int numOfFilters, - long len) { + long len) { for (int i = 0; i < numOfFilters; i++) { lc.addTurboFilter(new NOPTurboFilter()); } @@ -81,6 +81,9 @@ public class LoggerPerfTest { lbLogger.setLevel(Level.OFF); for (long i = 0; i < len; i++) logger.isDebugEnabled(); + Thread.yield(); + for (long i = 0; i < len; i++) + logger.isDebugEnabled(); long start = System.nanoTime(); for (long i = 0; i < len; i++) @@ -102,6 +105,10 @@ public class LoggerPerfTest { lbLogger.setLevel(Level.OFF); for (long i = 0; i < len; i++) logger.debug("Toto"); + Thread.yield(); + for (long i = 0; i < len; i++) + logger.debug("Toto"); + Thread.yield(); long start = System.nanoTime(); for (long i = 0; i < len; i++) @@ -118,7 +125,7 @@ public class LoggerPerfTest { long referencePerf = 30; BogoPerf.assertDuration(avgDuration, referencePerf, - CoreConstants.REFERENCE_BIPS); + CoreConstants.REFERENCE_BIPS); } double computeDurationOfDisabledLog_1_Parameter(long len) { @@ -148,7 +155,7 @@ public class LoggerPerfTest { long referencePerf = 800; BogoPerf.assertDuration(avgDuration, referencePerf, - CoreConstants.REFERENCE_BIPS); + CoreConstants.REFERENCE_BIPS); } double computeDurationOfEnabledLog(long len) { @@ -201,14 +208,14 @@ public class LoggerPerfTest { double tolerance = threadCount * .125; // Very little thread contention // should occur in this test. double max = ((((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) * iterCount) - * tolerance; + * tolerance; double serialized = (((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) - * iterCount * threadCount; + * iterCount * threadCount; double actual = ((double) (end - start)) / NANOS_IN_ONE_SEC; System.out - .printf( - "Sleep duration: %,.4f seconds. Max expected: %,.4f seconds, Serialized: %,.4f\n", - actual, max, serialized); + .printf( + "Sleep duration: %,.4f seconds. Max expected: %,.4f seconds, Serialized: %,.4f\n", + actual, max, serialized); assertTrue("Exceeded maximum expected time.", actual < max); } diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java index f4a6d32..f6bdfba 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java @@ -22,9 +22,12 @@ import java.io.ObjectOutputStream; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.slf4j.LoggerFactory; public class LoggerSerializationTest { + // force SLF4J initialization for subsequent Logger readResolce ooperaiton + org.slf4j.Logger unused = LoggerFactory.getLogger(this.getClass()); LoggerContext lc; Logger logger; diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java index d3706ac..0002f04 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/html/HTMLLayoutTest.java @@ -158,6 +158,7 @@ public class HTMLLayoutTest { { Element tdElement = (Element) trElement.elements().get(1); String regex = ClassicTestConstants.NAKED_MAIN_REGEX; + System.out.println(tdElement.getText()); assertTrue(tdElement.getText().matches(regex)); } { diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java index b5b6935..96059a1 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/net/SocketAppenderTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue; import java.util.Map; import ch.qos.logback.core.testUtil.RandomUtil; +import org.junit.Before; import org.junit.Test; import org.slf4j.MDC; import org.slf4j.Marker; @@ -40,8 +41,9 @@ public class SocketAppenderTest { static final int JOIN_OR_WAIT_TIMEOUT = 200; static final int SLEEP_AFTER_LOG = 100; - int port = 4561; int diff = RandomUtil.getPositiveInt(); + + int port = 1024+(diff%30000); String mdcKey = "key"+diff; LoggerContext lc = new LoggerContext(); @@ -51,17 +53,22 @@ public class SocketAppenderTest { private boolean includeCallerData = false; private SimpleSocketServer simpleSocketServer; + @Before + public void setUp() { + System.out.println("SocketAppenderTest, start at "+System.currentTimeMillis()+", port="+port); + } + @Test public void startFailNoRemoteHost() { SocketAppender appender = new SocketAppender(); appender.setContext(lc); - appender.setPort(123); + appender.setPort(port); appender.start(); assertEquals(1, lc.getStatusManager().getCount()); } @Test - public void recieveMessage() throws InterruptedException { + public void receiveMessage() throws InterruptedException { fireServer(); waitForServerToStart(); configureClient(); @@ -83,7 +90,7 @@ public class SocketAppenderTest { } @Test - public void recieveWithContext() throws InterruptedException { + public void receiveWithContext() throws InterruptedException { fireServer(); waitForServerToStart(); configureClient(); @@ -118,10 +125,10 @@ public class SocketAppenderTest { waitForServerToStart(); configureClient(); - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); MDC.put(mdcKey, "testValue"); - logger.debug("test msg"); + root.debug("test msg"); Thread.sleep(SLEEP_AFTER_LOG); simpleSocketServer.close(); @@ -188,13 +195,13 @@ public class SocketAppenderTest { configureClient(); - Logger logger = lc.getLogger(Logger.ROOT_LOGGER_NAME); + Logger root = lc.getLogger(Logger.ROOT_LOGGER_NAME); MDC.put(mdcKey, "testValue"); - logger.debug("test msg"); + root.debug("test msg"); MDC.put(mdcKey, "updatedTestValue"); - logger.debug("test msg 2"); + root.debug("test msg 2"); Thread.sleep(SLEEP_AFTER_LOG); simpleSocketServer.close(); @@ -245,6 +252,9 @@ public class SocketAppenderTest { private void fireServer() throws InterruptedException { Logger root = serverLC.getLogger("root"); + Logger socketNodeLogger = serverLC.getLogger(SocketNode.class); + socketNodeLogger.setLevel(Level.WARN); + la.setName(LIST_APPENDER_NAME); la.setContext(serverLC); la.start(); @@ -252,6 +262,7 @@ public class SocketAppenderTest { simpleSocketServer = new SimpleSocketServer(serverLC, port); simpleSocketServer.start(); Thread.yield(); + Thread.sleep(50); } ListAppender getListAppender() { diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/BogusClassLoader.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/BogusClassLoader.java index 361a80b..a96093d 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/BogusClassLoader.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/BogusClassLoader.java @@ -20,7 +20,7 @@ import java.net.URLClassLoader; * A trivial class loader which throws a NoClassDefFoundError if the requested * class name contains the string "Bogus". * - * @author Ceki G?lc? + * @author Ceki Gulcu */ public class BogusClassLoader extends URLClassLoader { diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LocalFirstClassLoader.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LocalFirstClassLoader.java index 9a06d42..83e3ebf 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LocalFirstClassLoader.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LocalFirstClassLoader.java @@ -20,7 +20,7 @@ import java.net.URLClassLoader; * An almost trivial no fuss implementation of a class loader following the * child-first delegation model. * - * @author Ceki G?lc? + * @author Ceki Gulcu */ public class LocalFirstClassLoader extends URLClassLoader { diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationPerfTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationPerfTest.java index 465dec6..637e5b3 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationPerfTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/spi/LoggingEventSerializationPerfTest.java @@ -95,7 +95,7 @@ public class LoggingEventSerializationPerfTest { } double rt = doLoop(builder, LOOP_LEN); System.out - .println("avetage time per logging event " + rt + " nanoseconds"); + .println("average time per logging event " + rt + " nanoseconds"); long averageSize = (long) (noos.size() / (LOOP_LEN)); System.out.println("noos size " + noos.size() + " average size=" diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java index f080e50..17331fd 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/turbo/ReconfigureOnChangeTest.java @@ -60,7 +60,7 @@ public class ReconfigureOnChangeTest { // it actually takes time for Windows to propagate file modification changes // values below 100 milliseconds can be problematic the same propagation // latency occurs in Linux but is even larger (>600 ms) - final static int DEFAULT_SLEEP_BETWEEN_UPDATES = 110; + final static int DEFAULT_SLEEP_BETWEEN_UPDATES = 210; int sleepBetweenUpdates = DEFAULT_SLEEP_BETWEEN_UPDATES; @@ -72,7 +72,7 @@ public class ReconfigureOnChangeTest { @Before public void setUp() { - System.out.println("======== TEST START"); + System.out.println("======== TEST START, time"+System.currentTimeMillis()); // take into account propagation latency occurs on Linux or Mac if (Env.isLinux() || Env.isMac()) { sleepBetweenUpdates = 950; @@ -129,8 +129,8 @@ public class ReconfigureOnChangeTest { loggerContext.getStatusManager().add( new InfoStatus("end of execution ", this)); - long expectedRreconfigurations = runnableArray[0].getCounter(); - verify(expectedRreconfigurations); + long expectedReconfigurations = runnableArray[0].getCounter(); + verify(expectedReconfigurations); } @Test @@ -170,7 +170,7 @@ public class ReconfigureOnChangeTest { int effectiveResets = checker .matchCount("Resetting and reconfiguring context"); // the number of effective resets must be equal or less than - // expectedRreconfigurations + // expectedReconfigurations assertTrue(effectiveResets <= expectedReconfigurations); // however, there should be some effective resets String failMsg = "effective=" + effectiveResets + ", expected=" diff --git a/logback-core/pom.xml b/logback-core/pom.xml index 05eb067..9297f98 100644 --- a/logback-core/pom.xml +++ b/logback-core/pom.xml @@ -140,7 +140,8 @@ **/All*Test.java **/PackageTest.java - **/ConsoleAppenderTest.java + **/ConsoleAppenderTest.java + **/TimeBasedRollingTest.java diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java index c9d64df..684b16a 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/PackageTest.java @@ -18,7 +18,7 @@ import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses( { RenameUtilTest.class, SizeBasedRollingTest.class, - TimeBasedRollingTest.class, TimeBasedRollingWithArchiveRemovalTest.class, + TimeBasedRolling2Test.class, TimeBasedRollingWithArchiveRemovalTest.class, MultiThreadedRollingTest.class, SizeAndTimeBasedFNATP_Test.class, RollingFileAppenderTest.class, diff --git a/logback-core/src/test/java/ch/qos/logback/core/rolling/RenameUtilTest.java b/logback-core/src/test/java/ch/qos/logback/core/rolling/RenameUtilTest.java index 282974c..899a429 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/rolling/RenameUtilTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/rolling/RenameUtilTest.java @@ -90,8 +90,8 @@ public class RenameUtilTest { filenames[0] = randomOutputDirAsStr + "test-" + sdf.format(currentTime); - // set currentTime to next second plus 50 millis - currentTime += 1000 - (currentTime % 1000) + 50; + // set currentTime to next second plus 250 millis + currentTime += 1000 - (currentTime % 1000) + 250; tbnatp.setCurrentTime(currentTime); rfa.doAppend("Hello 1"); ----------------------------------------------------------------------- Summary of changes: logback-classic/pom.xml | 19 ++++++++++++- .../logback/classic/net/SimpleSocketServer.java | 6 ++-- .../ch/qos/logback/classic/net/SocketNode.java | 4 ++- .../ch/qos/logback/classic/LoggerPerfTest.java | 25 +++++++++++------ .../logback/classic/LoggerSerializationTest.java | 3 ++ .../qos/logback/classic/html/HTMLLayoutTest.java | 1 + .../logback/classic/net/SocketAppenderTest.java | 29 +++++++++++++------ .../qos/logback/classic/spi/BogusClassLoader.java | 2 +- .../logback/classic/spi/LocalFirstClassLoader.java | 2 +- .../spi/LoggingEventSerializationPerfTest.java | 2 +- .../classic/turbo/ReconfigureOnChangeTest.java | 10 +++--- logback-core/pom.xml | 3 +- .../ch/qos/logback/core/rolling/PackageTest.java | 2 +- .../qos/logback/core/rolling/RenameUtilTest.java | 4 +- 14 files changed, 77 insertions(+), 35 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From git-noreply at pixie.qos.ch Thu Dec 30 15:57:21 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Thu, 30 Dec 2010 15:57:21 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.27-6-g9fa097d Message-ID: <20101230145722.02E6D3174FA@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via 9fa097d645fe31bb057884c21c20f3e40617a8bd (commit) from 0ee73e69b47e35deeaa9dc02d8f003d12a2f2e72 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=9fa097d645fe31bb057884c21c20f3e40617a8bd http://github.com/ceki/logback/commit/9fa097d645fe31bb057884c21c20f3e40617a8bd commit 9fa097d645fe31bb057884c21c20f3e40617a8bd Author: Ceki Gulcu Date: Thu Dec 30 15:51:48 2010 +0100 fix LBCLASSIC-238 diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/boolex/GEventEvaluator.java b/logback-classic/src/main/java/ch/qos/logback/classic/boolex/GEventEvaluator.java index 04687e2..fc9623c 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/boolex/GEventEvaluator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/boolex/GEventEvaluator.java @@ -41,6 +41,7 @@ public class GEventEvaluator extends EventEvaluatorBase { } public void start() { + int errors = 0; if (expression == null || expression.length() == 0) { addError("Empty expression"); return; @@ -54,7 +55,7 @@ public class GEventEvaluator extends EventEvaluatorBase { currentPackageName = currentPackageName.replace('.', '/'); String scriptText = FileUtil.resourceAsString(this, classLoader, currentPackageName + "/EvaluatorTemplate.groovy"); - if(scriptText == null) { + if (scriptText == null) { return; } @@ -70,13 +71,17 @@ public class GEventEvaluator extends EventEvaluatorBase { } catch (CompilationFailedException cfe) { addError("Failed to compile expression [" + expression + "]", cfe); + errors++; } catch (Exception e) { addError("Failed to compile expression [" + expression + "]", e); + errors++; } + if (errors == 0) + super.start(); } public boolean evaluate(ILoggingEvent event) throws NullPointerException, EvaluationException { - if(delegateEvaluator == null) { + if (delegateEvaluator == null) { return false; } return delegateEvaluator.doEvaluate(event); diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/boolex/GEventEvaluatorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/boolex/GEventEvaluatorTest.java index 5fe551f..d482e92 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/boolex/GEventEvaluatorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/boolex/GEventEvaluatorTest.java @@ -10,6 +10,7 @@ import ch.qos.logback.core.CoreConstants; import ch.qos.logback.core.boolex.EvaluationException; import ch.qos.logback.core.status.StatusChecker; import ch.qos.logback.core.util.StatusPrinter; +import org.junit.Before; import org.junit.Test; import org.slf4j.MDC; import org.slf4j.Marker; @@ -32,6 +33,13 @@ public class GEventEvaluatorTest { Logger logger = context.getLogger(this.getClass()); Marker markerA = MarkerFactory.getMarker("A"); + GEventEvaluator gee = new GEventEvaluator(); + + @Before + public void setUp() { + gee.setContext(context); + } + LoggingEvent makeEvent(String msg) { return makeEvent(Level.DEBUG, msg, null, null); } @@ -41,8 +49,6 @@ public class GEventEvaluatorTest { } void doEvaluateAndCheck(String expression, ILoggingEvent event, boolean expected) throws EvaluationException { - GEventEvaluator gee = new GEventEvaluator(); - gee.setContext(context); gee.setExpression(expression); gee.start(); @@ -127,10 +133,16 @@ public class GEventEvaluatorTest { return (end - start) / LEN; } + + @Test + public void startMakesIsStartedReturnTrue() { + gee.setExpression("return true"); + gee.start(); + assertTrue(gee.isStarted()); + } + @Test public void perfTest() throws EvaluationException { - GEventEvaluator gee = new GEventEvaluator(); - gee.setContext(context); gee.setExpression("event.timeStamp < 100 && event.message != 'xx' "); gee.start(); diff --git a/logback-site/src/site/pages/news.html b/logback-site/src/site/pages/news.html index 178c2d8..04bbcfa 100644 --- a/logback-site/src/site/pages/news.html +++ b/logback-site/src/site/pages/news.html @@ -30,6 +30,11 @@

    January xx, 2011 - Release of version 0.9.28

    +

    Fixed issue + 238 reported by Robert Elliot. GEventEvaluator's + start method now correctly sets the state of the instance. +

    +

    December 22nd, 2010 - Release of version 0.9.27

    ----------------------------------------------------------------------- Summary of changes: .../logback/classic/boolex/GEventEvaluator.java | 9 +++++++-- .../classic/boolex/GEventEvaluatorTest.java | 20 ++++++++++++++++---- logback-site/src/site/pages/news.html | 5 +++++ 3 files changed, 28 insertions(+), 6 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From noreply-jira at qos.ch Thu Dec 30 15:58:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Thu, 30 Dec 2010 15:58:51 +0100 (CET) Subject: [logback-dev] [JIRA] Resolved: (LBCLASSIC-238) GEventEvaluator cannot be started In-Reply-To: <1298881971.1293704151398.JavaMail.ceki@pixie> Message-ID: <777436371.1293721131288.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCLASSIC-238?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu resolved LBCLASSIC-238. ---------------------------------- Fix Version/s: 0.9.28 Resolution: Fixed Fixed in http://github.com/ceki/logback/commit/9fa097d645fe31 > GEventEvaluator cannot be started > --------------------------------- > > Key: LBCLASSIC-238 > URL: http://jira.qos.ch/browse/LBCLASSIC-238 > Project: logback-classic > Issue Type: Bug > Affects Versions: 0.9.27 > Reporter: Robert Elliot > Assignee: Ceki Gulcu > Priority: Critical > Fix For: 0.9.28 > > Attachments: GEventEvaluatorTest.java > > > GEventEvaluator is fundamentally broken, because it overrides the start() method on EventEvaluatorBase but never sets EventEvaluatorBase's started field to true, so the isStarted() method on EventEvaluatorBase always returns false resulting in EvaluatorFilter's decide method always returning NEUTRAL. -- 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 From noreply-jira at qos.ch Thu Dec 30 17:04:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Thu, 30 Dec 2010 17:04:51 +0100 (CET) Subject: [logback-dev] [JIRA] Moved: (LBCLASSIC-239) DBAppender swallow NullPointerException In-Reply-To: <1833168732.1293454551272.JavaMail.ceki@pixie> Message-ID: <1065717343.1293725091298.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCLASSIC-239?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu moved LBCORE-189 to LBCLASSIC-239: --------------------------------------------- Project: logback-classic (was: logback-core) Key: LBCLASSIC-239 (was: LBCORE-189) Affects Version/s: 0.9.27 (was: 0.9.26) Component/s: appender (was: Appender) > DBAppender swallow NullPointerException > --------------------------------------- > > Key: LBCLASSIC-239 > URL: http://jira.qos.ch/browse/LBCLASSIC-239 > Project: logback-classic > Issue Type: Bug > Components: appender > Affects Versions: 0.9.27 > Reporter: Artyom Kalita > Assignee: Ceki Gulcu > Priority: Minor > > logback.xml : > > > > com.mysql.jdbc.Driver > jdbc:mysql://localhost:3306/mrb > root > admin > > > Java code (using DBAppender): > Date dateFrom = null; > log.info("Processing code {}; code type is {}; request date {}; record from date {}",new Object[] { code, codeType, new Date(), dateFrom }); > DBAppender had null pointer exception on 141 line because of dateFrom, but this exception is swallowed and not shown. -- 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 From git-noreply at pixie.qos.ch Thu Dec 30 17:05:41 2010 From: git-noreply at pixie.qos.ch (added by portage for gitosis-gentoo) Date: Thu, 30 Dec 2010 17:05:41 +0100 (CET) Subject: [logback-dev] [GIT] Logback: the generic, reliable, fast and flexible logging framework. branch, master, updated. v_0.9.27-7-gb8790fc Message-ID: <20101230160541.A806131751B@pixie.qos.ch> This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Logback: the generic, reliable, fast and flexible logging framework.". The branch, master has been updated via b8790fc09eee12d16dcc0c8417df7d503927211f (commit) from 9fa097d645fe31bb057884c21c20f3e40617a8bd (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- http://git.qos.ch/gitweb/?p=logback.git;a=commit;h=b8790fc09eee12d16dcc0c8417df7d503927211f http://github.com/ceki/logback/commit/b8790fc09eee12d16dcc0c8417df7d503927211f commit b8790fc09eee12d16dcc0c8417df7d503927211f Author: Ceki Gulcu Date: Thu Dec 30 16:59:07 2010 +0100 FIX BCLASSIC-239 diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/db/DBAppender.java b/logback-classic/src/main/java/ch/qos/logback/classic/db/DBAppender.java index 0bbc74e..93e0c13 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/db/DBAppender.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/db/DBAppender.java @@ -138,7 +138,7 @@ public class DBAppender extends DBAppenderBase { int arrayLen = argArray != null ? argArray.length : 0; for(int i = 0; i < arrayLen && i < 4; i++) { - stmt.setString(ARG0_INDEX+i, truncateTo254(argArray[i].toString())); + stmt.setString(ARG0_INDEX+i, asStringTruncatedTo254(argArray[i])); } if(arrayLen < 4) { for(int i = arrayLen; i < 4; i++) { @@ -147,7 +147,12 @@ public class DBAppender extends DBAppenderBase { } } - String truncateTo254(String s) { + String asStringTruncatedTo254(Object o) { + String s = null; + if(o != null) { + s= o.toString(); + } + if(s == null) { return null; } diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderH2Test.java b/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderH2Test.java index f8daa42..f2a3606 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderH2Test.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/db/DBAppenderH2Test.java @@ -20,6 +20,7 @@ import static org.junit.Assert.fail; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.Date; import java.util.Map; import org.apache.log4j.MDC; @@ -36,7 +37,7 @@ import ch.qos.logback.core.db.DriverManagerConnectionSource; import ch.qos.logback.core.testUtil.RandomUtil; import ch.qos.logback.core.util.StatusPrinter; -public class DBAppenderH2Test { +public class DBAppenderH2Test { LoggerContext lc; Logger logger; @@ -44,13 +45,13 @@ public class DBAppenderH2Test { DriverManagerConnectionSource connectionSource; DBAppenderH2TestFixture dbAppenderH2TestFixture; int diff = RandomUtil.getPositiveInt(); - + @Before public void setUp() throws SQLException { dbAppenderH2TestFixture = new DBAppenderH2TestFixture(); dbAppenderH2TestFixture.setUp(); - + lc = new LoggerContext(); lc.setName("default"); logger = lc.getLogger("root"); @@ -61,16 +62,16 @@ public class DBAppenderH2Test { connectionSource.setContext(lc); connectionSource.setDriverClass(DBAppenderH2TestFixture.H2_DRIVER_CLASS); connectionSource.setUrl(dbAppenderH2TestFixture.url); - System.out.println("cs.url="+dbAppenderH2TestFixture.url); + System.out.println("cs.url=" + dbAppenderH2TestFixture.url); connectionSource.setUser(dbAppenderH2TestFixture.user); connectionSource.setPassword(dbAppenderH2TestFixture.password); - + connectionSource.start(); appender.setConnectionSource(connectionSource); appender.start(); } - + @After public void tearDown() throws SQLException { logger = null; @@ -85,9 +86,9 @@ public class DBAppenderH2Test { ILoggingEvent event = createLoggingEvent(); appender.append(event); - + StatusPrinter.print(lc); - + Statement stmt = connectionSource.getConnection().createStatement(); ResultSet rs = null; rs = stmt.executeQuery("SELECT * FROM logging_event"); @@ -106,11 +107,11 @@ public class DBAppenderH2Test { } else { fail("No row was inserted in the database"); } - + rs.close(); stmt.close(); } - + @Test public void testAppendThrowable() throws SQLException { ILoggingEvent event = createLoggingEvent(); @@ -121,29 +122,47 @@ public class DBAppenderH2Test { rs.next(); String expected = "java.lang.Exception: test Ex"; String firstLine = rs.getString(3); - assertTrue("["+firstLine+"] does not match ["+expected+"]", firstLine.contains(expected)); - + assertTrue("[" + firstLine + "] does not match [" + expected + "]", firstLine.contains(expected)); + int i = 0; while (rs.next()) { expected = event.getThrowableProxy().getStackTraceElementProxyArray()[i].toString(); String st = rs.getString(3); - assertTrue("["+st+"] does not match ["+expected+"]", st.contains(expected)); + assertTrue("[" + st + "] does not match [" + expected + "]", st.contains(expected)); i++; } assertTrue(i != 0); - + rs.close(); stmt.close(); } - + + @Test + public void withNullArgument() throws SQLException { + ILoggingEvent event = createLoggingEvent("Processing code {}; code type is {}; request date {}; record from date {}", new Object[] { 1, 2, new Date(), null }); + appender.append(event); + + + Statement stmt = connectionSource.getConnection().createStatement(); + ResultSet rs = null; + rs = stmt.executeQuery("SELECT * FROM logging_event"); + if (rs.next()) { + assertEquals(event.getTimeStamp(), rs.getLong(DBAppender.TIMESTMP_INDEX)); + assertEquals(event.getFormattedMessage(), rs.getString(DBAppender.FORMATTED_MESSAGE_INDEX)); + } + + StatusPrinter.print(lc); + + } + @Test public void testContextInfo() throws SQLException { lc.putProperty("testKey1", "testValue1"); - MDC.put("k"+diff, "v"+diff); + MDC.put("k" + diff, "v" + diff); ILoggingEvent event = createLoggingEvent(); - + appender.append(event); - + Statement stmt = connectionSource.getConnection().createStatement(); ResultSet rs = null; rs = stmt.executeQuery("SELECT * FROM LOGGING_EVENT_PROPERTY WHERE EVENT_ID=1"); @@ -159,14 +178,15 @@ public class DBAppenderH2Test { rs.close(); stmt.close(); } - + + @Test public void testAppendMultipleEvents() throws SQLException { for (int i = 0; i < 10; i++) { ILoggingEvent event = createLoggingEvent(); appender.append(event); } - + Statement stmt = connectionSource.getConnection().createStatement(); ResultSet rs = null; rs = stmt.executeQuery("SELECT * FROM logging_event"); @@ -175,15 +195,22 @@ public class DBAppenderH2Test { count++; } assertEquals(10, count); - + rs.close(); stmt.close(); } - - private ILoggingEvent createLoggingEvent() { + + private ILoggingEvent createLoggingEvent(String msg, Object[] args) { ILoggingEvent le = new LoggingEvent(this.getClass().getName(), logger, - Level.DEBUG, "test message", new Exception("test Ex"), new Integer[] {diff}); + Level.DEBUG, msg, new Exception("test Ex"), args); return le; } + + + private ILoggingEvent createLoggingEvent() { + return createLoggingEvent("test message", new Integer[]{diff}); + } + + } diff --git a/logback-site/src/site/pages/news.html b/logback-site/src/site/pages/news.html index 04bbcfa..57a55fb 100644 --- a/logback-site/src/site/pages/news.html +++ b/logback-site/src/site/pages/news.html @@ -35,6 +35,11 @@ start method now correctly sets the state of the instance.

    +

    Corrected handling of null valued arguments by DBAppender. This + fixes LBCLASSIC-239 + reported by Artyom Kalita.

    +

    December 22nd, 2010 - Release of version 0.9.27

    ----------------------------------------------------------------------- Summary of changes: .../java/ch/qos/logback/classic/db/DBAppender.java | 9 ++- .../qos/logback/classic/db/DBAppenderH2Test.java | 75 +++++++++++++------ logback-site/src/site/pages/news.html | 5 ++ 3 files changed, 63 insertions(+), 26 deletions(-) hooks/post-receive -- Logback: the generic, reliable, fast and flexible logging framework. From noreply-jira at qos.ch Thu Dec 30 17:06:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Thu, 30 Dec 2010 17:06:51 +0100 (CET) Subject: [logback-dev] [JIRA] Resolved: (LBCLASSIC-239) DBAppender swallow NullPointerException In-Reply-To: <1833168732.1293454551272.JavaMail.ceki@pixie> Message-ID: <788294405.1293725211519.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCLASSIC-239?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu resolved LBCLASSIC-239. ---------------------------------- Fix Version/s: 0.9.28 Resolution: Fixed Fixed in http://github.com/ceki/logback/commit/b8790fc09e > DBAppender swallow NullPointerException > --------------------------------------- > > Key: LBCLASSIC-239 > URL: http://jira.qos.ch/browse/LBCLASSIC-239 > Project: logback-classic > Issue Type: Bug > Components: appender > Affects Versions: 0.9.27 > Reporter: Artyom Kalita > Assignee: Ceki Gulcu > Priority: Minor > Fix For: 0.9.28 > > > logback.xml : > > > > com.mysql.jdbc.Driver > jdbc:mysql://localhost:3306/mrb > root > admin > > > Java code (using DBAppender): > Date dateFrom = null; > log.info("Processing code {}; code type is {}; request date {}; record from date {}",new Object[] { code, codeType, new Date(), dateFrom }); > DBAppender had null pointer exception on 141 line because of dateFrom, but this exception is swallowed and not shown. -- 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 From noreply-jira at qos.ch Thu Dec 30 18:12:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Thu, 30 Dec 2010 18:12:51 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBCORE-188) Log Rotation/Gzip process leaving .tmp files behind In-Reply-To: <1972951794.1292615931253.JavaMail.ceki@pixie> Message-ID: <1343034444.1293729171354.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-188?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11923#action_11923 ] Ceki Gulcu commented on LBCORE-188: ----------------------------------- Is this happenning on Windows? > Log Rotation/Gzip process leaving .tmp files behind > --------------------------------------------------- > > Key: LBCORE-188 > URL: http://jira.qos.ch/browse/LBCORE-188 > Project: logback-core > Issue Type: Bug > Components: Rolling > Affects Versions: 0.9.26 > Reporter: Bert B-L > Assignee: Logback dev list > > We are seeing logback leave .tmp files behind in the log directory, presumably due to a hiccup during log rotation or gzip. > Size > 2365956 Dec 11 00:00 statsreceiver.log.2010-12-10.gz > 2679618 Dec 12 00:01 statsreceiver.log.2010-12-11.gz > 9190879942 Dec 12 04:00 statsreceiver-debug.log23124507802228260.tmp > 2542799 Dec 13 00:00 statsreceiver.log.2010-12-12.gz > 9137740366 Dec 13 04:00 statsreceiver-debug.log23210907242250260.tmp > 543937393 Dec 13 20:07 statsreceiver-debug.log.2010-12-13_19:00.gz > 548781049 Dec 13 22:07 statsreceiver-debug.log.2010-12-13_21:00.gz > 2284216 Dec 14 00:00 statsreceiver.log.2010-12-13.gz > 8127562 Dec 15 00:00 statsreceiver.log.2010-12-14.gz > 19067117496 Dec 15 13:00 statsreceiver-debug.log23416102512001260.tmp > 18177324477 Dec 15 16:00 statsreceiver-debug.log23426920509229260.tmp > 2257423 Dec 15 23:00 statsreceiver-debug.log.2010-12-15_22:00.gz > The logback jar versions are: > WEB-INF/lib/logback-classic-0.9.26.jar > WEB-INF/lib/logback-core-0.9.26.jar > There is only a single application writing to those files, though it is conceivable that the .tmp droppings correlate to restarts of that application. > If this is expected on application restarts, could logback start gzip'ing them again when it comes back? > Here is the logback.xml file: > > > > ${logdir:-.}/${prog:-unknown}.log > true > > > warn > > > > ${logdir:-.}/${prog:-unknown}.log.%d{yyyy-MM-dd}.gz > 7 > > > %-30(%d{yyyy-MM-dd HH:mm:ss} %.-1level :) %m Context:[%X{GTNDC_INFO}]%n > > > > ${logdir:-.}/${prog:-unknown}-debug.log > true > > > debug > > > > ${logdir:-.}/${prog:-unknown}-debug.log.%d{yyyy-MM-dd_HH:00}.gz > 36 > > > %-60(%d{yyyy-MM-dd HH:mm:ss} [%thread] %.-1level :) %m Context:[%X{GTNDC_INFO}]%n > > > > > > > > -- 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 From noreply-jira at qos.ch Thu Dec 30 18:12:51 2010 From: noreply-jira at qos.ch (Ceki Gulcu (JIRA)) Date: Thu, 30 Dec 2010 18:12:51 +0100 (CET) Subject: [logback-dev] [JIRA] Assigned: (LBCORE-188) Log Rotation/Gzip process leaving .tmp files behind In-Reply-To: <1972951794.1292615931253.JavaMail.ceki@pixie> Message-ID: <137293508.1293729171647.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-188?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Ceki Gulcu reassigned LBCORE-188: --------------------------------- Assignee: Ceki Gulcu (was: Logback dev list) > Log Rotation/Gzip process leaving .tmp files behind > --------------------------------------------------- > > Key: LBCORE-188 > URL: http://jira.qos.ch/browse/LBCORE-188 > Project: logback-core > Issue Type: Bug > Components: Rolling > Affects Versions: 0.9.26 > Reporter: Bert B-L > Assignee: Ceki Gulcu > > We are seeing logback leave .tmp files behind in the log directory, presumably due to a hiccup during log rotation or gzip. > Size > 2365956 Dec 11 00:00 statsreceiver.log.2010-12-10.gz > 2679618 Dec 12 00:01 statsreceiver.log.2010-12-11.gz > 9190879942 Dec 12 04:00 statsreceiver-debug.log23124507802228260.tmp > 2542799 Dec 13 00:00 statsreceiver.log.2010-12-12.gz > 9137740366 Dec 13 04:00 statsreceiver-debug.log23210907242250260.tmp > 543937393 Dec 13 20:07 statsreceiver-debug.log.2010-12-13_19:00.gz > 548781049 Dec 13 22:07 statsreceiver-debug.log.2010-12-13_21:00.gz > 2284216 Dec 14 00:00 statsreceiver.log.2010-12-13.gz > 8127562 Dec 15 00:00 statsreceiver.log.2010-12-14.gz > 19067117496 Dec 15 13:00 statsreceiver-debug.log23416102512001260.tmp > 18177324477 Dec 15 16:00 statsreceiver-debug.log23426920509229260.tmp > 2257423 Dec 15 23:00 statsreceiver-debug.log.2010-12-15_22:00.gz > The logback jar versions are: > WEB-INF/lib/logback-classic-0.9.26.jar > WEB-INF/lib/logback-core-0.9.26.jar > There is only a single application writing to those files, though it is conceivable that the .tmp droppings correlate to restarts of that application. > If this is expected on application restarts, could logback start gzip'ing them again when it comes back? > Here is the logback.xml file: > > > > ${logdir:-.}/${prog:-unknown}.log > true > > > warn > > > > ${logdir:-.}/${prog:-unknown}.log.%d{yyyy-MM-dd}.gz > 7 > > > %-30(%d{yyyy-MM-dd HH:mm:ss} %.-1level :) %m Context:[%X{GTNDC_INFO}]%n > > > > ${logdir:-.}/${prog:-unknown}-debug.log > true > > > debug > > > > ${logdir:-.}/${prog:-unknown}-debug.log.%d{yyyy-MM-dd_HH:00}.gz > 36 > > > %-60(%d{yyyy-MM-dd HH:mm:ss} [%thread] %.-1level :) %m Context:[%X{GTNDC_INFO}]%n > > > > > > > > -- 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 From noreply-jira at qos.ch Thu Dec 30 18:18:51 2010 From: noreply-jira at qos.ch (Jeff Jensen (JIRA)) Date: Thu, 30 Dec 2010 18:18:51 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBCORE-188) Log Rotation/Gzip process leaving .tmp files behind In-Reply-To: <1972951794.1292615931253.JavaMail.ceki@pixie> Message-ID: <1465858701.1293729531288.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-188?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11924#action_11924 ] Jeff Jensen commented on LBCORE-188: ------------------------------------ Ubuntu for us. > Log Rotation/Gzip process leaving .tmp files behind > --------------------------------------------------- > > Key: LBCORE-188 > URL: http://jira.qos.ch/browse/LBCORE-188 > Project: logback-core > Issue Type: Bug > Components: Rolling > Affects Versions: 0.9.26 > Reporter: Bert B-L > Assignee: Ceki Gulcu > > We are seeing logback leave .tmp files behind in the log directory, presumably due to a hiccup during log rotation or gzip. > Size > 2365956 Dec 11 00:00 statsreceiver.log.2010-12-10.gz > 2679618 Dec 12 00:01 statsreceiver.log.2010-12-11.gz > 9190879942 Dec 12 04:00 statsreceiver-debug.log23124507802228260.tmp > 2542799 Dec 13 00:00 statsreceiver.log.2010-12-12.gz > 9137740366 Dec 13 04:00 statsreceiver-debug.log23210907242250260.tmp > 543937393 Dec 13 20:07 statsreceiver-debug.log.2010-12-13_19:00.gz > 548781049 Dec 13 22:07 statsreceiver-debug.log.2010-12-13_21:00.gz > 2284216 Dec 14 00:00 statsreceiver.log.2010-12-13.gz > 8127562 Dec 15 00:00 statsreceiver.log.2010-12-14.gz > 19067117496 Dec 15 13:00 statsreceiver-debug.log23416102512001260.tmp > 18177324477 Dec 15 16:00 statsreceiver-debug.log23426920509229260.tmp > 2257423 Dec 15 23:00 statsreceiver-debug.log.2010-12-15_22:00.gz > The logback jar versions are: > WEB-INF/lib/logback-classic-0.9.26.jar > WEB-INF/lib/logback-core-0.9.26.jar > There is only a single application writing to those files, though it is conceivable that the .tmp droppings correlate to restarts of that application. > If this is expected on application restarts, could logback start gzip'ing them again when it comes back? > Here is the logback.xml file: > > > > ${logdir:-.}/${prog:-unknown}.log > true > > > warn > > > > ${logdir:-.}/${prog:-unknown}.log.%d{yyyy-MM-dd}.gz > 7 > > > %-30(%d{yyyy-MM-dd HH:mm:ss} %.-1level :) %m Context:[%X{GTNDC_INFO}]%n > > > > ${logdir:-.}/${prog:-unknown}-debug.log > true > > > debug > > > > ${logdir:-.}/${prog:-unknown}-debug.log.%d{yyyy-MM-dd_HH:00}.gz > 36 > > > %-60(%d{yyyy-MM-dd HH:mm:ss} [%thread] %.-1level :) %m Context:[%X{GTNDC_INFO}]%n > > > > > > > > -- 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 From noreply-jira at qos.ch Thu Dec 30 19:58:51 2010 From: noreply-jira at qos.ch (Bert B-L (JIRA)) Date: Thu, 30 Dec 2010 19:58:51 +0100 (CET) Subject: [logback-dev] [JIRA] Commented: (LBCORE-188) Log Rotation/Gzip process leaving .tmp files behind In-Reply-To: <1972951794.1292615931253.JavaMail.ceki@pixie> Message-ID: <1135396486.1293735531310.JavaMail.ceki@pixie> [ http://jira.qos.ch/browse/LBCORE-188?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=11925#action_11925 ] Bert B-L commented on LBCORE-188: --------------------------------- RedHat For us. > Log Rotation/Gzip process leaving .tmp files behind > --------------------------------------------------- > > Key: LBCORE-188 > URL: http://jira.qos.ch/browse/LBCORE-188 > Project: logback-core > Issue Type: Bug > Components: Rolling > Affects Versions: 0.9.26 > Reporter: Bert B-L > Assignee: Ceki Gulcu > > We are seeing logback leave .tmp files behind in the log directory, presumably due to a hiccup during log rotation or gzip. > Size > 2365956 Dec 11 00:00 statsreceiver.log.2010-12-10.gz > 2679618 Dec 12 00:01 statsreceiver.log.2010-12-11.gz > 9190879942 Dec 12 04:00 statsreceiver-debug.log23124507802228260.tmp > 2542799 Dec 13 00:00 statsreceiver.log.2010-12-12.gz > 9137740366 Dec 13 04:00 statsreceiver-debug.log23210907242250260.tmp > 543937393 Dec 13 20:07 statsreceiver-debug.log.2010-12-13_19:00.gz > 548781049 Dec 13 22:07 statsreceiver-debug.log.2010-12-13_21:00.gz > 2284216 Dec 14 00:00 statsreceiver.log.2010-12-13.gz > 8127562 Dec 15 00:00 statsreceiver.log.2010-12-14.gz > 19067117496 Dec 15 13:00 statsreceiver-debug.log23416102512001260.tmp > 18177324477 Dec 15 16:00 statsreceiver-debug.log23426920509229260.tmp > 2257423 Dec 15 23:00 statsreceiver-debug.log.2010-12-15_22:00.gz > The logback jar versions are: > WEB-INF/lib/logback-classic-0.9.26.jar > WEB-INF/lib/logback-core-0.9.26.jar > There is only a single application writing to those files, though it is conceivable that the .tmp droppings correlate to restarts of that application. > If this is expected on application restarts, could logback start gzip'ing them again when it comes back? > Here is the logback.xml file: > > > > ${logdir:-.}/${prog:-unknown}.log > true > > > warn > > > > ${logdir:-.}/${prog:-unknown}.log.%d{yyyy-MM-dd}.gz > 7 > > > %-30(%d{yyyy-MM-dd HH:mm:ss} %.-1level :) %m Context:[%X{GTNDC_INFO}]%n > > > > ${logdir:-.}/${prog:-unknown}-debug.log > true > > > debug > > > > ${logdir:-.}/${prog:-unknown}-debug.log.%d{yyyy-MM-dd_HH:00}.gz > 36 > > > %-60(%d{yyyy-MM-dd HH:mm:ss} [%thread] %.-1level :) %m Context:[%X{GTNDC_INFO}]%n > > > > > > > > -- 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
  • toto StringThe email address of the recipient. Multiple recipients - can be specified by using several <To> elements.The email address of the recipient as a pattern. The + pattern is evaluated anew with the triggering event as input + for each outgoing email. Multiple recipients can be specified + by using several <to> elements.
    from
    + replace(p){r, t} + +

    Replaces occurrences of 'r', a regex, with its + replacement 't' in the string produces by the sub-pattern + 'p'. For example, "%replace(%msg){'\s', ''}" will remove all + spaces contained in the event message.

    + +

    The pattern 'p' can be arbitrarily complex and in + particular can contain multiple conversion keywords. For + instance, "%replace(%logger %msg){'\.', '/'}" will replace + all dots in the logger or the message of the event with a + forward slash. +

    +
    to StringThe email address of the recipient as a pattern. The - pattern is evaluated anew with the triggering event as input - for each outgoing email. Multiple recipients can be specified - by using several <to> elements.The email address of the recipient as a + pattern. The pattern is evaluated anew with the + triggering event as input for each outgoing email. Multiple + recipients can be specified by using several + <to> elements.
    from