For my LogBack logger, I am trying to programtically create an OutputStreamAppender that writes to a ByteArrayOutputStream. Here is what I have so far:
// Destination stream
ByteArrayOutputStream printStream = new ByteArrayOutputStream();
// Get LoggerContext from SLF4J
LoggerContext context = (LoggerContext)LoggerFactory.getILoggerFactory();
// Encoder
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setContext(context);
encoder.setPattern("%d{HH:mm:ss} %-5level %logger{36} - %msg%n");
encoder.start();
// OutputStreamAppender
OutputStreamAppender<ILoggingEvent> appender= new OutputStreamAppender<>();
appender.setName( "OutputStream Appender" );
appender.setContext(context);
appender.setOutputStream(printStream);
appender.setEncoder(encoder);
appender.start();
Logger log = context.getLogger(this.getClass());
log.addAppender(appender);
log.info( "text from logger");
// Output to stdout logback status
StatusPrinter.print(context);
Based on everything I have read, this should be correct. Nothing from the Logger is written to the stream and the OutputStreamAppender fails to correctly initialize according to the output from StatusPrinter
:
15:26:30,330 |-WARN in ch.qos.logback.core.OutputStreamAppender[OutputStream Appender] - Encoder has not been set. Cannot invoke its init method.
15:26:30,335 |-ERROR in ch.qos.logback.core.OutputStreamAppender[OutputStream Appender] - Appender [OutputStream Appender] failed to append. java.lang.NullPointerException
at java.lang.NullPointerException
at at ch.qos.logback.core.encoder.LayoutWrappingEncoder.doEncode(LayoutWrappingEncoder.java:135)
at at ch.qos.logback.core.OutputStreamAppender.writeOut(OutputStreamAppender.java:188)
at at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:212)
at at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:103)
at at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:88)
at at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:48)
at at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:272)
at at ch.qos.logback.classic.Logger.callAppenders(Logger.java:259)
at at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:441)
at at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:395)
at at ch.qos.logback.classic.Logger.info(Logger.java:599)
I am stumped by the warning and NPE at LayoutWrappingEncoder.doEncode(LayoutWrappingEncoder)
. I am setting the encoder on the Appender.
After poking around the source code, I found the encoder has to be set before the output stream:
OutputStreamAppender<ILoggingEvent> appender= new OutputStreamAppender<>();
appender.setName( "OutputStream Appender" );
appender.setContext(context);
appender.setEncoder(encoder); // <-- must be set before outputstream
appender.setOutputStream(printStream);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With