BAEL-1960: Custom appender for log4j

This commit is contained in:
shreyashthakare 2018-07-17 00:32:13 +05:30
parent b44883b364
commit d0c619a0ad
4 changed files with 297 additions and 189 deletions

View File

@ -1,117 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<modelVersion>4.0.0</modelVersion> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>log4j2</artifactId> <modelVersion>4.0.0</modelVersion>
<artifactId>log4j2</artifactId>
<parent> <parent>
<groupId>com.baeldung</groupId> <groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId> <artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
<relativePath>../../</relativePath> <relativePath>../../</relativePath>
</parent> </parent>
<dependencies> <dependencies>
<!-- This is the needed core component. --> <!-- This is the needed core component. -->
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId> <artifactId>log4j-core</artifactId>
<version>${log4j-core.version}</version> <version>${log4j-core.version}</version>
</dependency> </dependency>
<!-- This is used by JSONLayout. --> <!-- This is the needed API component. -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>log4j-api</artifactId>
<version>${jackson.version}</version> <version>${log4j-core.version}</version>
</dependency> </dependency>
<!-- This is used by XMLLayout. -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- This is used by JDBC Appender. --> <!-- This is used by JSONLayout. -->
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>h2</artifactId> <artifactId>jackson-databind</artifactId>
<version>${h2.version}</version> <version>${jackson.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>${commons-dbcp2.version}</version>
</dependency>
<!-- This is used for testing only. --> <!-- This is used by XMLLayout. -->
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>log4j-core</artifactId> <artifactId>jackson-dataformat-xml</artifactId>
<version>${log4j-core.version}</version> <version>${jackson.version}</version>
<type>test-jar</type> </dependency>
<scope>test</scope>
</dependency>
</dependencies>
<build> <!-- This is used by JDBC Appender. -->
<plugins> <dependency>
<plugin> <groupId>com.h2database</groupId>
<groupId>org.apache.maven.plugins</groupId> <artifactId>h2</artifactId>
<artifactId>maven-compiler-plugin</artifactId> <version>${h2.version}</version>
<version>${maven-compiler-plugin.version}</version> </dependency>
<configuration> <dependency>
<proc>none</proc> <groupId>org.apache.commons</groupId>
</configuration> <artifactId>commons-dbcp2</artifactId>
</plugin> <version>${commons-dbcp2.version}</version>
</plugins> </dependency>
</build>
<profiles> <!-- This is used for testing only. -->
<profile> <dependency>
<id>integration</id> <groupId>org.apache.logging.log4j</groupId>
<build> <artifactId>log4j-core</artifactId>
<plugins> <version>${log4j-core.version}</version>
<plugin> <type>test-jar</type>
<groupId>org.apache.maven.plugins</groupId> <scope>test</scope>
<artifactId>maven-surefire-plugin</artifactId> </dependency>
<executions> </dependencies>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*ManualTest.java</exclude>
<exclude>**/*LiveTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
<include>**/*IntTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
<logging.folder.path>${java.io.tmpdir}/${maven.build.timestamp}/logfile.json</logging.folder.path>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties> <build>
<jackson.version>2.9.5</jackson.version> <plugins>
<h2.version>1.4.193</h2.version> <plugin>
<commons-dbcp2.version>2.1.1</commons-dbcp2.version> <groupId>org.apache.maven.plugins</groupId>
<log4j-core.version>2.11.0</log4j-core.version> <artifactId>maven-compiler-plugin</artifactId>
<maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format> <version>${maven-compiler-plugin.version}</version>
</properties> <configuration>
<proc>none</proc>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>integration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*ManualTest.java</exclude>
<exclude>**/*LiveTest.java</exclude>
</excludes>
<includes>
<include>**/*IntegrationTest.java</include>
<include>**/*IntTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
<logging.folder.path>${java.io.tmpdir}/${maven.build.timestamp}/logfile.json</logging.folder.path>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<jackson.version>2.9.5</jackson.version>
<h2.version>1.4.193</h2.version>
<commons-dbcp2.version>2.1.1</commons-dbcp2.version>
<log4j-core.version>2.11.0</log4j-core.version>
<maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
</properties>
</project> </project>

View File

@ -0,0 +1,58 @@
/**
*
*/
package com.baeldung.logging.log4j2.appender;
import java.io.Serializable;
import java.time.Instant;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
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.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 = "MapAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true)
public class MapAppender extends AbstractAppender {
private ConcurrentMap<String, LogEvent> eventMap = new ConcurrentHashMap<>();
protected MapAppender(String name, Filter filter, Layout<? extends Serializable> layout) {
super(name, filter, layout);
}
@PluginFactory
public static MapAppender createAppender(@PluginAttribute("name") String name, @PluginElement("Layout") Layout<? extends Serializable> layout, @PluginElement("Filter") final Filter filter) {
if (name == null) {
LOGGER.error("No name provided for MapAppender");
return null;
}
if (layout == null) {
layout = PatternLayout.createDefaultLayout();
}
return new MapAppender(name, filter, layout);
}
@Override
public void append(LogEvent event) {
eventMap.put(Instant.now()
.toString(), event);
}
public ConcurrentMap<String, LogEvent> getEventMap() {
return eventMap;
}
public void setEventMap(ConcurrentMap<String, LogEvent> eventMap) {
this.eventMap = eventMap;
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.logging.log4j2.appender;
import static org.junit.Assert.assertEquals;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class MapAppenderIntegrationTest {
private Logger logger;
@Before
public void setup() {
logger = LogManager.getLogger(MapAppenderIntegrationTest.class);
}
@Test
public void whenLoggerEmitsLoggingEvent_thenAppenderReceivesEvent() throws Exception {
logger.info("Test from {}", this.getClass()
.getSimpleName());
LoggerContext context = LoggerContext.getContext(false);
Configuration config = context.getConfiguration();
MapAppender appender = config.getAppender("MapAppender");
assertEquals(appender.getEventMap()
.size(), 1);
}
}

View File

@ -1,87 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns:xi="http://www.w3.org/2001/XInclude" <Configuration xmlns:xi="http://www.w3.org/2001/XInclude"
status="WARN"> packages="com.baeldung" status="WARN">
<Appenders> <Appenders>
<xi:include <xi:include
href="log4j2-includes/console-appender_pattern-layout_colored.xml" /> href="log4j2-includes/console-appender_pattern-layout_colored.xml" />
<Console name="ConsoleAppender" target="SYSTEM_OUT"> <Console name="ConsoleAppender" target="SYSTEM_OUT">
<PatternLayout <PatternLayout
pattern="%d [%t] %-5level %logger{36} - %msg%n%throwable" /> pattern="%d [%t] %-5level %logger{36} - %msg%n%throwable" />
</Console> </Console>
<Console name="ConsoleRedAppender" target="SYSTEM_OUT"> <Console name="ConsoleRedAppender" target="SYSTEM_OUT">
<PatternLayout pattern="%style{%message}{red}%n" /> <PatternLayout pattern="%style{%message}{red}%n" />
<MarkerFilter marker="CONN_TRACE" /> <MarkerFilter marker="CONN_TRACE" />
</Console> </Console>
<Console name="ConsoleGreenAppender" target="SYSTEM_OUT"> <Console name="ConsoleGreenAppender" target="SYSTEM_OUT">
<PatternLayout <PatternLayout
pattern="%style{userId=%X{userId}:}{white} %style{%message}{green}%n" /> pattern="%style{userId=%X{userId}:}{white} %style{%message}{green}%n" />
</Console> </Console>
<Console name="ConsoleJSONAppender" target="SYSTEM_OUT"> <Console name="ConsoleJSONAppender" target="SYSTEM_OUT">
<JsonLayout complete="false" compact="false"> <JsonLayout complete="false" compact="false">
<KeyValuePair key="myCustomField" value="myCustomValue" /> <KeyValuePair key="myCustomField" value="myCustomValue" />
</JsonLayout> </JsonLayout>
</Console> </Console>
<File name="JSONLogfileAppender" fileName="${sys:logging.folder.path}"> <File name="JSONLogfileAppender"
<JSONLayout compact="true" eventEol="true" /> fileName="${sys:logging.folder.path}">
<BurstFilter level="INFO" rate="2" maxBurst="10" /> <JSONLayout compact="true" eventEol="true" />
</File> <BurstFilter level="INFO" rate="2" maxBurst="10" />
<Async name="AsyncAppender" bufferSize="80"> </File>
<AppenderRef ref="JSONLogfileAppender" /> <Async name="AsyncAppender" bufferSize="80">
</Async> <AppenderRef ref="JSONLogfileAppender" />
<!-- <Syslog name="Syslog" format="RFC5424" host="localhost" port="514" </Async>
protocol="TCP" facility="local3" connectTimeoutMillis="10000" reconnectionDelayMillis="5000" <!-- <Syslog name="Syslog" format="RFC5424" host="localhost" port="514"
mdcId="mdc" includeMDC="true" /> <Failover name="FailoverAppender" primary="Syslog"> protocol="TCP" facility="local3" connectTimeoutMillis="10000" reconnectionDelayMillis="5000"
<Failovers> <AppenderRef ref="ConsoleAppender" /> </Failovers> </Failover> --> mdcId="mdc" includeMDC="true" /> <Failover name="FailoverAppender" primary="Syslog">
<JDBC name="JDBCAppender" tableName="logs"> <Failovers> <AppenderRef ref="ConsoleAppender" /> </Failovers> </Failover> -->
<ConnectionFactory <JDBC name="JDBCAppender" tableName="logs">
class="com.baeldung.logging.log4j2.tests.jdbc.ConnectionFactory" <ConnectionFactory
method="getConnection" /> class="com.baeldung.logging.log4j2.tests.jdbc.ConnectionFactory"
<Column name="when" isEventTimestamp="true" /> method="getConnection" />
<Column name="logger" pattern="%logger" /> <Column name="when" isEventTimestamp="true" />
<Column name="level" pattern="%level" /> <Column name="logger" pattern="%logger" />
<Column name="message" pattern="%message" /> <Column name="level" pattern="%level" />
<Column name="throwable" pattern="%ex{full}" /> <Column name="message" pattern="%message" />
</JDBC> <Column name="throwable" pattern="%ex{full}" />
<RollingFile name="XMLRollingfileAppender" fileName="target/logfile.xml" </JDBC>
filePattern="target/logfile-%d{yyyy-MM-dd}-%i.log.gz"> <RollingFile name="XMLRollingfileAppender"
<XMLLayout /> fileName="target/logfile.xml"
<Policies> filePattern="target/logfile-%d{yyyy-MM-dd}-%i.log.gz">
<SizeBasedTriggeringPolicy <XMLLayout />
size="17 kB" /> <Policies>
</Policies> <SizeBasedTriggeringPolicy size="17 kB" />
</RollingFile> </Policies>
</Appenders> </RollingFile>
<Loggers> <MapAppender name="MapAppender">
<Logger name="CONSOLE_PATTERN_APPENDER_MARKER" level="TRACE" <PatternLayout
additivity="false"> pattern=" Date: %d | level:%level | class name:%logger | method name:%M() | line number:%L | Location: %l | message:%m%n" />
<AppenderRef ref="ConsoleRedAppender" /> </MapAppender>
</Logger> </Appenders>
<Logger name="CONSOLE_PATTERN_APPENDER_THREAD_CONTEXT" <Loggers>
level="INFO" additivity="false"> <Logger name="CONSOLE_PATTERN_APPENDER_MARKER" level="TRACE"
<AppenderRef ref="ConsoleGreenAppender" /> additivity="false">
<ThreadContextMapFilter> <AppenderRef ref="ConsoleRedAppender" />
<KeyValuePair key="userId" value="1000" /> </Logger>
</ThreadContextMapFilter> <Logger name="CONSOLE_PATTERN_APPENDER_THREAD_CONTEXT"
</Logger> level="INFO" additivity="false">
<Logger name="ASYNC_JSON_FILE_APPENDER" level="INFO" <AppenderRef ref="ConsoleGreenAppender" />
additivity="false"> <ThreadContextMapFilter>
<AppenderRef ref="AsyncAppender" /> <KeyValuePair key="userId" value="1000" />
</Logger> </ThreadContextMapFilter>
<!-- <Logger name="FAIL_OVER_SYSLOG_APPENDER" level="INFO" additivity="false"> </Logger>
<AppenderRef ref="FailoverAppender" /> </Logger> --> <Logger name="ASYNC_JSON_FILE_APPENDER" level="INFO"
<Logger name="JDBC_APPENDER" level="INFO" additivity="false"> additivity="false">
<AppenderRef ref="JDBCAppender" /> <AppenderRef ref="AsyncAppender" />
</Logger> </Logger>
<Logger name="XML_ROLLING_FILE_APPENDER" level="INFO" <!-- <Logger name="FAIL_OVER_SYSLOG_APPENDER" level="INFO" additivity="false">
additivity="false"> <AppenderRef ref="FailoverAppender" /> </Logger> -->
<AppenderRef ref="XMLRollingfileAppender" /> <Logger name="JDBC_APPENDER" level="INFO" additivity="false">
</Logger> <AppenderRef ref="JDBCAppender" />
<Logger name="CONSOLE_JSON_APPENDER" level="TRACE" </Logger>
additivity="false"> <Logger name="XML_ROLLING_FILE_APPENDER" level="INFO"
<AppenderRef ref="ConsoleJSONAppender" /> additivity="false">
</Logger> <AppenderRef ref="XMLRollingfileAppender" />
<Root level="DEBUG"> </Logger>
<AppenderRef ref="ConsoleAppender" /> <Logger name="CONSOLE_JSON_APPENDER" level="TRACE"
</Root> additivity="false">
</Loggers> <AppenderRef ref="ConsoleJSONAppender" />
</Logger>
<Root level="DEBUG">
<AppenderRef ref="ConsoleAppender" />
<AppenderRef ref="MapAppender" />
</Root>
</Loggers>
</Configuration> </Configuration>