2

I'd like to use log4jdbc-log4j2 to log JDBC calls. The documentation providers information how to use it with Log4j2 markers.

<logger name="log4jdbc.log4j2" level="info" additivity="false">
  <MarkerFilter marker="LOG4JDBC_OTHER" onMatch="DENY" onMismatch="NEUTRAL"/>
  <appender-ref ref="Console"/>
</logger>

Is there any way how to rewrite the above code to work with Logback?

UPDATE: I already tried to put a TurboFilter outside the logger directly inside the configuration element. It however doesn't change the log output.

<turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
    <Name>LOG4JDBC_LOGBACK_FILTER</Name>
    <Marker>LOG4JDBC_OTHER</Marker>
    <OnMatch>DENY</OnMatch>
</turboFilter>
devmake
  • 5,222
  • 2
  • 28
  • 26

4 Answers4

2

Markers in log4j2 work this way:

package org.so.log4j2.test;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;

public class Log4j2Test {
    public static void main(String[] args)
    {
        Logger logger = LogManager.getLogger("Test");
        Marker LOG4JDBC_OTHER = MarkerManager.getMarker("LOG4JDBC_OTHER");

        logger.info("Line to show.");
        logger.info(LOG4JDBC_OTHER, "Line to hide");
    }
}

With below log4j2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <MarkerFilter marker="LOG4JDBC_OTHER" onMatch="DENY" onMismatch="NEUTRAL"/>
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="error">
            <AppenderRef ref="Console"/>
        </Root>
        <Logger name="Test" level="info" additivity="false">
            <AppenderRef ref="Console"/>
        </Logger>
    </Loggers>
</Configuration>

Output:

12:37:22.416 [main] INFO  Test - Line to show.

Markers in Logback work this way:

package org.so.logback.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;

public class LogbackTest {
    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger("Test");
        Marker LOG4JDBC_OTHER = MarkerFactory.getMarker("LOG4JDBC_OTHER");
        logger.info("Line to show");
        logger.info(LOG4JDBC_OTHER, "Line to hide");
    }
}

With this logback.xml

<?xml version="1.0" ?>
<configuration>
    <property name="log.folder" value="./log"/>
    <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
        <Marker>LOG4JDBC_OTHER</Marker>
        <OnMatch>DENY</OnMatch>
        <OnMismatch>NEUTRAL</OnMismatch>
    </turboFilter>

  <appender class="ch.qos.logback.core.ConsoleAppender" name="CONSOLE">
    <encoder>
      <pattern>[%p] [%thread] %logger - %msg%n</pattern>
    </encoder>
  </appender>

  <root>
    <level value="INFO"/>
    <appender-ref ref="CONSOLE"/>
  </root>

  <logger name="Test" additivity="false">
    <level value="INFO" />
    <appender-ref ref="CONSOLE"/>
  </logger>     
</configuration>

Output:

[INFO] [main] Test - Line to show

Hope it helps.

P.s. maybe additivity flag again?..

