Is there a way to create a log4j Logger at runtime that will gather logging messages into a buffer?
I currently have a class that logs a number of events. For a remote application that needs to monitor the logged events, I'd like to just swap in a logger that logs to a buffer and then retrieve the buffer, rather than refactor the class. E.g. given something like:
Class Foo{
Logger log = ....;
public void doSomething(){
log.debug(...
.. actual code
log.debug(...
}
}
//what I'd like to do from some outside code:
String showFooLog(){
Foo f = new Foo();
f.log=new Logger(...
f.doSomething();
return f.log.contents();
}
Is this possible?
Edit: Found a shorter solution, pointed to from Jared's posting( although it's still not threadsafe). Thanks for the help.
Logger l = Logger.getLogger( ... );
StringWriter writer = new StringWriter();
WriterAppender appender = new WriterAppender( new HTMLLayout(), writer );
l.addAppender( appender );
... run code here
writer.flush();
l.removeAppender( appender );
return writer.toString()
It's absolutely possible - although you're probably going to need to create your own Appender. This is really easy to do, though. Here's a rough-out of an example (need to think out thread-safety...this isn't threadsafe....and I'm not sure I like the statics...but this should be good enough to push you in the right direction):
public class BufferAppender extends org.apache.log4j.AppenderSkeleton {
private static Map<String, StringBuffer> buffers = new HashMap<String, StringBuffer>();
@Override
protected void append(LoggingEvent evt) {
String toAppend = this.layout.format(evt);
StringBuffer sb = getBuffer(evt.getLoggerName());
buffer.append(toAppend);
}
public static String getBufferContents(String loggerName) {
StringBuffer sb = buffers.get(sb);
if(sb == null) {
return null;
} else {
return sb.toString();
}
}
public static void clearBuffer(String loggerName) {
createBuffer(loggerName);
}
private static StringBuffer getBuffer(String loggerName) {
StringBuffer sb = buffers.get(loggerName);
if(sb == null) {
sb = createBuffer(loggerName);
}
return sb;
}
private static StringBuffer createBuffer(String loggerName) {
StringBuffer sb = new StringBuffer();
buffers.put(loggerName, sb);
return sb;
}
}
You could subclass org.apache.log4j.WriterAppender and provide it a ByteArrayOutputStream to store any messages. See the other subclasses of WriterAppender for inspriation. Then you can provide an instance of that object to your logger for appending via addAppender.