Add a logging system, starter and sample for Log4j 2

Closes gh-1565
pull/1297/merge
Daniel Fullarton 10 years ago committed by Andy Wilkinson
parent 8e000f3da1
commit 1dbc94d0f7

@ -93,6 +93,7 @@
<junit.version>4.11</junit.version>
<liquibase.version>3.0.8</liquibase.version>
<log4j.version>1.2.17</log4j.version>
<log4j2.version>2.0.2</log4j2.version>
<logback.version>1.1.2</logback.version>
<mockito.version>1.9.5</mockito.version>
<mongodb.version>2.12.3</mongodb.version>
@ -287,6 +288,11 @@
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.2.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>1.2.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
@ -562,6 +568,21 @@
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>

@ -961,14 +961,15 @@ If Groovy is on the classpath you should be able to configure Logback with
[[howto-configure-log4j-for-logging]]
=== Configure Log4j for logging
Spring Boot supports http://logging.apache.org/log4j[Log4j] for logging
configuration, but it has to be on the classpath. If you are using the starter poms for
assembling dependencies that means you have to exclude logback and then include log4j
instead. If you aren't using the starter poms then you need to provide `commons-logging`
(at least) in addition to Log4j.
Spring Boot also supports either http://logging.apache.org/log4j/1.2[Log4j] or
http://logging.apache.org/log4j/2.x[Log4j 2] for logging configuration, but only if one
of them is on the classpath. If you are using the starter poms for assembling
dependencies that means you have to exclude Logback and then include your chosen version
of Log4j instead. If you aren't using the starter poms then you need to provide
`commons-logging` (at least) in addition to your chosen version of Log4j.
The simplest path to using Log4j is probably through the starter poms, even though it
requires some jiggling with excludes, e.g. in Maven:
The simplest path is probably through the starter poms, even though it requires some
jiggling with excludes, .e.g. in Maven:
[source,xml,indent=0,subs="verbatim,quotes,attributes"]
----
@ -992,10 +993,13 @@ requires some jiggling with excludes, e.g. in Maven:
</dependency>
----
NOTE: The use of the log4j starter gathers together the dependencies for common logging
requirements (e.g. including having Tomcat use `java.util.logging` but configure the
output using Log4j). See the Actuator Log4j Sample for more detail and to see it in
action.
To use Log4j 2, simply depend on `spring-boot-starter-log4j2` rather than
`spring-boot-starter-log4j`
NOTE: The use of the one of the Log4j starters gathers together the dependencies for
common logging requirements (e.g. including having Tomcat use `java.util.logging` but
configure the output using Log4j or Log4j 2). See the Actuator Log4j or Log4j 2
samples for more detail and to see it in action.

@ -22,6 +22,7 @@
<modules>
<module>spring-boot-sample-actuator</module>
<module>spring-boot-sample-actuator-log4j</module>
<module>spring-boot-sample-actuator-log4j2</module>
<module>spring-boot-sample-actuator-noweb</module>
<module>spring-boot-sample-actuator-ui</module>
<module>spring-boot-sample-amqp</module>

@ -8,8 +8,8 @@
<version>1.2.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-sample-actuator-log4j</artifactId>
<name>Spring Boot Actuator Log4J Sample</name>
<description>Spring Boot Actuator Log4J Sample</description>
<name>Spring Boot Actuator Log4j Sample</name>
<description>Spring Boot Actuator Log4j Sample</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>

