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)