[ https://issues.apache.org/jira/browse/LOG4J2-2118?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16258603#comment-16258603 ]
Zack Slayton commented on LOG4J2-2118: -------------------------------------- Ah, it seems that invoking {code:java} Message::getFormat {code} on [the incoming Message|https://github.com/apache/logging-log4j2/pull/131/files#diff-f108bde06d206362a7cb6d92a1837b13R213] causes temporary objects to be created in some implementations (e.g. ReusableSimpleMessage). I'm unsure how to best address this without introducing a new interface that requires no allocations. > MutableLogEvent does not retain the Message format string > --------------------------------------------------------- > > Key: LOG4J2-2118 > URL: https://issues.apache.org/jira/browse/LOG4J2-2118 > Project: Log4j 2 > Issue Type: Bug > Components: Layouts > Affects Versions: 2.8 > Environment: Mac OS X 10.11.6 > Java 1.8.0_141 > Reporter: Zack Slayton > Labels: layout > > I'm attempting to create a custom binary Layout that stores the provided > format string separate from the parameters rather than eagerly formatting > them all into a single piece of text. However, when I went to implement > `Layout::toByteArray`, I discovered that the `Message::getFormat` method > always returns null. > {code:java} > import org.apache.logging.log4j.LogManager; > import org.apache.logging.log4j.Logger; > import org.apache.logging.log4j.core.LogEvent; > import org.apache.logging.log4j.core.config.plugins.Plugin; > import org.apache.logging.log4j.core.config.plugins.PluginFactory; > import org.apache.logging.log4j.core.layout.AbstractLayout; > import java.io.Serializable; > import java.util.Arrays; > @Plugin(name = "MyLayout", category = "Core", elementType = "layout", > printObject = true) > public class MyLayout extends AbstractLayout { > public MyLayout() { > super(null, null, null); > } > @PluginFactory > public static MyLayout createLayout(){ > return new MyLayout(); > } > public static void main(String[] args) { > Logger log = LogManager.getLogger(MyLayout.class); > log.info("Here's a thing: {}. And another: {}", 75, "walrus"); > } > @Override > public byte[] toByteArray(LogEvent event) { > System.out.println("Format: " + event.getMessage().getFormat()); > System.out.println("Parameters: " + > Arrays.toString(event.getMessage().getParameters())); > return new byte[0]; > } > @Override > public Serializable toSerializable(LogEvent event) { > return null; > } > @Override > public String getContentType() { > return null; > } > @Override > public byte[] getFooter() { > return new byte[0]; > } > @Override > public byte[] getHeader() { > return new byte[0]; > } > } > {code} > If I run `main` (with an extra `PatternLayout`+`Console` appender in my > config), I see the following output: > {code} > 17:55:28.524 [main] INFO com.example.logging.plugins.MyLayout - Here's a > thing: 75. And another: walrus > Format: null > Parameters: [75, walrus] > {code} > I had expected to be able to see the format string and the array of > parameters, but instead I can only see the parameters. The format string is > always null. > This appears to be due to the implementation of `MutableLogEvent::setMessage` > highlighted [in > LOG4J2-1510|https://issues.apache.org/jira/browse/LOG4J2-1510]. Because the > messages are reusable, they appear to be eagerly formatted and the format > string itself is discarded. The `getFormat` method is hardcoded to return > `null`. > Is this by design? If so, what is the prescribed approach to getting the > format string in my layout? (Preferably one that does not disable the > performance optimizations offered by enabling threadlocals.) > Thanks! -- This message was sent by Atlassian JIRA (v6.4.14#64029)