From: <log...@pe...> - 2003-01-09 10:22:54
|
Welcome to the Log::Log4perl recipe of the week. Today: ============================================================ Log::Log4perl Recipe of the Week (#11): I keep getting duplicate log messages! What's wrong? ============================================================ Having several settings for related categories in the Log4perl configuration file sometimes leads to a phenomenon called "message duplication". It can be very confusing at first, but if thought through properly, it turns out that Log4perl behaves as advertised. But, don't despair, of course there's a number of ways to avoid message duplication in your logs. Here's a sample Log4perl configuration file that produces the phenomenon: log4perl.logger.Cat = ERROR, Screen log4perl.logger.Cat.Subcat = WARN, Screen log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout It defines two loggers, one for category "Cat" and one for "Cat::Subcat", which is obviously a subcategory of "Cat". The parent logger has a priority setting of ERROR, the child is set to the lower "WARN" level. Now imagine the following code in your program: my $logger = get_logger("Cat.Subcat"); $logger->warn("Warning!"); What do you think will happen? An unexperienced Log4perl user might think: "Well, the message is being sent with level WARN, so the "Cat::Subcat" logger will accept it and forward it to the attached "Screen" appender. Then, the message will percolate up the logger hierarchy, find the "Cat" logger, which will suppress the message because of its ERROR setting." But, perhaps surprisingly, what you'll get with the code snippet above is not one but two log messages written to the screen: WARN - Warning! WARN - Warning! What happened? The culprit is that once the logger "Cat::Subcat" decides to fire, it will forward the message *unconditionally* to all directly or indirectly attached appenders. The "Cat" logger will never be asked if it wants the message or not -- the message will just be pushed through to the appender attached to "Cat". One way to prevent the message from bubbling up the logger hierarchy is to set the "additivity" flag of the subordinate logger to 0: log4perl.logger.Cat = ERROR, Screen log4perl.logger.Cat.Subcat = WARN, Screen log4perl.additivity.Cat.Subcat = 0 log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout The message will now be accepted by the "Cat::Subcat" logger, forwarded to its appender, but then "Cat::Subcat" will suppress any further action. While this setting avoids duplicate messages as seen before, it is often not the desired behaviour. Messages percolating up the hierarchy are a useful Log4perl feature. If you're defining *different* appenders for the two loggers, one other option is to define an appender threshold for the higher-level appender. Typically it is set to be equal to the logger's level setting: log4perl.logger.Cat = ERROR, Screen1 log4perl.logger.Cat.Subcat = WARN, Screen2 log4perl.appender.Screen1 = Log::Dispatch::Screen log4perl.appender.Screen1.layout = SimpleLayout log4perl.appender.Screen1.Threshold = ERROR log4perl.appender.Screen2 = Log::Dispatch::Screen log4perl.appender.Screen2.layout = SimpleLayout Since the "Screen1" appender now blocks every message with a priority less than ERROR, even if the logger in charge lets it through, the message percolating up the hierarchy is being blocked at the last minute and *not* appended to "Screen1". So far, we've been operating well within the boundaries of the Log4j standard, which Log4perl adheres to. However, if you would really, really like to use a single appender and keep the message percolation intact without having to deal with message duplication, there's a non-standard solution for you: log4perl.logger.Cat = ERROR, Screen log4perl.logger.Cat.Subcat = WARN, Screen log4perl.appender.Screen = Log::Dispatch::Screen log4perl.appender.Screen.layout = SimpleLayout log4perl.oneMessagePerAppender = 1 The "oneMessagePerAppender" flag will suppress duplicate messages to the same appender. Again, that's non-standard. But way cool :). Have fun! Until next week. -- Mike ################################### # Mike Schilli # # log...@pe... # # http://perlmeister.com # # http://log4perl.sourceforge.net # ################################### |