Custom appender and layout issue

I'm trying to port my log4j appender and layout over to logback but am running into some issues. My log4j appender colorizes the timestamp printed in the logs and the layout colorizes the log messages based on level - at least, in theory. I think I've correctly configured everything in the XML but my classes are not quite correct. I'm getting the colored timestamp and I'm partially getting the colorized log messages, but am not getting the pattern I've specified in my XML and the log messages are all smushed together back to back. I suspect I'm not overriding the right methods or not calling them in the right order or place. Here's my appender XML: <appender name="foouilog" class="com.foo.logging.FooRollingFileAppender"> <file>/usr/local/tomcat/logs/fooui.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>/usr/local/tomcat/logs/fooui-%d{yyyy-MM-dd}.%i.gz</fileNamePattern> <maxHistory>10</maxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>25MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <layout class="com.foo.logging.AnsiColorLayout"/> <pattern>%date{ISO8601} %p [%logger{5}.%method:%line] - %msg%n%rEx</pattern> </encoder> </appender> And here's the relevant Java code: Appender: public class FooRollingFileAppender extends RollingFileAppender<ILoggingEvent> { *** snip *** public void append(ILoggingEvent eventObject) { OutputStream os = this.getOutputStream(); // code to write out color formatted timestamp os.flush(); super.append(eventObject); } *** snip *** } Layout: public class AnsiColorLayout extends LayoutBase<ILoggingEvent> { *** snip *** public String doLayout(ILoggingEvent event) { return this.format(event); } private String format(ILoggingEvent event) { StringBuilder sb = new StringBuilder(); switch (event.getLevel().toInt()) { *** snip *** } sb.append(event.getFormattedMessage()); sb.append(COLOR_DEFAULT); return sb.toString(); } *** snip *** } Thanks, --adam http://gordonizer.com

Although very similar to log4j, logback is different in certain aspects. In particular, logback's OutputStreamAppedner and derived classes (ConsoleAppnder, FileAppender and RollingFileAppender) use an Encoder [1] to write to the output stream. From the looks of it, you should probably write your own encoder. HTH, [1] http://logback.qos.ch/apidocs/ch/qos/logback/core/encoder/Encoder.html On 09.11.2011 21:29, Adam Gordon wrote:
I'm trying to port my log4j appender and layout over to logback but am running into some issues. My log4j appender colorizes the timestamp printed in the logs and the layout colorizes the log messages based on level - at least, in theory.
I think I've correctly configured everything in the XML but my classes are not quite correct. I'm getting the colored timestamp and I'm partially getting the colorized log messages, but am not getting the pattern I've specified in my XML and the log messages are all smushed together back to back. I suspect I'm not overriding the right methods or not calling them in the right order or place.
Here's my appender XML:
<appender name="foouilog" class="com.foo.logging.FooRollingFileAppender"> <file>/usr/local/tomcat/logs/fooui.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>/usr/local/tomcat/logs/fooui-%d{yyyy-MM-dd}.%i.gz</fileNamePattern> <maxHistory>10</maxHistory> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>25MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"> <layout class="com.foo.logging.AnsiColorLayout"/> <pattern>%date{ISO8601} %p [%logger{5}.%method:%line] - %msg%n%rEx</pattern> </encoder> </appender>
And here's the relevant Java code:
Appender:
public class FooRollingFileAppender extends RollingFileAppender<ILoggingEvent> { *** snip *** public void append(ILoggingEvent eventObject) { OutputStream os = this.getOutputStream(); // code to write out color formatted timestamp os.flush();
super.append(eventObject); } *** snip *** }
Layout:
public class AnsiColorLayout extends LayoutBase<ILoggingEvent> {
*** snip ***
public String doLayout(ILoggingEvent event) { return this.format(event); }
private String format(ILoggingEvent event) { StringBuilder sb = new StringBuilder(); switch (event.getLevel().toInt()) {
*** snip ***
} sb.append(event.getFormattedMessage()); sb.append(COLOR_DEFAULT); return sb.toString(); }
*** snip *** }
Thanks,
--adam
-- Ceki http://twitter.com/#!/ceki

Ahhhhhh. Thanks. I will try that. Which encoder should I extend - LayoutWrapping or PatternLayout? I noticed that OutputStreamAppenders use LayoutWrappingEncoder. Or should I roll my own from scratch? --adam http://gordonizer.com On Wed, Nov 9, 2011 at 13:51, ceki <ceki@qos.ch> wrote:
Although very similar to log4j, logback is different in certain aspects. In particular, logback's OutputStreamAppedner and derived classes (ConsoleAppnder, FileAppender and RollingFileAppender) use an Encoder [1] to write to the output stream. From the looks of it, you should probably write your own encoder.
HTH,
On 09.11.2011 21:29, Adam Gordon wrote:
I'm trying to port my log4j appender and layout over to logback but am running into some issues. My log4j appender colorizes the timestamp printed in the logs and the layout colorizes the log messages based on level - at least, in theory.
I think I've correctly configured everything in the XML but my classes are not quite correct. I'm getting the colored timestamp and I'm partially getting the colorized log messages, but am not getting the pattern I've specified in my XML and the log messages are all smushed together back to back. I suspect I'm not overriding the right methods or not calling them in the right order or place.
Here's my appender XML:
<appender name="foouilog" class="com.foo.logging.** FooRollingFileAppender"> <file>/usr/local/tomcat/logs/**fooui.log</file> <rollingPolicy class="ch.qos.logback.core.**rolling.** TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>/usr/local/**tomcat/logs/fooui-%d{yyyy-MM-** dd}.%i.gz</fileNamePattern> <maxHistory>10</maxHistory> <**timeBasedFileNamingAndTriggeri**ngPolicy class="ch.qos.logback.core.**rolling.SizeAndTimeBasedFNATP"**> <maxFileSize>25MB</**maxFileSize> </**timeBasedFileNamingAndTriggeri**ngPolicy> </rollingPolicy> <encoder class="ch.qos.logback.core.**encoder.LayoutWrappingEncoder"**> <layout class="com.foo.logging.**AnsiColorLayout"/> <pattern>%date{ISO8601} %p [%logger{5}.%method:%line] - %msg%n%rEx</pattern> </encoder> </appender>
And here's the relevant Java code:
Appender:
public class FooRollingFileAppender extends RollingFileAppender<**ILoggingEvent> { *** snip *** public void append(ILoggingEvent eventObject) { OutputStream os = this.getOutputStream(); // code to write out color formatted timestamp os.flush();
super.append(eventObject); } *** snip *** }
Layout:
public class AnsiColorLayout extends LayoutBase<ILoggingEvent> {
*** snip ***
public String doLayout(ILoggingEvent event) { return this.format(event); }
private String format(ILoggingEvent event) { StringBuilder sb = new StringBuilder(); switch (event.getLevel().toInt()) {
*** snip ***
} sb.append(event.**getFormattedMessage()); sb.append(COLOR_DEFAULT); return sb.toString(); }
*** snip *** }
Thanks,
--adam
-- Ceki http://twitter.com/#!/ceki ______________________________**_________________ Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/**listinfo/logback-user<http://mailman.qos.ch/mailman/listinfo/logback-user>

You should look at what LayoutWrappingEncoder and try to adapt that for your use case. It's just a guess though. -- Ceki http://twitter.com/#!/ceki On 09.11.2011 22:46, Adam Gordon wrote:
Ahhhhhh. Thanks. I will try that. Which encoder should I extend - LayoutWrapping or PatternLayout? I noticed that OutputStreamAppenders use LayoutWrappingEncoder. Or should I roll my own from scratch?
--adam
On Wed, Nov 9, 2011 at 13:51, ceki <ceki@qos.ch <mailto:ceki@qos.ch>> wrote:
Although very similar to log4j, logback is different in certain aspects. In particular, logback's OutputStreamAppedner and derived classes (ConsoleAppnder, FileAppender and RollingFileAppender) use an Encoder [1] to write to the output stream. From the looks of it, you should probably write your own encoder.
HTH,
[1] http://logback.qos.ch/apidocs/__ch/qos/logback/core/encoder/__Encoder.html <http://logback.qos.ch/apidocs/ch/qos/logback/core/encoder/Encoder.html>
On 09.11.2011 21:29, Adam Gordon wrote:
I'm trying to port my log4j appender and layout over to logback but am running into some issues. My log4j appender colorizes the timestamp printed in the logs and the layout colorizes the log messages based on level - at least, in theory.
I think I've correctly configured everything in the XML but my classes are not quite correct. I'm getting the colored timestamp and I'm partially getting the colorized log messages, but am not getting the pattern I've specified in my XML and the log messages are all smushed together back to back. I suspect I'm not overriding the right methods or not calling them in the right order or place.
Here's my appender XML:
<appender name="foouilog" class="com.foo.logging.__FooRollingFileAppender"> <file>/usr/local/tomcat/logs/__fooui.log</file> <rollingPolicy class="ch.qos.logback.core.__rolling.__TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>/usr/local/__tomcat/logs/fooui-%d{yyyy-MM-__dd}.%i.gz</fileNamePattern> <maxHistory>10</maxHistory> <__timeBasedFileNamingAndTriggeri__ngPolicy
class="ch.qos.logback.core.__rolling.SizeAndTimeBasedFNATP"__> <maxFileSize>25MB</__maxFileSize> </__timeBasedFileNamingAndTriggeri__ngPolicy> </rollingPolicy> <encoder class="ch.qos.logback.core.__encoder.LayoutWrappingEncoder"__> <layout class="com.foo.logging.__AnsiColorLayout"/> <pattern>%date{ISO8601} %p [%logger{5}.%method:%line] - %msg%n%rEx</pattern> </encoder> </appender>
And here's the relevant Java code:
Appender:
public class FooRollingFileAppender extends RollingFileAppender<__ILoggingEvent> { *** snip *** public void append(ILoggingEvent eventObject) { OutputStream os = this.getOutputStream(); // code to write out color formatted timestamp os.flush();
super.append(eventObject); } *** snip *** }
Layout:
public class AnsiColorLayout extends LayoutBase<ILoggingEvent> {
*** snip ***
public String doLayout(ILoggingEvent event) { return this.format(event); }
private String format(ILoggingEvent event) { StringBuilder sb = new StringBuilder(); switch (event.getLevel().toInt()) {
*** snip ***
} sb.append(event.__getFormattedMessage()); sb.append(COLOR_DEFAULT); return sb.toString(); }
*** snip *** }
Thanks,
--adam

That worked. My custom encoder is doing everything I want and more. For some reason, it looks like Logback is calling the doEncode(ILoggingEvent) twice as the log messages are showing up in duplicate. I've modified my XML to use the stock RollingFileAppender and my custom encoder. Any ideas? My encoder is definitely only calling the getFormattedMessage(...) method and writing it to the output stream once. Thanks. --adam http://gordonizer.com On Wed, Nov 9, 2011 at 15:17, ceki <ceki@qos.ch> wrote:
You should look at what LayoutWrappingEncoder and try to adapt that for your use case. It's just a guess though.
-- Ceki http://twitter.com/#!/ceki
On 09.11.2011 22:46, Adam Gordon wrote:
Ahhhhhh. Thanks. I will try that. Which encoder should I extend - LayoutWrapping or PatternLayout? I noticed that OutputStreamAppenders use LayoutWrappingEncoder. Or should I roll my own from scratch?
--adam
On Wed, Nov 9, 2011 at 13:51, ceki <ceki@qos.ch <mailto:ceki@qos.ch>> wrote:
Although very similar to log4j, logback is different in certain aspects. In particular, logback's OutputStreamAppedner and derived classes (ConsoleAppnder, FileAppender and RollingFileAppender) use an Encoder [1] to write to the output stream. From the looks of it, you should probably write your own encoder.
HTH,
[1] http://logback.qos.ch/apidocs/**__ch/qos/logback/core/encoder/** __Encoder.html<http://logback.qos.ch/apidocs/__ch/qos/logback/core/encoder/__Encoder.html>
<http://logback.qos.ch/**apidocs/ch/qos/logback/core/** encoder/Encoder.html<http://logback.qos.ch/apidocs/ch/qos/logback/core/encoder/Encoder.html>
On 09.11.2011 21:29, Adam Gordon wrote:
I'm trying to port my log4j appender and layout over to logback but am running into some issues. My log4j appender colorizes the timestamp printed in the logs and the layout colorizes the log messages based on level - at least, in theory.
I think I've correctly configured everything in the XML but my classes are not quite correct. I'm getting the colored timestamp and I'm partially getting the colorized log messages, but am not getting the pattern I've specified in my XML and the log messages are all smushed together back to back. I suspect I'm not overriding the right methods or not calling them in the right order or place.
Here's my appender XML:
<appender name="foouilog" class="com.foo.logging.__**FooRollingFileAppender"> <file>/usr/local/tomcat/logs/_**_fooui.log</file> <rollingPolicy class="ch.qos.logback.core.__**rolling.__** TimeBasedRollingPolicy"> <!-- rollover daily --> <fileNamePattern>/usr/local/__**tomcat/logs/fooui-%d{yyyy-MM-_** _dd}.%i.gz</fileNamePattern> <maxHistory>10</maxHistory> <__**timeBasedFileNamingAndTriggeri**__ngPolicy
class="ch.qos.logback.core.__**rolling.SizeAndTimeBasedFNATP"** __> <maxFileSize>25MB</__**maxFileSize> </__**timeBasedFileNamingAndTriggeri**__ngPolicy> </rollingPolicy> <encoder class="ch.qos.logback.core.__**encoder.LayoutWrappingEncoder"**__> <layout class="com.foo.logging.__**AnsiColorLayout"/>
<pattern>%date{ISO8601} %p [%logger{5}.%method:%line] - %msg%n%rEx</pattern> </encoder> </appender>
And here's the relevant Java code:
Appender:
public class FooRollingFileAppender extends RollingFileAppender<__**ILoggingEvent> {
*** snip *** public void append(ILoggingEvent eventObject) { OutputStream os = this.getOutputStream(); // code to write out color formatted timestamp os.flush();
super.append(eventObject); } *** snip *** }
Layout:
public class AnsiColorLayout extends LayoutBase<ILoggingEvent> {
*** snip ***
public String doLayout(ILoggingEvent event) { return this.format(event); }
private String format(ILoggingEvent event) { StringBuilder sb = new StringBuilder(); switch (event.getLevel().toInt()) {
*** snip ***
} sb.append(event.__**getFormattedMessage());
sb.append(COLOR_DEFAULT); return sb.toString(); }
*** snip *** }
Thanks,
--adam
______________________________**_________________ Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/**listinfo/logback-user<http://mailman.qos.ch/mailman/listinfo/logback-user>

It's hard to say without looking at the actual code. Can you place your code in github? -- Ceki http://twitter.com/#!/ceki On 10.11.2011 00:50, Adam Gordon wrote:
That worked. My custom encoder is doing everything I want and more. For some reason, it looks like Logback is calling the doEncode(ILoggingEvent) twice as the log messages are showing up in duplicate. I've modified my XML to use the stock RollingFileAppender and my custom encoder. Any ideas? My encoder is definitely only calling the getFormattedMessage(...) method and writing it to the output stream once. Thanks.
--adam

Here you go: git://github.com/icfantv/color-logback.git Thanks. --a adam.n.gordon@gmail.com http://gordonizer.com On Nov 9, 2011, at 5:04 PM, ceki wrote:
It's hard to say without looking at the actual code. Can you place your code in github?
-- Ceki http://twitter.com/#!/ceki
On 10.11.2011 00:50, Adam Gordon wrote:
That worked. My custom encoder is doing everything I want and more. For some reason, it looks like Logback is calling the doEncode(ILoggingEvent) twice as the log messages are showing up in duplicate. I've modified my XML to use the stock RollingFileAppender and my custom encoder. Any ideas? My encoder is definitely only calling the getFormattedMessage(...) method and writing it to the output stream once. Thanks.
--adam
_______________________________________________ Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/listinfo/logback-user

Are you aware of appender additivity? http://logback.qos.ch/manual/architecture.html#additivity http://logback.qos.ch/manual/configuration.html#cumulative On 10.11.2011 05:44, Adam Gordon wrote:
Here you go: git://github.com/icfantv/color-logback.git
Thanks.
--a
------------------------------------------------------------------------ adam.n.gordon@gmail.com <mailto:adam.n.gordon@gmail.com> http://gordonizer.com
On Nov 9, 2011, at 5:04 PM, ceki wrote:
It's hard to say without looking at the actual code. Can you place your code in github?
-- Ceki http://twitter.com/#!/ceki
On 10.11.2011 00:50, Adam Gordon wrote:
That worked. My custom encoder is doing everything I want and more. For some reason, it looks like Logback is calling the doEncode(ILoggingEvent) twice as the log messages are showing up in duplicate. I've modified my XML to use the stock RollingFileAppender and my custom encoder. Any ideas? My encoder is definitely only calling the getFormattedMessage(...) method and writing it to the output stream once. Thanks.
--adam
-- Ceki http://twitter.com/#!/ceki

I was not. I'm currently sitting on an airplane so I cannot look more closely. is this my issue? I have only one appender defined so I'm a bit confused as to any implicit hierarchy. --adam On Nov 10, 2011, at 0:27, ceki <ceki@qos.ch> wrote:
Are you aware of appender additivity?
http://logback.qos.ch/manual/architecture.html#additivity http://logback.qos.ch/manual/configuration.html#cumulative
On 10.11.2011 05:44, Adam Gordon wrote:
Here you go: git://github.com/icfantv/color-logback.git
Thanks.
--a
------------------------------------------------------------------------ adam.n.gordon@gmail.com <mailto:adam.n.gordon@gmail.com> http://gordonizer.com
On Nov 9, 2011, at 5:04 PM, ceki wrote:
It's hard to say without looking at the actual code. Can you place your code in github?
-- Ceki http://twitter.com/#!/ceki
On 10.11.2011 00:50, Adam Gordon wrote:
That worked. My custom encoder is doing everything I want and more. For some reason, it looks like Logback is calling the doEncode(ILoggingEvent) twice as the log messages are showing up in duplicate. I've modified my XML to use the stock RollingFileAppender and my custom encoder. Any ideas? My encoder is definitely only calling the getFormattedMessage(...) method and writing it to the output stream once. Thanks.
--adam
-- Ceki http://twitter.com/#!/ceki _______________________________________________ Logback-user mailing list Logback-user@qos.ch http://mailman.qos.ch/mailman/listinfo/logback-user

Hopefully, reading the two links I mentioned in my previous message will make things clearer. On 10.11.2011 17:02, Adam Gordon wrote:
I was not. I'm currently sitting on an airplane so I cannot look more closely. is this my issue? I have only one appender defined so I'm a bit confused as to any implicit hierarchy.
--adam
On Nov 10, 2011, at 0:27, ceki<ceki@qos.ch> wrote:
Are you aware of appender additivity?
http://logback.qos.ch/manual/architecture.html#additivity http://logback.qos.ch/manual/configuration.html#cumulative
On 10.11.2011 05:44, Adam Gordon wrote:
Here you go: git://github.com/icfantv/color-logback.git
Thanks.
--a
------------------------------------------------------------------------ adam.n.gordon@gmail.com<mailto:adam.n.gordon@gmail.com> http://gordonizer.com
On Nov 9, 2011, at 5:04 PM, ceki wrote:
It's hard to say without looking at the actual code. Can you place your code in github?
-- Ceki http://twitter.com/#!/ceki
On 10.11.2011 00:50, Adam Gordon wrote:
That worked. My custom encoder is doing everything I want and more. For some reason, it looks like Logback is calling the doEncode(ILoggingEvent) twice as the log messages are showing up in duplicate. I've modified my XML to use the stock RollingFileAppender and my custom encoder. Any ideas? My encoder is definitely only calling the getFormattedMessage(...) method and writing it to the output stream once. Thanks.
--adam
participants (2)
-
Adam Gordon
-
ceki