Type: New Feature
Affects Version/s: None
Fix Version/s: None
Here's my use case:
I have an appender, standard.log, whose job is to log major system events such as startup and shutdown, and all problems. I have configured my logger levels very carefully to ensure I get exactly the output I want - in some cases suppressing WARN messages that I know are not a problem by setting the level to ERROR, in some cases allowing INFO messages that let me see important lifecycle events.
A simplified example might look like this:
I have a problem in a couple of parts of the system which means I want to turn on debug logging for that part of the system. I want the output of this to go to a separate appender - debug.log.
So now my config looks like this:
But now I have an issue; all my debug statements are going to standard.log. It is being polluted with a load of information I don't want in it.
I have several options:
1) Set additivity to false on x.y.z and a.b.
But then any ERROR messages in a.b or INFO or above messages in x.y.z no longer get to standard.log, so this won't do
2) Add a filter of INFO or greater to the standard.log appender
But then any INFO and WARN messages in a.b will get to standard.log - and I only want ERROR messages from a and its descendants in there
3) Add a filter of WARN or greater to the standard.log appender
Now I still get the WARN messages from a.b that I don't want - and I've lost the INFO messages from x.y that I do want
4) Create two new appenders, standard.log2 for a and standard.log3 for x.y.z. Add a filter to standard.log2 so that it only accepts ERROR. Add a filter to standard.log3 so it only accepts INFO or above. Set additivity to false on a and x.y.z.
That works. But it's a huge amount of added configuration, and that would rapidly multiply in a real world setting.
5) Create a custom filter for standard.log which would effectively mirror the logger config by querying the event for its logger and and level.
That blows DRY out of the water, of course, and again is a large amount of work for a simple use case.
My suggestion to make this easy is to allow Appenders to be added to a Logger with a Level. This solution would operate in parallel with the existing solution, and would not alter the existing behaviour one iota.
This would allow me to add debug,log as an appender on a and x.y.z with a level of debug. All debug statements in a and x.y.z & their descendants would be appended to that appender. All statements would also be passed to the "normal" appender and logger hierarchy, so standard.log would still get the same output as before.
I have written unit tests for this behaviour and attach a patch fulfilling them; I hope the unit tests flesh out any queries you may have around how this behaves in edge cases.
The only change to the public API is a new method addAppender(Appender<LoggingEvent> newAppender, Level level) on Logger.
The only change to the config format is allowing an optional level attribute on appender-ref.