Andrey Lebedenko
  • 1,850
  • 17
  • 24
  • I'm able to get an example with my own ```MarkerFactory.getMarker``` working as you have it in #2. However it doesn't work with the log4jdbc-log4j2 because it uses org.apache.logging.log4j.Logger (example #1) and I use logback.xml (example #2). – devmake May 07 '16 at 16:27
  • What do you want to achieve in the end? Single XML config file combining both -- logback and log4jdbc-log4j2 settings? – Andrey Lebedenko May 07 '16 at 20:04
  • I'm trying to configure this with single xml config file however don't mind number of files. I want output to console and one file for both my app and the library. – devmake May 08 '16 at 05:53
  • Can you switch log4jdbc to slf4j ? Quote from project: " The name of this project is slightly misleading, as it also supports SLF4J, which implicitly supports every major logging framework." – Andrey Lebedenko May 09 '16 at 07:45
  • I'm able to get logging work as needed with slf4j as described in my [answer](http://stackoverflow.com/a/37087547/398861). I just cannot make it work with the Markers. – devmake May 09 '16 at 11:31
1

I tried to put log4jdbc.dump.sql.select=false in log4jdbc.log4j2.properties, and it filtered out select statements. You can replace 'select' with other key words like 'create', 'update'...

If you want to have more control on the logging, you can extend Slf4jSpyLogDelegator, point log4jdbc.spylogdelegator.name to your new class and override methods as needed.

ss33
  • 11
  • 1
0

I believe what you are looking for is called TurboFilters in Logback. See http://logback.qos.ch/manual/filters.html

Update: if I understand your question correctly, you have an application that uses the Log4j 2 API (or one of its dependencies does). You want to use Logback as the logger implementation. Now, the question is, how to route calls from the Log4j 2 API to the Logback implementation, ideally translating Log4j 2 Markers into SLF4J Markers?

Perhaps all you need to do is add the Log4j to SLF4J adapter (log4j-to-slf4j-2.x.jar).

Be careful:

Use of the SLF4J adapter (log4j-to-slf4j-2.x.jar) together with the SLF4J bridge (log4j-slf4j-impl-2.x.jar) should never be attempted as it will cause events to endlessly be routed between SLF4J and Log4j 2.

Remko Popma
  • 35,130
  • 11
  • 92
  • 114
  • Thanks for prompt answer. I already tried it before posting my question and it didn't work for me. I've updated my question. I'm not sure if I can simply use the log4j2 marker name that the library uses. – devmake May 07 '16 at 10:24
  • Your understanding is correct. The dependency ```log4jdbc-log4j2``` uses Log4j 2 API and I use ```spring-boot-starter``` with ```logback```. I tried to add dependency to ```org.apache.logging.log4j:log4j-to-slf4j:2.5``` but it doesn't filter anything, I still see all the messages in console. – devmake May 07 '16 at 16:42
  • That's strange. Looking at the code, log4j-to-slf4j does try to convert the Markers: http://logging.apache.org/log4j/2.x/log4j-to-slf4j/xref/org/apache/logging/slf4j/SLF4JLogger.html#L92 – Remko Popma May 07 '16 at 16:51
  • Perhaps you still see log4j2 output in the console because the log4j2 implementation jar (log4j-core) is still in the classpath? (You only need log4j-api and log4j-to-slf4j) – Remko Popma May 08 '16 at 08:15
  • I don't have log4j-core among dependencies. I have ```logback-core``` and ```logback-classic```. Spring Boot adds ```org.slf4j:log4j-over-slf4j:1.7.16```` which redirects log4j calls to slf4j. I also added ```org.slf4j:log4j-over-slf4j:2.5``` as you suggested. In additional to that I also see following dependencies ```org.apache.logging.log4j:log4j-api:2.4.1```, ```org.slf4j:jcl-over-slf4j:1.7.16```, ```org.slf4j:jul-to-slf4j:1.7.16```, ```org.slf4j:slf4j-api:1.7.16```. – devmake May 09 '16 at 04:29
  • What level are the messages you're seeing? ERROR? – Remko Popma May 09 '16 at 05:02
  • I see INFO level messages. – devmake May 09 '16 at 11:32
0

This works for me in logback.xml. This doesn't use markers at all but does what I need i.e. filters only sql statements (with timing).

<logger name="jdbc.sqlonly" level="error" additivity="false" ><appender-ref ref="CONSOLE"/></logger>
<logger name="jdbc.sqltiming" level="info" additivity="false" ><appender-ref ref="CONSOLE"/></logger>
<logger name="jdbc.audit" level="error" additivity="false" ><appender-ref ref="CONSOLE"/></logger>
<logger name="jdbc.resultset" level="error" additivity="false" ><appender-ref ref="CONSOLE"/></logger>
<logger name="jdbc.resultsettable" level="info" additivity="false" ><appender-ref ref="CONSOLE"/></logger>
<logger name="jdbc.connection" level="error" additivity="false" ><appender-ref ref="CONSOLE"/></logger>

These 6 loggers are described in log4jdbc-log4j2 documentation.

devmake
  • 5,222
  • 2
  • 28
  • 26