[ 
https://issues.apache.org/jira/browse/LOG4J2-1630?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15560449#comment-15560449
 ] 

Ralph Goers commented on LOG4J2-1630:
-------------------------------------

Wow, our comments are getting long. I'd edit your comment to add mine but that 
would get confusing.

Yes, you clarified the Unit of Work case, but after thinking about it I've come 
to the conclusion that adding anything to the configuration to perform the 
buffering for that is complicated and probably the wrong approach.  Instead, I 
would suggest that for that use case you would want to use a UnitOfWorkMessage 
that contains an array of the things you want to capture. That said, I suspect 
you would need a UnitOfWorkFilter to add events to the Message that the 
application doesn't explicitly add and to determine if the UnitOfWork is 
complete. With a Message a "rollback" isn't required as the Message is just 
discarded.

I think before I get into how the EventBuffer would work I need to remind you 
of how the logging flow works, although I apologize because this should be old 
news to you. The application calls the logging method on the Logger. Before 
anything is done the isEnabled method is called which uses the global Filters 
attached to the Configuration to determine if the event should be logged. If 
there are no filters then just the log level of the Logger is checked. If it 
passes then LoggerConfig.log() is called. The LogEvent is then created and the 
event is filtered again. If it passes that filter the callAppenders is called 
which calls any Filters that were attached to the AppenderRef. Finally, if that 
passes the event is passed to the Appender where any Filters attached to the 
Appender are called. This is all described at 
http://logging.apache.org/log4j/2.x/manual/configuration.html#Filters with 
examples of each.

A Filter always accepts or denies a log event. An EventBuffer filter would be 
no different, except that it would store the event to possibly be logged later. 
Denying the event is the only way to return control to the application without 
having the event flow all the way to the Appender.

As far as the EventBuffer goes example a) is probably the most useful as that 
is where all events can be buffered without having to go through any filtering. 
Placing the EventBuffer anywhere else introduces the possibility that the event 
will already have been discarded (which may or may not be desirable). 

The EventBuffer would contain a ring of empty LogEvents that contains all the 
items that can be passed on a logging call. In case a) it caches all events 
before they are handled by any Logger (although the call to do the filtering is 
done by a Logger) by copying the individual parameters into a LogEvent and it 
releases these to Loggers by calling the Logger's logMessage method (which 
means a reference to the Logger needs to be in the EventBuffer along with the 
event data).  In case b) The event will be buffered in the LoggerConfig 
associated with the Logger before it is passed to any appenders, which means it 
might be associated with multiple Loggers. In this case when the trigger fires 
the EventBuffer needs to call the LoggerConfig's callAppenders method.  In case 
c) the event is buffered - inside the AppenderControl attached to the 
LoggerConfig before it is passed to the Appender, so the buffer only applies to 
events that may pass to the Appender through this LoggerConfig and will not 
apply to other appender references within that LoggerConfig. When the trigger 
occurs the events would have to pass to a new method in AppenderControl that 
calls isRecursiveCall() followed by callAppenderPreventRecursion().  In case d) 
the buffer is within the Appender. When the trigger occurs the events are 
passed to the Appender's append() method.

So yes, you are missing use cases. The EventBuffer should be able to placed 
anywhere a Filter can reside, which is precisely why making it a Filter is the 
right thing to do.

> Unit of Work Logging
> --------------------
>
>                 Key: LOG4J2-1630
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-1630
>             Project: Log4j 2
>          Issue Type: Story
>          Components: API, Core, Filters
>    Affects Versions: 2.7
>            Reporter: Remko Popma
>             Fix For: 2.8
>
>
> h3. Intent
> Provide a way to filter log events, where the decision on whether to discard 
> the message or actually log them cannot be made until after the application 
> has already logged the message.
> h3. Motivation
> In many systems, particularly event processing applications, log files 
> contain a lot of repetitive log messages. Suppose an application needs to do 
> some calculation to decide whether or not to react to some event, and a lot 
> of detail is logged during this calculation. Imagine that 99% of the time, 
> the application decides to take no action. Once the application arrived at 
> that conclusion it would be nice if we could go back and undo all the 
> detailed logging and print a summary instead. When the application _does_ 
> decide to take some action, however, we _do_ want the detailed log messages. 
> A Unit of Work for logging would allow us to group a set of log messages and 
> either discard them or log them together. (Inspired by Martin Fowler's [Unit 
> of Work|http://martinfowler.com/eaaCatalog/unitOfWork.html] pattern.)
> This should result in log files where a lot of the "uninteresting" logging is 
> filtered out, significantly reducing the amount of data logged.
> Some applications do this in an ad hoc manner, for example by passing a 
> Collection to its components, where these components can add log message 
> strings to this Collection. When the discard/retain decision is made, the 
> application then either clears the Collection or logs the contents of the 
> Collection. This works, but having to pass the Collection down the component 
> tree is clunky and the result often omits details like logger name, timestamp 
> and other details that come for free with normal logging. Log4j can provide a 
> reusable and less intrusive way to accomplish this.
> h3. How it works
> There would need to be some API for the application to mark the _start_ of 
> the unit of work, and some API to signal whether the log messages that are 
> part of that unit of work need to be _discarded_ or _logged_ (retained).
> Not all logging that occurs after a unit of work was started is part of that 
> unit of work. The application may want some messages to be logged regardless 
> of whether the unit of work was discarded or not. There needs to be a 
> flexible way (or multiple ways) to include or exclude logging statements from 
> the unit of work. 
> The application may also designate multiple units of work, which may be 
> sequential, nested or partially overlapping. Each unit of work may define its 
> own rules for which log messages are considered included in or excluded from 
> the unit of work.



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

Reply via email to