@ -0,0 +1,60 @@
<?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>
<parent>
<!-- Your own application should inherit from spring-boot-starter-parent -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-samples</artifactId>
<version>1.2.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-sample-actuator-log4j2</artifactId>
<name>Spring Boot Actuator Log4j 2 Sample</name>
<description>Spring Boot Actuator Log4j 2 Sample</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,32 @@
/*
* Copyright 2012-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.actuator.log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class HelloWorldService {
@Autowired
private ServiceProperties configuration;
public String getHelloMessage() {
return "Hello " + this.configuration.getName();
}
}

@ -0,0 +1,35 @@
/*
* Copyright 2012-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.actuator.log4j2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@EnableConfigurationProperties
@ComponentScan
public class SampleActuatorApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleActuatorApplication.class, args);
}
}

@ -0,0 +1,45 @@
/*
* Copyright 2012-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.actuator.log4j2;
import java.util.Collections;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SampleController {
@Autowired
private HelloWorldService helloWorldService;
@RequestMapping("/")
@ResponseBody
public Map<String, String> helloWorld() {
return Collections.singletonMap("message",
this.helloWorldService.getHelloMessage());
}
@RequestMapping("/foo")
@ResponseBody
public String foo() {
throw new IllegalArgumentException("Server error");
}
}

@ -0,0 +1,36 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.actuator.log4j2;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "service", ignoreUnknownFields = false)
@Component
public class ServiceProperties {
private String name = "World";
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}

@ -0,0 +1,17 @@
logging.file: /tmp/logs/app.log
#server.port: 8080
#management.port: 8080
management.address: 127.0.0.1
endpoints.shutdown.enabled: true
server.tomcat.basedir: target/tomcat
server.tomcat.access_log_pattern: %h %t "%r" %s %b
security.require_ssl: false
service.name: Daniel
shell.ssh.enabled: true
shell.ssh.port: 2222
#shell.telnet.enabled: false
#shell.telnet.port: 1111
shell.auth: spring
#shell.auth: key
#shell.auth.key.path: ${user.home}/test/id_rsa.pub.pem
#shell.auth: simple

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<Property name="PID">????</Property>
<Property name="LOG_PATTERN">[%d{yyyy-MM-dd HH:mm:ss.SSS}] log4j2%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

@ -0,0 +1,61 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.actuator.log4j2;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import static org.junit.Assert.assertEquals;
/**
* Basic integration tests for service demo application.
*
* @author Dave Syer
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SampleActuatorApplication.class)
@WebAppConfiguration
@IntegrationTest("server.port=0")
@DirtiesContext
public class SampleActuatorApplicationTests {
@Value("${local.server.port}")
private int port;
@Test
public void testHome() throws Exception {
@SuppressWarnings("rawtypes")
ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(
"http://localhost:" + port, Map.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
@SuppressWarnings("unchecked")
Map<String, Object> body = entity.getBody();
assertEquals("Hello Daniel", body.get("message"));
}
}

@ -41,6 +41,7 @@
<module>spring-boot-starter-jta-bitronix</module>
<module>spring-boot-starter-logging</module>
<module>spring-boot-starter-log4j</module>
<module>spring-boot-starter-log4j2</module>
<module>spring-boot-starter-mobile</module>
<module>spring-boot-starter-actuator</module>
<module>spring-boot-starter-parent</module>

@ -0,0 +1,42 @@
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starters</artifactId>
<version>1.2.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-starter-log4j2</artifactId>
<name>Spring Boot Log4J2 Starter</name>
<description>Spring Boot Log4J2 Starter</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
</dependencies>
</project>

@ -74,6 +74,16 @@
<artifactId>log4j</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>

@ -37,6 +37,8 @@ public abstract class LoggingSystem {
systems.put("ch.qos.logback.core.Appender", pkg + ".logback.LogbackLoggingSystem");
systems.put("org.apache.log4j.PropertyConfigurator", pkg
+ ".log4j.Log4JLoggingSystem");
systems.put("org.apache.logging.log4j.LogManager", pkg
+ ".log4j2.Log4J2LoggingSystem");
systems.put("java.util.logging.LogManager", pkg + ".java.JavaLoggingSystem");
SYSTEMS = Collections.unmodifiableMap(systems);
}

@ -33,7 +33,7 @@ import org.springframework.util.Log4jConfigurer;
import org.springframework.util.StringUtils;
/**
* {@link LoggingSystem} for for <a href="http://logging.apache.org/log4j">log4j</a>.
* {@link LoggingSystem} for <a href="http://logging.apache.org/log4j/1.2">Log4j</a>.
*
* @author Phillip Webb
* @author Dave Syer

@ -15,7 +15,7 @@
*/
/**
* Support for the Log4J logging library.
* Support for the Log4j logging library.
*/
package org.springframework.boot.logging.log4j;

