Logback Additivity Example
If you use Logback or Log4j logging framework, you may come across some situations that you realize too much or too little log messages on the console or in a file. But you don’t actually understand how it happens. It is probably the consequence of the additivity attribute in the logging framework. So in this post, we shall discuss the additivity flag in the Logback framework.
1. Logback Framework
What is Logback? Logback is intended as a successor to the popular Log4j project. After broad experiences and feedbacks, Log4j’s founder, Ceki Gülcü also designed the Logback as a most popular and modern logging framework. You can find more information about Logback architecture and Logback configuration in one of my posts: Logback Syslog Example. In this part, I would like to discuss Logback named hierarchy and additivity.
But before going into detail, we should be sure that we are already familiar with Logger and Appender classes in the Logback. Briefly, loggers are logical, own-configurable components in the framework. Each log event for a given logger is forwarded to the relevant appender. Appender determines the log destination system such as console, file, e-mail, syslog…
1.1 Logback Named Hierarchy
In the Logback, Loggers have case-sensitive names and they follow the hierarchical naming rule: A logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. A logger is said to be a parent of a child logger if there are no ancestors between itself and the descendant logger. For example, the logger named “com.javacodegeeks” is a parent of the logger named “com.javacodegeeks.example”. Similarly, “java” is a parent of “java.util” and an ancestor of “java.util.List”. The root logger resides at the top of the logger hierarchy.
1.2 Logback Additivity
Appenders are added to the loggers. One logger may include more than one appenders. Thus, its log messages are written more than one desired destination systems. Additivity is exactly about this point.
The output of a log statement of logger A will go to all the appenders in A and its ancestors. However, if an ancestor of logger A, say B, has the additivity flag set to false, then A’s output will be directed to all the appenders in A and its ancestors up to and including B but not the appenders in any of the ancestors of B. Loggers have their additivity flag set to true by default.
In the table below, I design a logger named hierarchy with different varieties of appenders, additivity flags. You can see the target output as the result of this configuration.
Logger Name | Attached Appenders | Additivity Flag | Output Targets | Description |
---|---|---|---|---|
root | A1 | not applicable | A1 | The additivity flag does not apply to the root logger. |
com | A2, A3 | true | A1, A2, A3 | Appenders of “com” and of root. |
com.javacodegeeks | none | true | A1, A2, A3 | Appenders of “com” and of root. |
com.javacodegeeks.examples | A4 | true | A1, A2, A3, A4 | Appenders of “com.javacodegeeks.examples”, “com” and of root. |
com.javacodegeeks.applications | A5 | false | A5 | Additivity flag is false. So only appenders of “com.javacodegeeks.applications” |
com.javacodegeeks.applications.java | none | true | A5 | Only appenders of “com.javacodegeeks.applications” because its additivity flag is set to false. |
Logger Name | Attached Appenders | Additivity Flag | Output Targets |
---|---|---|---|
root | FILE1, STDOUT | not applicable | FILE1,STDOUT |
employee.director | FILE2 | true by default | FILE1, STDOUT, FILE2 |
employee.director.manager | FILE3 | false | FILE3 |
employee.director.manager.engineer | FILE4 | true by default | FILE3, FILE4 |
employee.director.manager.engineer.intern | FILE5 | false | FILE5 |
After execution, we obtain these results in the destination files and the console:
Console:
INFO employee.director - New Director is created. His/her name is : Ali
file1.log’s content:
INFO employee.director - New Director is created. His/her name is : Ali
file2.log’s content:
INFO employee.director - New Director is created. His/her name is : Ali
file3.log’s content:
INFO employee.director.manager - New Manager is created. His/her name is : Susan INFO employee.director.manager.engineer - New Engineer is created. His/her name is : Abony
file4.log’s content:
INFO employee.director.manager.engineer - New Engineer is created. His/her name is : Abony
file5.log’s content:
INFO e.director.manager.engineer.intern - New Intern is created. His/her name is : Mehmet
Now let’s discuss the results and criticize each statement in the ApplicationStarter
class:
The statement final Employee director = new Director( "Ali" );
gets the named logger employee.director run. FILE2 appender is attached to it. So the log message ( “New Director is created. His/her name is : Ali” ) in the Director
class is written to the “file2.log” file. Its additivity flag is set to true by default. Thus, the log message is also added to the appenders ( console and “file1.log” file ) of the root logger. Therefore, we surely see the same log message in the console, “file1.log” file and “file2.log” file.
The statement final Employee manager = new Manager( "Susan" );
gets the named logger employee.director.manager run. FILE3 appender is attached to it. So the log message ( “New Manager is created. His/her name is : Susan” ) in the Manager
class is written to the “file3.log” file. Its additivity flag is set to false. Thus, this message is not added to the appenders of the ancestor loggers ( “employee.director” named logger and root logger ) of the “employee.director.manager” named logger. Otherwise we see the message in file2, file1 and console.
The statement final Employee engineer = new Engineer( "Abony" );
gets the named logger employee.director.manager.engineer run. FILE4 appender is attached to it. So the log message ( “New Engineer is created. His/her name is : Abony” ) in the Engineer
class is written to the “file4.log” file. Its additivity flag is set to true by default. So the same message is added to the appenders ( “file3.log” file ) of its ancestor logger ( “employee.director.manager” named logger ). Please note that this message is also not added to the ancestor logger appenders higher than the “employee.director.manager” named logger. Because “employee.director.manager” named logger’s additivity flag is false. Log messages are written to the appenders of the ancestor loggers respectively until root logger or a additivity “false” logger in the hierarchy is encountered.
The statement final Employee intern = new Intern( "Mehmet" );
gets the named logger employee.director.manager.engineer.intern run. FILE5 appender is attached to it. So the log message ( “New Intern is created. His/her name is : Mehmet” ) in the Intern
class is written to the “file5.log” file. Its additivity flag is set to false. Thus, this message is not added to the appenders of the ancestor loggers.
4. Download the Eclipse Project
This project demonstrates how to use the “additivity flag” in the Logback framework. Download link is below.
You can download the full source code of this example here : logbackadditivityexample