[
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)