BAEL-1338 - Programmatic Log4j2
This commit features a number of tests for programmatically configuring log4j. Note that in order to have these tests live together, there is a slight deviation in how these are configured vs how they are in the real world, specifically around static initialization. Generally speaking, whenever static initialization is needed for a given configuration, it is embedded in a @BeforeClass-annotated JUnit method. Also, to isolate the tests from each other's plugins, annotation processing was turned off in the build. This is not required when doing programmatic configuration of log4j. It is simply needed for the specific use case of demonstrating these various log4j plugins all in the same module.
This commit is contained in:
@@ -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 Log4j2Test {
|
||||
@AfterClass
|
||||
public static void tearDown() throws Exception {
|
||||
Field factories = ConfigurationFactory.class.getDeclaredField("factories");
|
||||
factories.setAccessible(true);
|
||||
factories.set(null, null);
|
||||
ConfigurationFactory.resetConfigurationFactory();
|
||||
|
||||
}
|
||||
}
|
||||
+35
@@ -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.Log4j2Test;
|
||||
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 SetConfigurationFactoryTest extends Log4j2Test {
|
||||
@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");
|
||||
}
|
||||
}
|
||||
+94
@@ -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[] { "*" };
|
||||
}
|
||||
}
|
||||
|
||||
+30
@@ -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.Log4j2Test;
|
||||
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 SimpleConfigurationTest extends Log4j2Test {
|
||||
@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");
|
||||
}
|
||||
}
|
||||
+16
@@ -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");
|
||||
}
|
||||
}
|
||||
+40
@@ -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.Log4j2Test;
|
||||
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 SimpleConfiguratorTest extends Log4j2Test {
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -6,6 +6,7 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import com.baeldung.logging.log4j2.Log4j2Test;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.junit.Before;
|
||||
@@ -13,7 +14,7 @@ import org.junit.Test;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
public class JSONLayoutTest {
|
||||
public class JSONLayoutTest extends Log4j2Test {
|
||||
|
||||
private static Logger logger;
|
||||
private ByteArrayOutputStream consoleOutput = new ByteArrayOutputStream();
|
||||
|
||||
+24
@@ -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", "*" };
|
||||
}
|
||||
}
|
||||
+36
@@ -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);
|
||||
}
|
||||
}
|
||||
+44
@@ -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.Log4j2Test;
|
||||
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 XMLConfigLogTest extends Log4j2Test {
|
||||
|
||||
@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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user