logging-log4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Remko Popma (JIRA)" <j...@apache.org>
Subject [jira] [Resolved] (LOG4J2-1342) ReusableParameterizedMessage should preserve parameters when used with Async Loggers
Date Fri, 22 Apr 2016 06:10:12 GMT

     [ 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-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org


Mime
View raw message