[ 
https://issues.apache.org/jira/browse/LOG4J2-2874?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Volkan Yazici updated LOG4J2-2874:
----------------------------------
    Labels:   (was: blocking)

> StringBuilderFormattable check failure in layouts due to wrapped Message
> ------------------------------------------------------------------------
>
>                 Key: LOG4J2-2874
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-2874
>             Project: Log4j 2
>          Issue Type: Bug
>            Reporter: Volkan Yazici
>            Priority: Major
>
> Upon further investigation on [Fred Eisele's question in the mailing 
> list|http://mail-archives.apache.org/mod_mbox/logging-log4j-user/202006.mbox/%3CCAJGQK3M63cx37tfLUSB0X9x3U8PmvUdDOigX-kUTMs6r2nP6hg%40mail.gmail.com%3E],
>  I figured {{Layout}}'s way of handling {{Message}}'s of type 
> {{StringBuilderFormattable}} is broken when the actual message is wrapped by 
> some other message. Consider the following Java code:
> {code:java}
> import org.apache.logging.log4j.message.Message;
> import org.apache.logging.log4j.util.StringBuilderFormattable;
> import org.junit.Test;
> public class TraceExitTest {
>     @Test
>     public void test() {
>         System.setProperty(
>                 "log4j.configurationFile",
>                 "/tmp/traceExit.xml");
>         Logger logger = LogManager.getLogger("TraceExit");
>         int result = logger.traceExit(
>                 new CustomMessage("Volkan was here"),
>                 1);
>         logger.warn("result = %d", result);
>     }
>     private static final class CustomMessage
>             implements Message, StringBuilderFormattable {
>         private final String text;
>         private CustomMessage(String text) {
>             this.text = text;
>         }
>         @Override
>         public String getFormattedMessage() {
>             throw new UnsupportedOperationException();
>         }
>         @Override
>         public String getFormat() {
>             return "";
>         }
>         @Override
>         public Object[] getParameters() {
>             return new Object[0];
>         }
>         @Override
>         public Throwable getThrowable() {
>             return null;
>         }
>         @Override
>         public void formatTo(StringBuilder buffer) {
>             buffer.append(text);
>         }
>     }
> }
> {code}
> In combination with the following {{/tmp/traceExit.xml}}:
> {code:xml}
> <?xml version="1.0" encoding="UTF-8"?>
> <Configuration status="ERROR">
>     <Appenders>
>         <Console name="Console" target="SYSTEM_OUT">
>             <PatternLayout pattern="%msg%n%throwable"/>
>         </Console>
>     </Appenders>
>     <Loggers>
>         <Root level="TRACE">
>             <AppenderRef ref="Console"/>
>         </Root>
>     </Loggers>
> </Configuration>
> {code}
> Log4j produces the {{An exception occurred processing Appender Console 
> java.lang.UnsupportedOperationException}} error message. In the case of
> {{PatternLayout}}, it handles {{StringBuilderFormattable}} with a simple
> {{instanceof}} check -- just like any other layout. Though check out the
> following {{AbstractLogger#traceExit()}} implementation:
> {code:java}
> @Override
> public <R> R traceExit(final Message message, final R result) {
>     // If the message is null, traceEnter returned null because ...
>     if (message != null && isEnabled(Level.TRACE, EXIT_MARKER, message, 
> null)) {
>         logMessageSafely(...,
> flowMessageFactory.newExitMessage(result, message), null);
>     }
>     return result;
> }
> {code}
>  
> {{CustomMessage}} gets wrapped by a 
> {{DefaultFlowMessageFactory.SimpleExitMessage}} invalidating the {{instanceof 
> StringBuilderFormattable}} check.
> One can fix the existing layouts by improving the check as follows:
> {code:java}
> final boolean formattable =
>         logEvent.getMessage() instanceof StringBuilderFormattable ||
>                 (logEvent.getMessage() instanceof FlowMessage && 
> ((FlowMessage) logEvent.getMessage()) instanceof StringBuilderFormattable);
> {code}
> Though I have my doubts if this will cover every single case.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to