[ https://issues.apache.org/jira/browse/LOG4J2-1342?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Remko Popma resolved LOG4J2-1342. --------------------------------- Resolution: Fixed Fixed in master. The following methods were added to {{ReusableMessage}}: - memento() - takes immutable snapshot, for use by AsyncAppender - swapParameters(Object[] emptyReplacement) : Object[] - getParameterCount() Layouts that want to be garbage-free and have access to the original parameters should use this pattern: {code} final static Object[] DUMMY = new Object[10]; ... public void encode(LogEvent event, ByteBufferDestination destination) { if (event.getMessage() instanceof ReusableMessage) { ReusableMessage reusable = (ReusableMessage) event.getMessage(); Object[] params = reusable.swap(DUMMY); reusable.swap(params); // swap back, or DUMMY will be modified by other thread later for (int i = 0; i < reusable.getParameterCount(); i++) { doSomethingWithParam(i, params[i]); } } .... } {code} > ReusableParameterizedMessage should preserve parameters when used with Async > Loggers > ------------------------------------------------------------------------------------ > > Key: LOG4J2-1342 > URL: https://issues.apache.org/jira/browse/LOG4J2-1342 > Project: Log4j 2 > Issue Type: Bug > Components: API > Affects Versions: 2.6 > Reporter: Remko Popma > Assignee: Remko Popma > Fix For: 2.6 > > > *Problem* > Some layouts (like CsvParameterLayout) need access to the message parameters. > With the current garbage-free asynchronous logging implementation the > formatted message text is passed correctly, but parameter information is no > longer passed on. > *Analysis* > ReusableParameterizedMessage instances are mutable by design and their > contents may be overwritten with the next call to {{Logger.log}}. > For synchronous logging this is not an issue since the message contents will > have been fully processed by the appenders before this happens. > With asynchronous logging, the log event and its contents need to be handed > off to the background thread, and we need to ensure that this data is not > modified by another call to {{Logger.log}} before the background thread can > process it. Different async logging mechanisms handle this in different ways: > *Async Appender* > This appender takes a snapshot of the LogEvent before enqueueing it. This is > implemented by invoking {{Log4jLogEvent.serialize(LogEvent)}}. The Message > contents is turned into text with {{Message.getFormattedString()}} and a new > {{SimpleMessage}} is created with this text. In the process, any parameters > of the original message are lost. > This mechanism does not try to be garbage-free, so one solution would be to > add a method {{createMemento() : Message}} to ReusableMessage. > ReusableParameterizedMessage could implement this to copy the parameter > values into the memento copy. > *All Loggers Async* > This has a ring buffer with pre-allocated RingBufferLogEvent objects. Values > are copied into these RingBufferLogEvents for each call to {{Logger.log}}. If > the message is a ReusableMessage, RingBufferLogEvent will call > {{message.formatTo(StringBuilder}} to copy the formatted message text to a > StringBuilder held by the the RingBufferLogEvent. This only copies the > formatted text, any parameters of the original message are lost. > Potential solution: RingBufferLogEvent could have an Object[] array field to > hold parameters. When the RingBufferLogEvent is populated, the > ReusableMessage could swap its parameter array with the RingBufferLogEvent's > parameter array. > There needs to be a method in ReusableMessage to allow this swap. > Consideration: when RingBufferLogEvent.clear() is called, the array elements > need to be nulled out to prevent memory leaks. > *Mixed Sync/Async Loggers* > This has a ring buffer with pre-allocated Log4jEventWrapper objects. In > classic mode, when {{Logger.log}} is called a new Log4jLogEvent is created > and set in the Log4jEventWrapper. In garbage-free mode, the Log4jEventWrapper > is pre-allocated with MutableLogEvent objects and the values from the > {{Logger.log}} call are copied into the ringbuffer's MutableLogEvent. In that > case we have the same problem as with _All Loggers Async_: If the message is > a ReusableMessage, RingBufferLogEvent will call > {{message.formatTo(StringBuilder}} to copy the formatted message text to a > StringBuilder held by the the RingBufferLogEvent. This only copies the > formatted text, any parameters of the original message are lost. -- This message was sent by Atlassian JIRA (v6.3.4#6332) --------------------------------------------------------------------- To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org