Merge branch 'master' into BAEL-16646-2

This commit is contained in:
Alessio Stalla
2019-10-24 13:20:08 +02:00
parent db85c8f275
commit c499158763
20506 changed files with 1643665 additions and 0 deletions
View File
+7
View File
@@ -0,0 +1,7 @@
### Relevant articles
- [Intro to Log4j2 Appenders, Layouts and Filters](http://www.baeldung.com/log4j2-appenders-layouts-filters)
- [Log4j 2 and Lambda Expressions](http://www.baeldung.com/log4j-2-lazy-logging)
- [Programmatic Configuration with Log4j 2](http://www.baeldung.com/log4j2-programmatic-config)
- [Creating a Custom Log4j2 Appender](https://www.baeldung.com/log4j2-custom-appender)
- [Get Log Output in JSON](http://www.baeldung.com/java-log-json-output)
+123
View File
@@ -0,0 +1,123 @@
<?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"
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>
<artifactId>log4j2</artifactId>
<name>log4j2</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<dependencies>
<!-- This is the needed core component. -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j-core.version}</version>
</dependency>
<!-- This is the needed API component. -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j-core.version}</version>
</dependency>
<!-- This is used by JSONLayout. -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</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. -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>${commons-dbcp2.version}</version>
</dependency>
<!-- This is used for testing only. -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j-core.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<proc>none</proc>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>integration-lite-first</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>
<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>
@@ -0,0 +1,18 @@
package com.baeldung.logging.log4j2;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
public class Log4j2ComparisonSysout {
public static void main(String[] args) throws FileNotFoundException {
PrintStream outStream = new PrintStream(new File("outFile.txt"));
System.setOut(outStream);
System.out.println("This is a baeldung article");
PrintStream errStream = new PrintStream(new File("errFile.txt"));
System.setErr(errStream);
System.err.println("This is a baeldung article error");
}
}
@@ -0,0 +1,19 @@
package com.baeldung.logging.log4j2;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
public class Log4j2Example {
private static final Logger logger = LogManager.getLogger(Log4j2Example.class);
public static void main(String[] args) {
logger.debug("Debug log message");
logger.info("Info log message");
logger.error("Error log message");
logger.warn("Warn log message");
logger.fatal("Fatal log message");
logger.trace("Trace log message");
}
}
@@ -0,0 +1,54 @@
/**
*
*/
package com.baeldung.logging.log4j2.appender;
import java.time.Instant;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.logging.log4j.Level;
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.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;
@Plugin(name = "MapAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE)
public class MapAppender extends AbstractAppender {
private ConcurrentMap<String, LogEvent> eventMap = new ConcurrentHashMap<>();
protected MapAppender(String name, Filter filter) {
super(name, filter, null);
}
@PluginFactory
public static MapAppender createAppender(@PluginAttribute("name") String name, @PluginElement("Filter") final Filter filter) {
return new MapAppender(name, filter);
}
@Override
public void append(LogEvent event) {
if (event.getLevel()
.isLessSpecificThan(Level.WARN)) {
error("Unable to log less than WARN level.");
return;
}
eventMap.put(Instant.now()
.toString(), event);
}
public ConcurrentMap<String, LogEvent> getEventMap() {
return eventMap;
}
public void setEventMap(ConcurrentMap<String, LogEvent> eventMap) {
this.eventMap = eventMap;
}
}
@@ -0,0 +1,18 @@
package com.baeldung.logging.log4j2;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.spi.LoggerContextFactory;
import org.junit.AfterClass;
import java.lang.reflect.Field;
public class Log4j2BaseIntegrationTest {
@AfterClass
public static void tearDown() throws Exception {
Field factories = ConfigurationFactory.class.getDeclaredField("factories");
factories.setAccessible(true);
factories.set(null, null);
ConfigurationFactory.resetConfigurationFactory();
}
}
@@ -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.error("Error log message from {}", this.getClass()
.getSimpleName());
LoggerContext context = LoggerContext.getContext(false);
Configuration config = context.getConfiguration();
MapAppender appender = config.getAppender("MapAppender");
assertEquals(appender.getEventMap()
.size(), 1);
}
}
@@ -0,0 +1,35 @@
/**
This class invokes the configuration factory with static initialization,
as defined in section 4.1 of the "Programmatic Configuration with Log4j 2"
**/
package com.baeldung.logging.log4j2.setconfigurationfactory;
import com.baeldung.logging.log4j2.Log4j2BaseIntegrationTest;
import com.baeldung.logging.log4j2.simpleconfiguration.CustomConfigurationFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class SetConfigurationFactoryIntegrationTest extends Log4j2BaseIntegrationTest {
@BeforeClass
public static void setUp() {
CustomConfigurationFactory customConfigurationFactory = new CustomConfigurationFactory();
ConfigurationFactory.setConfigurationFactory(customConfigurationFactory);
}
@Test
public void givenDirectConfiguration_whenUsingFlowMarkers_ThenLogsCorrectly() {
Logger logger = LogManager.getLogger(this.getClass());
Marker markerContent = MarkerManager.getMarker("FLOW");
logger.debug(markerContent, "Debug log message");
logger.info(markerContent, "Info log message");
logger.error(markerContent, "Error log message");
}
}
@@ -0,0 +1,94 @@
/**
This class demonstrates how to build the components of
the configuration factory, as described in Section 3 of
"Programmatic Configuration with Log4j 2"
**/
package com.baeldung.logging.log4j2.simpleconfiguration;
import java.io.IOException;
import java.net.URI;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Order;
import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.FilterComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.LoggerComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
import org.apache.logging.log4j.core.config.plugins.Plugin;
@Plugin(name = "simple", category = ConfigurationFactory.CATEGORY)
@Order(50)
public class CustomConfigurationFactory extends ConfigurationFactory {
static Configuration createConfiguration(final String name, ConfigurationBuilder<BuiltConfiguration> builder) {
AppenderComponentBuilder console = builder.newAppender("Stdout", "Console");
LayoutComponentBuilder layout = builder.newLayout("PatternLayout")
.addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable");
console.add(layout);
FilterComponentBuilder filter = builder.newFilter("MarkerFilter", Filter.Result.ACCEPT, Filter.Result.DENY);
filter.addAttribute("marker", "FLOW");
console.add(filter);
builder.add(console);
ComponentBuilder triggeringPolicies = builder.newComponent("Policies")
.addComponent(builder.newComponent("CronTriggeringPolicy")
.addAttribute("schedule", "0 0 0 * * ?"))
.addComponent(builder.newComponent("SizeBasedTriggeringPolicy")
.addAttribute("size", "100M"));
AppenderComponentBuilder rollingFile = builder.newAppender("rolling", "RollingFile");
rollingFile.addAttribute("fileName", "target/rolling.log");
rollingFile.addAttribute("filePattern", "target/archive/rolling-%d{MM-dd-yy}.log.gz");
rollingFile.add(layout);
rollingFile.addComponent(triggeringPolicies);
builder.add(rollingFile);
AppenderComponentBuilder file = builder.newAppender("FileSystem", "File");
file.addAttribute("fileName", "target/logging.log");
file.add(layout);
builder.add(file);
LoggerComponentBuilder logger = builder.newLogger("com", Level.DEBUG);
logger.add(builder.newAppenderRef("Stdout"));
logger.add(builder.newAppenderRef("rolling"));
logger.add(builder.newAppenderRef("FileSystem"));
logger.addAttribute("additivity", false);
builder.add(logger);
RootLoggerComponentBuilder rootLogger = builder.newRootLogger(Level.ERROR);
rootLogger.add(builder.newAppenderRef("Stdout"));
rootLogger.add(builder.newAppenderRef("rolling"));
// rootLogger.add(builder.newAppenderRef("syslogAppender"));
rootLogger.add(builder.newAppenderRef("FileSystem"));
rootLogger.addAttribute("additivity", false);
builder.add(rootLogger);
try {
builder.writeXmlConfiguration(System.out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return builder.build();
}
@Override
public Configuration getConfiguration(LoggerContext loggerContext, ConfigurationSource source) {
return getConfiguration(loggerContext, source.toString(), null);
}
public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
return createConfiguration(name, builder);
}
@Override
protected String[] getSupportedTypes() {
return new String[] { "*" };
}
}
@@ -0,0 +1,30 @@
/**
This class invokes the configuration factory through the run time property,
as defined in section 4.2 of the "Programmatic Configuration with Log4j 2"
**/
package com.baeldung.logging.log4j2.simpleconfiguration;
import com.baeldung.logging.log4j2.Log4j2BaseIntegrationTest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
import org.junit.BeforeClass;
import org.junit.Test;
public class SimpleConfigurationIntegrationTest extends Log4j2BaseIntegrationTest {
@BeforeClass
public static void setUp() {
PluginManager.addPackage("com.baeldung.logging.log4j2.simpleconfiguration");
}
@Test
public void givenSimpleConfigurationPlugin_whenUsingFlowMarkers_thenLogsCorrectly() throws Exception {
Logger logger = LogManager.getLogger(this.getClass());
Marker markerContent = MarkerManager.getMarker("FLOW");
logger.debug(markerContent, "Debug log message");
logger.info(markerContent, "Info log message");
logger.error(markerContent, "Error log message");
}
}
@@ -0,0 +1,16 @@
package com.baeldung.logging.log4j2.simpleconfigurator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class LogPrinter {
private Logger logger = LogManager.getLogger();
public void printlog() {
logger.debug("Debug log message");
logger.info("Info log message");
logger.error("Error log message");
}
}
@@ -0,0 +1,40 @@
/**
* This class demonstrates how to use ConfigurationBuilderFactory directly,
* as described in Section 3 of "Programmatic Configuration with Log4j 2"
**/
package com.baeldung.logging.log4j2.simpleconfigurator;
import com.baeldung.logging.log4j2.Log4j2BaseIntegrationTest;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class SimpleConfiguratorIntegrationTest extends Log4j2BaseIntegrationTest {
@Test
public void givenDefaultLog4j2Environment_whenProgrammaticallyConfigured_thenLogsCorrectly() {
ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
AppenderComponentBuilder console = builder.newAppender("Stdout", "CONSOLE")
.addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
console.add(builder.newLayout("PatternLayout")
.addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
builder.add(console);
builder.add(builder.newLogger("com", Level.DEBUG)
.add(builder.newAppenderRef("Stdout"))
.addAttribute("additivity", false));
builder.add(builder.newRootLogger(Level.ERROR)
.add(builder.newAppenderRef("Stdout")));
Configurator.initialize(builder.build());
LogPrinter logPrinter = new LogPrinter();
logPrinter.printlog();
}
}
@@ -0,0 +1,134 @@
package com.baeldung.logging.log4j2.tests;
import static org.junit.Assert.assertTrue;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.ResultSet;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import org.apache.logging.log4j.ThreadContext;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import com.baeldung.logging.log4j2.tests.jdbc.ConnectionFactory;
@RunWith(JUnit4.class)
public class CustomLoggingIntegrationTest {
private static String logFilePath = System.getProperty("logging.folder.path");
@BeforeClass
public static void setup() throws Exception {
Connection connection = ConnectionFactory.getConnection();
connection.createStatement()
.execute("CREATE TABLE logs(" + "when TIMESTAMP," + "logger VARCHAR(255)," + "level VARCHAR(255)," + "message VARCHAR(4096)," + "throwable TEXT)");
connection.commit();
}
@Test
public void givenLoggerWithDefaultConfig_whenLogToConsole_thanOK() throws Exception {
Logger logger = LogManager.getLogger(getClass());
Exception e = new RuntimeException("This is only a test!");
logger.info("This is a simple message at INFO level. " + "It will be hidden.");
logger.error("This is a simple message at ERROR level. " + "This is the minimum visible level.", e);
}
@Test
public void givenLoggerWithConsoleConfig_whenLogToConsoleInColors_thanOK() throws Exception {
Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_MARKER");
Exception e = new RuntimeException("This is only a test!");
logger.trace("This is a colored message at TRACE level.");
logger.debug("This is a colored message at DEBUG level. " + "This is the minimum visible level.");
logger.info("This is a colored message at INFO level.");
logger.warn("This is a colored message at WARN level.");
logger.error("This is a colored message at ERROR level.", e);
logger.fatal("This is a colored message at FATAL level.");
}
@Test
public void givenLoggerWithConsoleConfig_whenFilterByMarker_thanOK() throws Exception {
Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_MARKER");
Marker appError = MarkerManager.getMarker("APP_ERROR");
Marker connectionTrace = MarkerManager.getMarker("CONN_TRACE");
logger.error(appError, "This marker message at ERROR level should be hidden.");
logger.trace(connectionTrace, "This is a marker message at TRACE level.");
}
@Test
public void givenLoggerWithConsoleConfig_whenFilterByThreadContext_thanOK() throws Exception {
Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_THREAD_CONTEXT");
ThreadContext.put("userId", "1000");
logger.info("This is a log-visible user login. Maybe from an admin account?");
ThreadContext.put("userId", "1001");
logger.info("This is a log-invisible user login.");
}
@Test
public void givenLoggerWithAsyncConfig_whenLogToJsonFile_thanOK() throws Exception {
Logger logger = LogManager.getLogger("ASYNC_JSON_FILE_APPENDER");
final int count = 88;
for (int i = 0; i < count; i++) {
logger.info("This is async JSON message #{} at INFO level.", count);
}
long logEventsCount = Files.lines(Paths.get(logFilePath))
.count();
assertTrue(logEventsCount >= 0 && logEventsCount <= count);
}
@Test
public void givenLoggerWithFailoverConfig_whenLog_thanOK() throws Exception {
Logger logger = LogManager.getLogger("FAIL_OVER_SYSLOG_APPENDER");
Exception e = new RuntimeException("This is only a test!");
logger.trace("This is a syslog message at TRACE level.");
logger.debug("This is a syslog message at DEBUG level.");
logger.info("This is a syslog message at INFO level. This is the minimum visible level.");
logger.warn("This is a syslog message at WARN level.");
logger.error("This is a syslog message at ERROR level.", e);
logger.fatal("This is a syslog message at FATAL level.");
}
@Test
public void givenLoggerWithJdbcConfig_whenLogToDataSource_thanOK() throws Exception {
Logger logger = LogManager.getLogger("JDBC_APPENDER");
final int count = 88;
for (int i = 0; i < count; i++) {
logger.info("This is JDBC message #{} at INFO level.", count);
}
Connection connection = ConnectionFactory.getConnection();
ResultSet resultSet = connection.createStatement()
.executeQuery("SELECT COUNT(*) AS ROW_COUNT FROM logs");
int logCount = 0;
if (resultSet.next()) {
logCount = resultSet.getInt("ROW_COUNT");
}
assertTrue(logCount <= count);
}
@Test
public void givenLoggerWithRollingFileConfig_whenLogToXMLFile_thanOK() throws Exception {
Logger logger = LogManager.getLogger("XML_ROLLING_FILE_APPENDER");
final int count = 88;
for (int i = 0; i < count; i++) {
logger.info("This is rolling file XML message #{} at INFO level.", i);
}
}
}
@@ -0,0 +1,47 @@
package com.baeldung.logging.log4j2.tests;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Before;
import org.junit.Test;
import com.baeldung.logging.log4j2.Log4j2BaseIntegrationTest;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JSONLayoutIntegrationTest extends Log4j2BaseIntegrationTest {
private static Logger logger;
private ByteArrayOutputStream consoleOutput = new ByteArrayOutputStream();
private PrintStream ps = new PrintStream(consoleOutput);
@Before
public void setUp() {
// Redirect console output to our stream
System.setOut(ps);
logger = LogManager.getLogger("CONSOLE_JSON_APPENDER");
}
@Test
public void whenLogLayoutInJSON_thenOutputIsCorrectJSON() {
logger.debug("Debug message");
String currentLog = consoleOutput.toString();
assertTrue(currentLog.isEmpty());
assertTrue(isValidJSON(currentLog));
}
public static boolean isValidJSON(String jsonInString) {
try {
final ObjectMapper mapper = new ObjectMapper();
mapper.readTree(jsonInString);
return true;
} catch (IOException e) {
return false;
}
}
}
@@ -0,0 +1,33 @@
package com.baeldung.logging.log4j2.tests;
import java.util.Random;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;
public class LambdaExpressionsIntegrationTest {
private static final Logger logger = LogManager.getRootLogger();
@Test
public void whenCheckLogMessage_thenOk() {
if (logger.isTraceEnabled()) {
logger.trace("Numer is {}", getRandomNumber());
}
}
@Test
public void whenUseLambdaExpression_thenOk() {
logger.trace("Number is {}", () -> getRandomNumber());
logger.trace("Name is {} and age is {}", () -> getName(), () -> getRandomNumber());
}
private int getRandomNumber() {
return (new Random()).nextInt(10);
}
private String getName() {
return "John";
}
}
@@ -0,0 +1,25 @@
package com.baeldung.logging.log4j2.tests.jdbc;
import org.apache.commons.dbcp2.BasicDataSource;
import org.h2.Driver;
import java.sql.Connection;
import java.sql.SQLException;
public class ConnectionFactory {
private interface Singleton {
ConnectionFactory INSTANCE = new ConnectionFactory();
}
private BasicDataSource dataSource;
private ConnectionFactory() {
dataSource = new BasicDataSource();
dataSource.setDriver(new Driver());
dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
}
public static Connection getConnection() throws SQLException {
return Singleton.INSTANCE.dataSource.getConnection();
}
}
@@ -0,0 +1,24 @@
package com.baeldung.logging.log4j2.xmlconfiguration;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Order;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory;
@Plugin(name = "xml", category = ConfigurationFactory.CATEGORY)
@Order(50)
public class CustomXMLConfigurationFactory extends XmlConfigurationFactory {
@Override
public Configuration getConfiguration(LoggerContext loggerContext, ConfigurationSource source) {
return new MyXMLConfiguration(loggerContext, source);
}
@Override
public String[] getSupportedTypes() {
return new String[] { ".xml", "*" };
}
}
@@ -0,0 +1,36 @@
/**
This class demonstrates on overriding the configuration loaded through xml
as defined in section 4.4 of "Programmatic Configuration with Log4j 2"
**/
package com.baeldung.logging.log4j2.xmlconfiguration;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
import org.apache.logging.log4j.core.layout.PatternLayout;
public class MyXMLConfiguration extends XmlConfiguration {
public MyXMLConfiguration(LoggerContext loggerContext, ConfigurationSource source) {
super(loggerContext, source);
}
@Override
protected void doConfigure() {
super.doConfigure();
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration config = ctx.getConfiguration();
LoggerConfig loggerConfig = config.getLoggerConfig("com");
final Layout layout = PatternLayout.createLayout("[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n", null, config, null, null, false, false, null, null);
Appender appender = FileAppender.createAppender("target/test.log", "false", "false", "File", "true", "false", "false", "4000", layout, null, "false", null, config);
loggerConfig.addAppender(appender, Level.DEBUG, null);
addAppender(appender);
}
}
@@ -0,0 +1,44 @@
/**
This class loads the logging configuration from the xml defined in
src/main/resources and uses the same configuration generated through
programmatic configuration as defined in simple-configuration example.
**/
package com.baeldung.logging.log4j2.xmlconfiguration;
import com.baeldung.logging.log4j2.Log4j2BaseIntegrationTest;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
import org.junit.BeforeClass;
import org.junit.Test;
public class XMLConfigLogIntegrationTest extends Log4j2BaseIntegrationTest {
@BeforeClass
public static void setUp() {
PluginManager.addPackage("com.baeldung.logging.log4j2.xmlconfiguration");
}
@Test
public void givenXMLConfigurationPlugin_whenUsingFlowMarkers_ThenLogsCorrectly() throws Exception {
Logger logger = LogManager.getLogger(this.getClass());
Marker markerContent = MarkerManager.getMarker("FLOW");
logger.debug(markerContent, "Debug log message");
logger.info(markerContent, "Info log message");
logger.error(markerContent, "Error log message");
}
@Test
public void givenXMLConfigurationPlugin_whenSimpleLog_ThenLogsCorrectly() throws Exception {
Logger logger = LogManager.getLogger(this.getClass());
LoggerContext ctx = (LoggerContext) LogManager.getContext();
logger.debug("Debug log message");
logger.info("Info log message");
logger.error("Error log message");
}
}
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Console name="ConsoleAppender" target="SYSTEM_OUT">
<PatternLayout
pattern="%style{%date{DEFAULT}}{yellow} [%style{%thread}{white}] %highlight{%-5level}{FATAL=bg_red, ERROR=red, WARN=yellow, INFO=green, DEBUG=cyan, TRACE=blue} %style{%logger{36}}{cyan}:%n[+] %message%n%throwable" />
</Console>
@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns:xi="http://www.w3.org/2001/XInclude"
packages="com.baeldung" status="WARN">
<Appenders>
<xi:include
href="log4j2-includes/console-appender_pattern-layout_colored.xml" />
<Console name="ConsoleAppender" target="SYSTEM_OUT">
<PatternLayout pattern="%style{%date{DEFAULT}}{yellow} %highlight{%-5level}{FATAL=bg_red, ERROR=red, WARN=yellow, INFO=green} %message"/>
</Console>
<Console name="ConsoleRedAppender" target="SYSTEM_OUT">
<PatternLayout pattern="%style{%message}{red}%n" />
<MarkerFilter marker="CONN_TRACE" />
</Console>
<Console name="ConsoleGreenAppender" target="SYSTEM_OUT">
<PatternLayout
pattern="%style{userId=%X{userId}:}{white} %style{%message}{green}%n" />
</Console>
<Console name="ConsoleJSONAppender" target="SYSTEM_OUT">
<JsonLayout complete="false" compact="false">
<KeyValuePair key="myCustomField" value="myCustomValue" />
</JsonLayout>
</Console>
<File name="JSONLogfileAppender" fileName="${sys:logging.folder.path}">
<JSONLayout compact="true" eventEol="true" />
<BurstFilter level="INFO" rate="2" maxBurst="10" />
</File>
<Async name="AsyncAppender" bufferSize="80">
<AppenderRef ref="JSONLogfileAppender" />
</Async>
<!-- <Syslog name="Syslog" format="RFC5424" host="localhost" port="514"
protocol="TCP" facility="local3" connectTimeoutMillis="10000" reconnectionDelayMillis="5000"
mdcId="mdc" includeMDC="true" /> <Failover name="FailoverAppender" primary="Syslog">
<Failovers> <AppenderRef ref="ConsoleAppender" /> </Failovers> </Failover> -->
<JDBC name="JDBCAppender" tableName="logs">
<ConnectionFactory
class="com.baeldung.logging.log4j2.tests.jdbc.ConnectionFactory"
method="getConnection" />
<Column name="when" isEventTimestamp="true" />
<Column name="logger" pattern="%logger" />
<Column name="level" pattern="%level" />
<Column name="message" pattern="%message" />
<Column name="throwable" pattern="%ex{full}" />
</JDBC>
<RollingFile name="XMLRollingfileAppender" fileName="target/logfile.xml"
filePattern="target/logfile-%d{yyyy-MM-dd}-%i.log.gz">
<XMLLayout />
<Policies>
<SizeBasedTriggeringPolicy
size="17 kB" />
</Policies>
</RollingFile>
<MapAppender name="MapAppender"/>
</Appenders>
<Loggers>
<Logger name="CONSOLE_PATTERN_APPENDER_MARKER" level="TRACE"
additivity="false">
<AppenderRef ref="ConsoleRedAppender" />
</Logger>
<Logger name="CONSOLE_PATTERN_APPENDER_THREAD_CONTEXT"
level="INFO" additivity="false">
<AppenderRef ref="ConsoleGreenAppender" />
<ThreadContextMapFilter>
<KeyValuePair key="userId" value="1000" />
</ThreadContextMapFilter>
</Logger>
<Logger name="ASYNC_JSON_FILE_APPENDER" level="INFO"
additivity="false">
<AppenderRef ref="AsyncAppender" />
</Logger>
<!-- <Logger name="FAIL_OVER_SYSLOG_APPENDER" level="INFO" additivity="false">
<AppenderRef ref="FailoverAppender" /> </Logger> -->
<Logger name="JDBC_APPENDER" level="INFO" additivity="false">
<AppenderRef ref="JDBCAppender" />
</Logger>
<Logger name="XML_ROLLING_FILE_APPENDER" level="INFO"
additivity="false">
<AppenderRef ref="XMLRollingfileAppender" />
</Logger>
<Logger name="CONSOLE_JSON_APPENDER" level="TRACE"
additivity="false">
<AppenderRef ref="ConsoleJSONAppender" />
</Logger>
<Root level="DEBUG">
<AppenderRef ref="ConsoleAppender" />
<AppenderRef ref="MapAppender" />
</Root>
</Loggers>
</Configuration>