You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@logging.apache.org by "Volkan Yazici (Jira)" <ji...@apache.org> on 2020/06/18 09:28:00 UTC

[jira] [Created] (LOG4J2-2874) StringBuilderFormattable check failure in layouts due to wrapped Message

Volkan Yazici created LOG4J2-2874:
-------------------------------------

             Summary: 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


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)