Wednesday 15 January 2014

Log4j logger hierarchies and Java nested classes

According to this LOG4J article, 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. So beware of nested classes!

  <logger name="com.my_group_id.MyClassDontLogDebug">
    <level value="error" />
  </logger>

  <logger name="com.my_group_id">
    <level value="debug" />
  </logger>

Any DEBUG-level log statements from the MyClassDontLogDebug will be ignored, as expected. However, any DEBUG-level log statements from any loggers obtained from classes nested inside MyClassDontLogDebug will be appearing in your logs. And that despite the fact that nested classes are members of MyClassDontLogDebug! The problem is that the class name will include a dollar sign "$" to separate the nested class name from its nesting class. For example, when com.my_group_id.MyClassDontLogDebug$MyNestedClass acquires a logger in the usual fashion - LogFactory.getLog(getClass()); - the logger will not inherit logging level from MyClassDontLogDebug, as it's not its ancestor. It will become a child of the com.my_group_id parent logger, and inherit the DEBUG logging level, despite our efforts to stop logging at DEBUG level from the MyClassDontLogDebug class.

Re-read the definition carefully again: 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.

Take the name of our logger "com.my_group_id.MyClassDontLogDebug", append a dot, "com.my_group_id.MyClassDontLogDebug." and see if it is a prefix of "com.my_group_id.MyClassDontLogDebug$MyNestedClass" and behold! it's not. There's the dollar sign. Caught me out. Don't let it catch YOU out.

1 comment: