Forcing logger/appender to output line logged at lower than its current level

enterprise-developmentlogging

Consider the following scenario:

I am writing a Dispatcher Servlet that delegates processing to various handlers depending on the request URL; the handler objects having previously registered themselves for URL patterns, pretty much as Servlets register themselves in web.xml.

When a Handler registers or unregisters itself for a pattern, I want to log a line that includes the action and pattern; and also the current mappings, so that when a subsequent request processing logs a warning that a request was not processed I can go back in the logs and find out the mappings.

The question is how to ensure that lines logged by registerUrlPattern/unregisterUrlPattern actually appear in the log file:

  • It seems to me that these methods should log the mapping changes at INFO level, since it is additional INFO being logged. But the logger's level is WARN so that will not work. The logger get many other messages at INFO level so it is not possible to change its level to INFO in production, except for troubleshooting.

  • I could log it at WARN level, but qa/usability/customer does not like such warnings to appear.

I can think of the following alternatives:

  • Change the Logger's level to INFO when logging these lines, possibly by adding a forceInfo method in my Logger (which wraps a standard log4j type logger)

  • Use a different Logger for these methods and set its level to INFO

  • Log at warning level but change the language to indicate that it is not something to be worried about

Best Answer

So, you need different treshold within the same class. I think you use a different logger corresponding to a specific name. You can thus set the log level to INFO for this specific Logger in DispatchServlet class.

For me, the benefits would be:

  • the possibility to specificly reduce the treshold to INFO as you required (the goal).
  • if one day you realize that your specific logs become too verbose and finally useless because the functionnality is 100% stable and doesn't cause any issue, you still can reduce the treshold by configuration and without impacting the rest of the logs. Logging in WARNING level or do something based on forcedLog would imply you to modify the sources for such a purpose.

The only CON I see is that it might be "surprising" but a correct documentation solves everything.

For example in your log4j.xml file, you could have:

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <!-- general application log -->
    <appender name="MyLogFileAppender" class="org.apache.log4j.FileAppender">
        <param name="File" value="mylog.log" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{yyyy MM dd - HH:mm:ss,SSS} %-5p %t [%-40.40c] %x - %m%n"/>
        </layout>
    </appender>
    <logger name="DispatchServletSpecific">
        <level value="INFO" />
        <appender-ref ref="MyLogFileAppender" />
    </logger>
    <root>
         <level value="WARNING" />
         <appender-ref ref="MyLogFileAppender" />
    </root>
</log4j:configuration>

And in the Java code you create a specific Logger

Logger specificLogger = Logger.getLogger("DispatchServletSpecific");

This way the log treshold should be set to INFO while the rest of your app should be log only WARNING logs. Hope it helps.