Appenders are the output destination, or sink, for your logging statements. One or more appenders may be added to a logger programmatically or via a configuration method. They also may be added indirectly through inheritance depending on the Additivity flag.
A PropertyConfigurator file example.
# Define a console appender log4j.appender.C=org.apache.log4j.ConsoleAppender # Define a file appender log4j.appender.R=org.apache.log4j.RollingFileAppender log4j.appender.R.File=example.log # All output to the root logger will go to the file appender log4j.rootLogger=ALL, R # Warn or higher statements will trigger the App logger. They will be written to # the console appender C and the file appender R. log4j.logger.App=WARN, C
What if you had this switched around and only wanted WARN or higher statements to go to the file and you had temporarily enabled the App logger to send ALL log statements? If you simply changed the two logger configuration lines to be log4j.rootLogger=WARN, R and log4j.logger.App=ALL, C you might be surprised to find that all your App log output is also going to the file. There are a couple of reasons for this that you need to get your head around.
Setting the level on a logger only affects if a log statement will emit the log message (become a source.) (it affects if isLEVELEnabled() returns true). If a descendant logger inherits the appender, it may send log messages that don't match this logger's log level.
Loggers don't "write", appenders do. To get the appender to output log messages of a specific level or only messages above a specific level you must use the appender's Filter or Threshold settings (both provided by AppenderSkeleton which most (all?) built-in appenders derive from.
The Additivity flag may be the reason it seems like your logging request should be filtered based on the ancestor's logging levels. The log4cxx and log4j manuals (brief introductions) have a table with examples of what appenders would be output targets (sinks) based on the additivity flag. If you think of the additivity flag is as an inherit from parent flag instead of a way of filtering your output, the tables still make sense and hopefully the notion of filtering appenders based on logger log level disappears.
Using the console and syslog example above, if we didn't want any App and descendant logger messages to go to the console, we could have set the additivity on the MyApp logger to false so that the C appender would not be inherited.
Mailing List Threads
Discussions in the mailing list archive that either deal with the topic directly, or which may have been resolved by having a better understanding of appenders.