Log4j 1.2 multi-level filtering

2019-08-28 14:54发布

问题:

BTW, this is log4j 1.2.

My application needs to log every time we create an alert, and we want to do it at INFO level. Our root logger has priority level set to INFO. So far so good. We have added several appenders for specialized needs, including a stadard CONSOLE appender and a server.log appender (and others). I have configured the root logger with the console and server.log appenders. Also fine up to this point.

   <root>
      <priority value="INFO"/>
      <appender-ref ref="CONSOLE"/>
      <appender-ref ref="server"/>
      <appender-ref ref="logfileForErrors"/>
   </root>

Now I need a new appender that gets all of ERROR/WARNING/FATAL that normally goes to server.log, but also INFOs for a specific class. I started with an appender with threshold of INFO so I could accept the alarm INFO logs:

<appender name="logfileForAlarmsAndOther" class="org.apache.log4j.RollingFileAppender">
    <errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
    <param name="file" value="${biomerieux.data}/simon/logs/vilink.log" />
    <param name="append" value="true" />
    <param name="threshold" value="INFO" />
    <param name="maxBackupIndex" value="1" />
</appender>

Then I defined a logger for my class:

    <logger name="my.root.path.service.alert.AlertService" additivity="false">
        <level value="info" />
        <appender-ref ref="logfileForAlarmsAndOther"/>
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="server"/>
    </logger>

So I successfully get my alert logs in all of the listed logs (a lot of work for nothing since the root was already at INFO). But what I really want is to now get INFOs at my new appender only if they are from the one specific class.

I am not sure I have described this well, and I am not log4j savvy, so please ask for clarifications if needed. The conundrum has to do with limiting my new appender to WARNING and greater, except I also want INFOs from a specific class. And these INFOs for this class should also go to every appender that parent loggeres would normally log INFOs. I may be confused, but it seems like a custom filter is all I can think of to work in log4j 1.2.

回答1:

The way I solved this was to eliminate the extra child logger for the specific class and handle instead with a series of filters within the appender:

<appender name="logfileForAlarmsAndOther" class="org.apache.log4j.RollingFileAppender">
    <errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
    <param name="file" value="${biomerieux.data}/simon/logs/vilink.log" />
    <param name="append" value="true" />
    <param name="threshold" value="INFO" />
    <param name="maxBackupIndex" value="1" />
    <filter class="org.apache.log4j.varia.StringMatchFilter">
        <param name="StringToMatch" value="MyStringToMatch" />
        <param name="AcceptOnMatch" value="true" />
    </filter>
    <filter class="org.apache.log4j.varia.LevelRangeFilter">
        <param name="LevelMin" value="WARN" />
    </filter>
</appender>

So the global threshold is INFO, and it immediately accepts INFOs that match the String, but anything else is subject to the second filter which limits remaining messages to WARN or above.

The downside of this is that I had to introduce a unique searchable String in the log message.



标签: java log4j