@ -0,0 +1,74 @@
package org.springframework.boot.logging.log4j2;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
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.springframework.boot.logging.AbstractLoggingSystem;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import org.springframework.util.SystemPropertyUtils;
/**
* {@link LoggingSystem} for <a href="http://logging.apache.org/log4j/2.x/">Log4j 2</a>.
*
* @author Daniel Fullarton
* @since 1.2.0
*/
public class Log4J2LoggingSystem extends AbstractLoggingSystem {
private static final Map<LogLevel, Level> LEVELS;
static {
Map<LogLevel, Level> levels = new HashMap<LogLevel, Level>();
levels.put(LogLevel.TRACE, Level.TRACE);
levels.put(LogLevel.DEBUG, Level.DEBUG);
levels.put(LogLevel.INFO, Level.INFO);
levels.put(LogLevel.WARN, Level.WARN);
levels.put(LogLevel.ERROR, Level.ERROR);
levels.put(LogLevel.FATAL, Level.ERROR);
levels.put(LogLevel.OFF, Level.OFF);
LEVELS = Collections.unmodifiableMap(levels);
}
public Log4J2LoggingSystem(ClassLoader classLoader) {
super(classLoader, "log4j2.json", "log4j2.jsn", "log4j2.xml");
}
@Override
public void initialize(String configLocation) {
Assert.notNull(configLocation, "ConfigLocation must not be null");
String resolvedLocation = SystemPropertyUtils.resolvePlaceholders(configLocation);
try {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
URL url = ResourceUtils.getURL(resolvedLocation);
ConfigurationSource configSource = new ConfigurationSource(url.openStream(),
url);
Configuration config = ConfigurationFactory.getInstance().getConfiguration(
configSource);
ctx.start(config);
}
catch (Exception ex) {
throw new IllegalStateException("Could not initialize logging from "
+ configLocation, ex);
}
}
@Override
public void setLogLevel(String loggerName, LogLevel level) {
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
ctx.getConfiguration().getLoggerConfig(loggerName).setLevel(LEVELS.get(level));
ctx.updateLoggers();
}
}

@ -0,0 +1,21 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Support for the Log4j 2 logging library.
*/
package org.springframework.boot.logging.log4j2;

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<Property name="PID">????</Property>
<Property name="LOG_PATTERN">[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
</Appenders>
<Loggers>
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
<Logger name="org.crsh.plugin" level="WARN" />
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
<Logger name="org.apache.catalina.util.LifecycleBase" level="error" />
<Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<Property name="PID">????</Property>
<Property name="LOG_PATH">/tmp</Property>
<Property name="LOG_FILE">${sys:LOG_PATH}/spring.log</Property>
<Property name="LOG_PATTERN">[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
<RollingFile name="File" fileName="${sys:LOG_FILE}"
filePattern="logs/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log.gz">
<PatternLayout>
<Pattern>${LOG_PATTERN}</Pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="10 MB"/>
</Policies>
</RollingFile>
</Appenders>
<Loggers>
<Logger name="org.hibernate.validator.internal.util.Version" level="warn" />
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="warn" />
<Logger name="org.crsh.plugin" level="warn" />
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="warn" />
<Logger name="org.apache.catalina.startup.DigesterFactory" level="error" />
<Logger name="org.apache.catalina.util.LifecycleBase" level="error" />
<Logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="error" />
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

@ -0,0 +1,93 @@
/*
* Copyright 2012-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.logging.log4j2;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.test.OutputCapture;
import org.springframework.util.StringUtils;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* Tests for {@link Log4J2LoggingSystem}.
*
* @author Daniel Fullarton
*/
public class Log4J2LoggingSystemTests {
@Rule
public OutputCapture output = new OutputCapture();
private final Log4J2LoggingSystem loggingSystem = new Log4J2LoggingSystem(getClass()
.getClassLoader());
private Logger logger;
@Before
public void setup() {
this.logger = LogManager.getLogger(getClass());
}
@After
public void clear() {
System.clearProperty("LOG_FILE");
System.clearProperty("LOG_PATH");
System.clearProperty("PID");
}
@Test
public void testNonDefaultConfigLocation() throws Exception {
this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize("classpath:log4j2-nondefault.xml");
this.logger.info("Hello world");
String output = this.output.toString().trim();
assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
assertTrue("Wrong output:\n" + output, output.contains("/tmp/spring.log"));
}
@Test(expected = IllegalStateException.class)
public void testNonexistentConfigLocation() throws Exception {
this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize("classpath:log4j2-nonexistent.xml");
}
@Test(expected = IllegalArgumentException.class)
public void testNullConfigLocation() throws Exception {
this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize(null);
}
@Test
public void setLevel() throws Exception {
this.loggingSystem.beforeInitialize();
this.loggingSystem.initialize();
this.logger.debug("Hello");
this.loggingSystem.setLogLevel("org.springframework.boot", LogLevel.DEBUG);
this.logger.debug("Hello");
assertThat(StringUtils.countOccurrencesOf(this.output.toString(), "Hello"),
equalTo(1));
}
}

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Properties>
<Property name="PID">????</Property>
<Property name="LOG_PATH">/tmp</Property>
<Property name="LOG_FILE">${sys:LOG_PATH}/spring.log</Property>
<Property name="LOG_PATTERN">${sys:LOG_FILE} %d{yyyy-MM-dd HH:mm:ss.SSS}] service%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
Loading…
Cancel
Save