SLF4J markers example
In this example, we shall show you how to use Markers with SLF4J.
SLF4J is a simple facade over various logging frameworks. It gives abstraction and therefore makes it easier to change logging implementations later on in a software project. It is a very stable library and is actively used by various open source software like Apache Camel, ActiveMQ, Solr and EhCache etc.
For this example, we will be using logback as logger with SLF4J. Logback was conceived and created as a successor to Log4J. Logback supports markers for the logging calls. These Markers allow association of tags with log statements. These tags enable various appenders to take decision on basis of their presence and absence. For the purposes of this example, we will be associating a ‘confidential’ tag which filter certain log statements on basis of what they are marked with.
For this example we will be using Logback 1.0.1 and SLF4J 1.6.4. The example is compilable on Java 5 and above.
1. Creating Hello World Maven Project
Initially, we will be creating a bare minimum maven project. This will be a command line Hello World application.Later on we will be integrating SLF4J in it.Once you have maven installed and running on your machine, issue following command from command line.
mvn archetype:generate -DgroupId=com.javacodegeeks -DartifactId=slf4jmarker -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Maven will be downloading all dependencies from the default Maven Central repository and creating a bare minimum hello world project for us.
Once the above command have completed, Maven would have generated a really small pom.xml file and src folder for us. There is a single class called ‘App.java’ in the src. If you compile and run application at this point. You will get a command line Hello World message.
2. Integrating SLF4J and Logback
To integrating SLF4J and Logback, we need to make following changes to pom.xml
-
Adding jars file to classpath.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javacodegeeks</groupId> <artifactId>slf4jmarker</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>slf4jmarker</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <slf4j.version>1.6.4</slf4j.version> <logback.version>1.0.1</logback.version> </properties> <dependencies> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>${logback.version}</version> </dependency> </dependencies> </project>
- Adding maven exec plugin. This is a helpful plugin for console based applications. Using this plugin we will be invoking our Java application main method from command line. Here are the contents of final pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javacodegeeks</groupId> <artifactId>slf4jmarker</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>slf4jmarker</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <slf4j.version>1.6.4</slf4j.version> <logback.version>1.0.1</logback.version> </properties> <dependencies> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>${logback.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <executions> <execution> <goals> <goal>java</goal> </goals> </execution> </executions> <configuration> <mainClass>com.javacodegeeks.slf4jmarker.App</mainClass> </configuration> </plugin> </plugins> </build> </project>
-
Creating logback.xml file in resource folder.
Create a resource folder at /src/main/resources and add following logback.xml file to it.
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
We are using ConsoleAppender for this example. So all logging will be directed to console output.Next we are specifying the pattern of logged statements. Just like Log4J, we can use various pattern in the section to format and output log statements.
-
Using SLF4J and in our hello world application.
We will be using Slf4J for logging to console.
package com.javacodegeeks.slf4jmarker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.Marker; import org.slf4j.MarkerFactory; /** * Hello world! * */ public class App { private static final Logger logger = LoggerFactory.getLogger(App.class); public static void main( String[] args ) { String confidentialMarkerText = "CONFIDENTIAL"; Marker confidentialMarker = MarkerFactory.getMarker(confidentialMarkerText); logger.debug("Hello world from slf4j"); logger.debug("This logger supports confidentail messages...."); logger.debug(confidentialMarker,"This is a confidential message...."); logger.debug("Just logged a confidential message"); } }
In this step, we are doing debug level logging. In third statement, we are using a marker ‘CONFIDENTIAL’.Therefore third statement will be tagged by logback as CONFIDENTIAL. We will be using this tag in next step to filter out this particular log.
cd slf4jmarker mvn clean install mvn exec:java 23:05:47.022 [main] DEBUG javacodegeeks.slf4jmarker.App - Hello world from slf4j 23:05:47.027 [main] DEBUG javacodegeeks.slf4jmarker.App - This logger supports confidentail messages.... 23:05:47.027 [main] DEBUG javacodegeeks.slf4jmarker.App - This is a confidential message.... 23:05:47.027 [main] DEBUG javacodegeeks.slf4jmarker.App - Just logged a confidential message
-
Filtering Confidential logs.
We will be using Logback’s Turbo Filter to filter out tagged messages. Configuring this filter is very simple and can be done via xml file itself.Add TurboFilter tag to logback.xml file created in earlier step. Final file would look like below
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> <Name>CONFIDENTIAL_FILTER</Name> <Marker>CONFIDENTIAL</Marker> <OnMatch>DENY</OnMatch> </turboFilter> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>
Building the project
mvn clean install mvn exec:java [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building slf4jmarker 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) > validate @ slf4jmarker > >> [INFO] [INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) < validate @ slf4jmarker < << [INFO] [INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ slf4jmarker --- 23:20:37.223 [com.javacodegeeks.slf4jmarker.App.main()] DEBUG com.javacodegeeks. slf4jmarker.App - Hello world from slf4j 23:20:37.228 [com.javacodegeeks.slf4jatmarker.App.main()] DEBUG com.javacodegeeks. slf4jmarker.App - This logger supports confidentail messages.... 23:20:37.228 [com.javacodegeeks.slf4jmarker.App.main()] DEBUG com.javacodegeeks. slf4jmarker.App - Just logged a confidential message [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 0.904 s
As you see, third statement we logged from our code has been filtered out.
5. Download source code
You can download the full source code of this example here: Slf4JMarker Example
Can I use a marker with custom appender? If yes, can you please provide an example.
Thanks a lot!!!!