[ https://issues.apache.org/jira/browse/LOG4J2-1630?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15559192#comment-15559192 ]
Ralph Goers commented on LOG4J2-1630: ------------------------------------- Remko, thanks for the update. I see the scenario more like this: a) A Global EventBuffer. In this case all events are buffered until an error level log event is encountered. At that point events are passed to the appropriate loggers for processing. {code} <?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <EventBuffer name="timeMachine" size="128"> <ThresholdFilter level="ERROR"/> <!-- flush buffer if an event with ERROR level is enqueued --> </EventBuffer> <Appenders> <Console name="console" target="SYSTEM_OUT"><PatternLayout pattern="%d [%t] %p %c{36} - %m%n"/></Console> <File name="file" fileName="app.log" ><PatternLayout pattern="%d [%t] %p %c{1.} - %m%n"/></File> <File name="errors" fileName="err.log" ><PatternLayout pattern="%d [%t] %p %c{1.} - %m%n"/></File> </Appenders> <Loggers> <Root level="trace"> <AppenderRef ref="file" level="trace" /> <!-- logs all events that were buffered --> <AppenderRef ref="errors" level="error" /> <!-- logs only the error events --> </Root> </Loggers> </Configuration> {code} b) An EventBuffer for a particular Logger (the root logger in this example). Only events for that Logger are accumulated and are all passed to the Logger with the triggering event occurs. {code} <?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="console" target="SYSTEM_OUT"><PatternLayout pattern="%d [%t] %p %c{36} - %m%n"/></Console> <File name="file" fileName="app.log" ><PatternLayout pattern="%d [%t] %p %c{1.} - %m%n"/></File> <File name="errors" fileName="err.log" ><PatternLayout pattern="%d [%t] %p %c{1.} - %m%n"/></File> </Appenders> <Loggers> <Root level="trace"> <EventBuffer name="file" size="128"> <ThresholdFilter level="ERROR"/> <!-- flush buffer if an event with ERROR level is enqueued --> </EventBuffer> <AppenderRef ref="file" level="trace" /> <!-- logs all events that were buffered --> <AppenderRef ref="errors" level="error" /> <!-- logs only the error events --> </Root> </Loggers> </Configuration> {code} c) An EventBuffer for a particular Appender reference. The events are queued and when the event occurs they are passed to the appender. <?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="console" target="SYSTEM_OUT"><PatternLayout pattern="%d [%t] %p %c{36} - %m%n"/></Console> <File name="file" fileName="app.log" ><PatternLayout pattern="%d [%t] %p %c{1.} - %m%n"/></File> <File name="errors" fileName="err.log" ><PatternLayout pattern="%d [%t] %p %c{1.} - %m%n"/></File> </Appenders> <Loggers> <Root level="trace"> <AppenderRef ref="file" level="trace" ><!-- logs all events that were buffered --> <EventBuffer name="timeMachine" size="128"> <ThresholdFilter level="ERROR"/> <!-- flush buffer if an event with ERROR level is enqueued --> </EventBuffer> </AppenderRef> <AppenderRef ref="errors" level="error" /> <!-- logs only the error events --> </Root> </Loggers> </Configuration> {code} d) An EventBuffer for a particular Appender. The events directed to the Appender are queued and when the triggering event occurs they are passed to the appender.{code} <?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="console" target="SYSTEM_OUT"><PatternLayout pattern="%d [%t] %p %c{36} - %m%n"/></Console> <File name="file" fileName="app.log" ><PatternLayout pattern="%d [%t] %p %c{1.} - %m%n"/> <EventBuffer name="timeMachine" size="128"> <ThresholdFilter level="ERROR"/> <!-- flush buffer if an event with ERROR level is enqueued --> </EventBuffer> </File> <File name="errors" fileName="err.log" ><PatternLayout pattern="%d [%t] %p %c{1.} - %m%n"/></File> </Appenders> <Loggers> <Root level="trace"> <AppenderRef ref="file" level="trace" /> <!-- log all events when a trigger occurs --> <AppenderRef ref="errors" level="error" /> <!-- logs only the error events --> </Root> </Loggers> </Configuration> {code} Note that in this particular example you get the same behavior no matter when you place the EventBuffer but that wouldn't always be the case. Also note that the EventBuffer is really an instance of a Filter. The only thing getting in the way of implementing this is that we need to pass the EventBuffer its parent component and ideally its component type so that it can know how to deliver the events once the trigger occurs. I have thought of a couple of ways to do that. My preference would be to add a getParent method to the Configuration that takes the EventBuffer object as the parameter. Since Plugins can all access the configuration the only change required would be to implement a Map to the configuration. > 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