
Hello Lukas, I just added one line to your code, after errAppender.start(); errAppender.start(); StatusPrinter.print(lc); <--- this is the new line of code This resulted in the following output (edited for brevity): INFO in c.q.l.c.LoggerContext - Could NOT find resource logback-test.xml] INFO in c.q.l.c.LoggerContext - Could NOT find resource [logback.xml] INFO in c.q.l.c.LoggerContext - Setting up default configuration. ERROR in ErrorCounterAppender - No layout set for the appender named [null]. The error message explains the reasons for the behavior you are seeing. HTH, Lukas Zapletal wrote:
Hello,
I need to count number of error messages coming thru SLF4J into my app and integrate this number with System.exit() call at the end of the program.
I have found that best solution would be to write an appender and dynamicaly add it in the code of my application. I am configuring logging by calling LoggerConfigurer (loading XML file) but I do not want to have my appender in this configuration - I do want to configure it dynamically not allowing user to modify XML and disable this error counter appender. But this does not work - the new appender method append() is never called. I think there is a problem with context or something. Here is the code:
public class Test { final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Test.class);
public void main(String[] args) { String fileName = "myfile.xml"; LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
try { JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); // the context was probably already configured by default configuration // rules lc.shutdownAndReset(); configurator.doConfigure(fileName);
ErrorCounterAppender errAppender = new ErrorCounterAppender(); Logger root = LoggerFactory.getLogger(LoggerContext.ROOT_NAME); errAppender.setContext(lc); errAppender.start(); ((ch.qos.logback.classic.Logger) root).addAppender(errAppender); logger.error("TEST"); logger.info("Number of errors: {}", errAppender.getErrorNumber()); // prints 0 System.exit(errAppender.getErrorNumber()); // returns 0 (instead of 1)
} catch (Throwable t) { logger.warn("Cannot configure logger from location " + fileName, t); } StatusPrinter.print(lc); }
}
I think there must be some problem in the context or something. Or is there any better solution of my problem? Here is my appender:
/**
* Thread-safe implementation of error counter appender for LogBack.
*/
public class ErrorCounterAppender extends AppenderBase<LoggingEvent> {
AtomicInteger errorCounter = new AtomicInteger(0);
private Layout<LoggingEvent> layout;
public ErrorCounterAppender() {
}
@Override
public void setLayout(Layout<LoggingEvent> layout) {
this.layout = layout;
}
public void resetErrorNumber() {
errorCounter.set(0);
}
public int getErrorNumber() {
return errorCounter.get();
}
@Override
public void start() {
if (this.layout == null) {
addError("No layout set for the appender named [" + name + "].");
return;
}
super.start();
}
@Override
public void append(LoggingEvent event) {
if (event == null)
return;
if (Level.ERROR == event.getLevel()) {
errorCounter.incrementAndGet();
}
}
}
----- -- Lukas Zapletal http://lukas.zapletalovi.com
-- Ceki Gülcü Logback: The reliable, generic, fast and flexible logging framework for Java. http://logback.qos.ch