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