Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logback logger logging twice

I would like to use slf4j+logback for two purposes in my application - log and audit.

For logging, I log the normal way:

static final Logger logger = LoggerFactory.getLogger(Main.class);
logger.debug("-> main()");

For Audit, I create a special named logger and log to it:

static final Logger logger = LoggerFactory.getLogger("AUDIT_LOGGER");
Object[] params =
    { new Integer(1) /* TenantID */, new Integer(10) /* UserID */, msg};
logger.info("{}|{}|{}", params);

logback configuration:

<logger name="AUDIT_LOGGER" level="info">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS}|%msg%n
            </pattern>
        </encoder>
    </appender>
</logger>

<root level="all">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
            </pattern>
        </encoder>
    </appender>
</root>

Problem: Messages logged through audit logger appear twice - once under the AUDIT_LOGGER and once under the root logger.

14:41:57.975 [main] DEBUG com.gammay.example.Main - -> main()

14:41:57.978|1|10|welcome to main

14:41:57.978 [main] INFO AUDIT_LOGGER - 1|10|welcome to main

How can I make sure audit messages appear only once under the audit logger?

like image 637
gammay Avatar asked Jun 12 '14 09:06

gammay


2 Answers

Change audit logger definition as shown below. Note additivity="false" flag in the logger definition.

<logger name="AUDIT_LOGGER" level="info" additivity="false">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS}|%msg%n
            </pattern>
        </encoder>
    </appender>
</logger>

That will avoid logging this again in root logger. Read logback configuration documentation for more information.

like image 171
RaviH Avatar answered Nov 19 '22 03:11

RaviH


I ran into the same problem, but I think the correct solution is different from what's proposed here through additivity. The attached diagram tries to visualize the two approaches that do not result in duplicate logs:

  1. For every <logger> you also add an <appender> and disable additivity. This is what's shown in the diagram under "Without additivity". The result is that each individual logger passes the logs directly to the appender and does not pass them to the ROOT logger.

  2. You specify the <logger>s and their log levels, but omit appender-refs for all but the ROOT logger, and leave additivty on. This is shown under "With addivity". The result is that a matching log from the com.foo logger is passed to the ROOT logger and uses the <appender> specified there. Note that, at that point, the log level filtering of the ROOT logger does not apply anymore. This means that even though com.foo is of log level INFO and the ROOT logger specifies ERROR, the log is still shown because it was already matched by com.foo.

Visualization of the data flow from logger to appender in the two scenarios described above

like image 28
fresskoma Avatar answered Nov 19 '22 02:11

fresskoma