Each Logger references the appropriate
LoggerConfig, which in turn can reference its parent. If you don’t specify
logging level to a LoggerConfig, then it gets the logging level from parent Logger
Configuration.
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="DEBUG"> <Appenders> <Console name="my_console_appender" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </Console> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="my_console_appender" /> </Root> <Logger name="x.y.z"> <AppenderRef ref="my_console_appender" /> </Logger> </Loggers> </Configuration>
PrintDataUtil.java
package x.y.z; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class PrintDataUtil { private static final Logger log = LogManager.getLogger(); public static void printData(){ log.trace("Trace Message!"); log.debug("Debug Message!"); log.info("Info Message!"); log.warn("Warn Message!"); log.error("Error Message!"); log.fatal("Fatal Message!"); } }
HelloWorld.java
package log4j_tutorial; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import x.y.z.PrintDataUtil; public class HelloWorld { private static final Logger log = LogManager.getLogger(); public static void printData() { log.trace("Trace Message!"); log.debug("Debug Message!"); log.info("Info Message!"); log.warn("Warn Message!"); log.error("Error Message!"); log.fatal("Fatal Message!"); } public static void main(String args[]) { printData(); PrintDataUtil.printData(); } }
When you ran
HelloWorld application, you will get following statements in console.
15:05:36.935 [main] INFO log4j_tutorial.HelloWorld - Info Message! 15:05:36.936 [main] WARN log4j_tutorial.HelloWorld - Warn Message! 15:05:36.936 [main] ERROR log4j_tutorial.HelloWorld - Error Message! 15:05:36.936 [main] FATAL log4j_tutorial.HelloWorld - Fatal Message! 15:05:36.937 [main] INFO x.y.z.PrintDataUtil - Info Message! 15:05:36.937 [main] INFO x.y.z.PrintDataUtil - Info Message! 15:05:36.937 [main] WARN x.y.z.PrintDataUtil - Warn Message! 15:05:36.937 [main] WARN x.y.z.PrintDataUtil - Warn Message! 15:05:36.937 [main] ERROR x.y.z.PrintDataUtil - Error Message! 15:05:36.937 [main] ERROR x.y.z.PrintDataUtil - Error Message! 15:05:36.937 [main] FATAL x.y.z.PrintDataUtil - Fatal Message! 15:05:36.937 [main] FATAL x.y.z.PrintDataUtil - Fatal Message!
Notice the output, the log messages from
‘x.y.z’ repeated twice. This is because the appender associated with logger x.y.z
is first used, which writes the first instance to the Console. Next, the parent
of x.y.z, which in this case is the root logger, is referenced. The event is
then passed to its appender, which is also writes to the Console, resulting in
the second instance. This feature is known as additivity. But additivity some
times makes you irritate by printing log messages twice to the console/file/or
some external system.
Disable
Additivity
You can disable additivity feature, by
setting the attribute ‘additivity’ to false. Once an event reaches a logger
with its additivity set to false, the event will not be passed to any of its
parent loggers, regardless of their additivity setting.
<Logger
name="x.y.z" additivity="false">
<AppenderRef
ref="my_console_appender" />
</Logger>
Complete log4j2.xml looks like below.
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="DEBUG"> <Appenders> <Console name="my_console_appender" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </Console> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="my_console_appender" /> </Root> <Logger name="x.y.z" additivity="false"> <AppenderRef ref="my_console_appender" /> </Logger> </Loggers> </Configuration>
Re run
HelloWorld application, by disabling additivity, you will get following output
in console.
15:11:43.472 [main] INFO log4j_tutorial.HelloWorld - Info Message! 15:11:43.472 [main] WARN log4j_tutorial.HelloWorld - Warn Message! 15:11:43.472 [main] ERROR log4j_tutorial.HelloWorld - Error Message! 15:11:43.472 [main] FATAL log4j_tutorial.HelloWorld - Fatal Message! 15:11:43.473 [main] INFO x.y.z.PrintDataUtil - Info Message! 15:11:43.473 [main] WARN x.y.z.PrintDataUtil - Warn Message! 15:11:43.473 [main] ERROR x.y.z.PrintDataUtil - Error Message! 15:11:43.473 [main] FATAL x.y.z.PrintDataUtil - Fatal Message!
Example 2
Whenever application
requests a logger with specific name from the LogManager, LogManager locate the
appropriate LoggerContext, next obtain the Logger from it. LoggerConfig
objects are created from Logger declarations in the configuration.
If the
Logger must be created it will be associated with the LoggerConfig that
contains either
a) the same
name as the Logger,
b) the name
of a parent package,
c) the root
LoggerConfig.
For example,
Logger
Name
|
Assigned
LoggerConfig
|
LoggerConfig
Level
|
Level
|
root
|
root
|
DEBUG
|
DEBUG
|
x
|
x
|
ERROR
|
ERROR
|
x.y
|
x
|
ERROR
|
ERROR
|
x.y.z
|
x.y.z
|
WARN
|
WARN
|
As shown in
above table, the loggers root, x and x.y.z each have a configured LoggerConfig
with the same name. The Logger x.y does not have a configured LoggerConfig with
a matching name so uses the configuration of LoggerConfig x (x is the parent of
x.y), since that is the LoggerConfig whose name has the longest match to the
start of the Logger's name.
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="DEBUG" monitorInterval="30"> <Appenders> <Console name="my_console_appender" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </Console> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="my_console_appender" /> </Root> <Logger name="x" level="error" /> <Logger name="x.y.z" level="warn" /> </Loggers> </Configuration>
package x; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class PrintDataUtil1 { private static final Logger log = LogManager.getLogger(); public static void printData() { log.trace("Trace Message!"); log.debug("Debug Message!"); log.info("Info Message!"); log.warn("Warn Message!"); log.error("Error Message!"); log.fatal("Fatal Message!"); } }
package x.y; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class PrintDataUtil2 { private static final Logger log = LogManager.getLogger(); public static void printData() { log.trace("Trace Message!"); log.debug("Debug Message!"); log.info("Info Message!"); log.warn("Warn Message!"); log.error("Error Message!"); log.fatal("Fatal Message!"); } }
package x.y.z; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class PrintDataUtil3 { private static final Logger log = LogManager.getLogger(); public static void printData(){ log.trace("Trace Message!"); log.debug("Debug Message!"); log.info("Info Message!"); log.warn("Warn Message!"); log.error("Error Message!"); log.fatal("Fatal Message!"); } }
package log4j_tutorial; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import x.PrintDataUtil1; import x.y.PrintDataUtil2; import x.y.z.PrintDataUtil3; public class HelloWorld { private static final Logger log = LogManager.getLogger(); public static void printData() { log.trace("Trace Message!"); log.debug("Debug Message!"); log.info("Info Message!"); log.warn("Warn Message!"); log.error("Error Message!"); log.fatal("Fatal Message!"); } public static void main(String args[]) throws InterruptedException { printData(); PrintDataUtil1.printData(); PrintDataUtil2.printData(); PrintDataUtil3.printData(); } }
Run HelloWorld
application, you will get following output.
16:19:58.450 [main] DEBUG log4j_tutorial.HelloWorld - Debug Message! 16:19:58.451 [main] INFO log4j_tutorial.HelloWorld - Info Message! 16:19:58.451 [main] WARN log4j_tutorial.HelloWorld - Warn Message! 16:19:58.451 [main] ERROR log4j_tutorial.HelloWorld - Error Message! 16:19:58.451 [main] FATAL log4j_tutorial.HelloWorld - Fatal Message! 16:19:58.451 [main] ERROR x.PrintDataUtil1 - Error Message! 16:19:58.451 [main] FATAL x.PrintDataUtil1 - Fatal Message! 16:19:58.452 [main] ERROR x.y.PrintDataUtil2 - Error Message! 16:19:58.452 [main] FATAL x.y.PrintDataUtil2 - Fatal Message! 16:19:58.452 [main] WARN x.y.z.PrintDataUtil3 - Warn Message! 16:19:58.452 [main] ERROR x.y.z.PrintDataUtil3 - Error Message! 16:19:58.452 [main] FATAL x.y.z.PrintDataUtil3 - Fatal Message!
As you observe
the output, log level error is assigned to x.y. PrintDataUtil2 class.
No comments:
Post a Comment