In this post, We will learn How to Create a Custom Appender in log4j 2?
In log4j 2, We usually create a plugin for creating a custom appender.
When we annotate our custom Appender class with @Plugin(name = “MyCustomAppender”, category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true) the plugin name becomes the configuration element name.
Below is the complete source code:
pom.xml
We have added log4j2 log4j-api & log4j-core dependency in the dependencies section.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<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.kkjavatutorials.org</groupId> <artifactId>Log4j2CustomAppenderExample</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.17.1</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.17.1</version> </dependency> </dependencies> </project> |
log4j2.xml
In the log4j2.xml file don’t forget to specify the packages attribute here you have to configure your custom appender packages. If you have multiple packages then each package should separate with a semicolon(;)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" packages="com.kkjavatutorials.appender"> <Appenders> <MyCustomAppender name="customAppender"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </MyCustomAppender> </Appenders> <Loggers> <Root level="debug" additivity="false"> <AppenderRef ref="customAppender" /> </Root> </Loggers> </Configuration> |
MyCustomAppender.java
Now we are creating a plugin for a custom appender.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
package com.kkjavatutorials.appender; import java.io.Serializable; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Core; import org.apache.logging.log4j.core.Filter; import org.apache.logging.log4j.core.Layout; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.appender.AbstractAppender; import org.apache.logging.log4j.core.appender.AppenderLoggingException; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginAttribute; import org.apache.logging.log4j.core.config.plugins.PluginElement; import org.apache.logging.log4j.core.config.plugins.PluginFactory; import org.apache.logging.log4j.core.layout.PatternLayout; @Plugin(name = "MyCustomAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true) public class MyCustomAppender extends AbstractAppender { private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private final Lock readLock = readWriteLock.readLock(); protected MyCustomAppender(String name, Filter filter, Layout<? extends Serializable> layout, final boolean ignoreExceptions) { super(name, filter, layout, ignoreExceptions, null); LOGGER.info("MyCustomAppender is instantiated.."); } @PluginFactory public static MyCustomAppender createAppender(@PluginAttribute("name") String name, @PluginElement("Layout") Layout<? extends Serializable> layout, @PluginElement("Filter") final Filter filter, @PluginAttribute("otherAttribute") String otherAttribute) { if (name == null) { LOGGER.error("There is no name provided for MyCustomAppender"); return null; } if (layout == null) { layout = PatternLayout.createDefaultLayout(); } return new MyCustomAppender(name, filter, layout, true); } @Override public void append(LogEvent logEvent) { readLock.lock(); try { final byte[] bytes = getLayout().toByteArray(logEvent); //Printing log into console System.out.print("Custom Log: " + new String(bytes)); } catch (Exception ex) { if (!ignoreExceptions()) { throw new AppenderLoggingException(ex); } } finally { readLock.unlock(); } } } |
ClientTest.java
Now we are going to test our custom appender. For this, I’ve written below test class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.kkjavatutorials.client; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class ClientTest { private static final Logger logger = LogManager.getLogger(ClientTest.class); public static void main(String[] args) { logger.info("This is info message"); logger.warn("This is warn message"); logger.error("This is error message"); } } |
If you run ClientTest.java as java application then you’ll find below output:
Custom Log: 22:36:11.538 [main] INFO com.kkjavatutorials.client.ClientTest – This is info message
Custom Log: 22:36:11.540 [main] WARN com.kkjavatutorials.client.ClientTest – This is warn message
Custom Log: 22:36:11.540 [main] ERROR com.kkjavatutorials.client.ClientTest – This is error message
You May Also Like:
Why Logging?
Log4j 2 simple example
That’s All about How to Create a Custom Appender in log4j 2?
I run that code on IntelliJ this work but when i build jar file this not work, it out problems:
2023-01-26 15:14:53,436 main ERROR Error processing element MyCustomAppender ([Appenders: null]): CLASS_NOT_FOUND
2023-01-26 15:14:53,506 main ERROR Unable to locate appender “customAppender” for logger config “root”