如何在 Spring 下配置 Logback
How to configure Logback under Spring
配置 Logback 的大多数示例使用 logback.xml。但是,我的应用程序使用 profiles and PropertySourcesPlaceholderConfigurer 的 Spring 功能将特定于环境的配置注入到需要它的组件中。像我的其他 Spring 组件一样以编程方式配置 Logback 的正确方法是什么?
在我们的一个项目中,我们是这样编码的:
import java.io.IOException;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;
@Component
public class InitializationService implements ApplicationListener<ContextRefreshedEvent> {
@Value("${logbackErrorMailPassword}")
private String logbackErrorMailPassword;
@Value("${supportEmail}")
private String supportEmail;
@Value("${spring.profiles.active}")
private String env;
@Value("${log.dir}")
private String logDir;
@Value("${log.name}")
private String logName;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
try {
configureLogback();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void configureLogback() throws IOException {
// assume SLF4J is bound to logback in the current environment
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
try {
JoranConfigurator jc = new JoranConfigurator();
jc.setContext(context);
context.reset(); // override default configuration
// inject the name of the current application as "application-name"
// property of the LoggerContext
context.putProperty("LOG_DIR", logDir);
context.putProperty("LOG_NAME", logName);
context.putProperty("ERROR_MAIL_PASSWORD", logbackErrorMailPassword);
context.putProperty("SUPPORT_EMAIL_ID", supportEmail);
context.putProperty("ENV", env);
//jc .doConfigure(servletContext.getRealPath("/WEB-INF/my-logback.xml"));
jc.doConfigure(new ClassPathResource("my-logback.xml").getInputStream());
} catch (JoranException je) {
// StatusPrinter will handle this
}
StatusPrinter.printInCaseOfErrorsOrWarnings(context);
}
}
my-logback.xml
住在 src/main/resources
,看起来像这样:
<configuration debug="true" scan="true" scanPeriod="10 minutes">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%date %level [%thread] %logger %msg%n</Pattern>
</encoder>
</appender>
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${LOG_DIR}${LOG_NAME}.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
${LOG_DIR}${LOG_NAME}-%d.%i.log.gz
</FileNamePattern>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>10MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<Pattern>%date %level [%thread] %logger %msg%n</Pattern>
</encoder>
</appender>
<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- deny all events with a level below ERROR -->
<level>ERROR</level>
</filter>
<smtpHost>xxxxxx.bluehost.com</smtpHost>
<smtpPort>465</smtpPort>
<username>xxxxxxx+xxxxx.com</username>
<password>${ERROR_MAIL_PASSWORD}</password>
<SSL>true</SSL>
<to>${SUPPORT_EMAIL_ID}</to>
<!-- Multiple to elements are permitted -->
<from>xxxxx@xxxxx.com</from>
<subject>[${ENV}] ERROR in ${LOG_NAME}</subject>
<cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker">
<bufferSize>1</bufferSize>
</cyclicBufferTracker>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%date %-5level %logger{35} - %message%n</pattern>
</layout>
</appender>
<logger name="javax.net" level="info"/>
<logger name="javax.management" level="info"/>
<logger name="org.springframework" level="info"/>
<logger name="org.compass" level="info"/>
<logger name="org.tuckey" level="info"/>
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ROLLING" />
<appender-ref ref="EMAIL" />
</root>
</configuration>
正如 orid 指出的那样,在 Spring 中使用 Logback 的官方方法是 the Logback Spring extension.
真正酷的是 Logback Spring 扩展在 Spring 或 servlet 之前启动并存储日志消息,直到配置 Appender。 (简单的附加程序将立即可用,而需要 Spring 的附加程序将通过 DelegatingLogbackAppender
代理)。
此外,您还可以:
- 使用 SLF4J 的 java.util.logging 桥。
- 使用 Spring resource path and system property 占位符指定
logback.xml
位置。
- 使用
logback.xml
内的预设系统属性webapp.root
(解压WAR目录的路径)设置日志文件路径等
配置 Logback 的大多数示例使用 logback.xml。但是,我的应用程序使用 profiles and PropertySourcesPlaceholderConfigurer 的 Spring 功能将特定于环境的配置注入到需要它的组件中。像我的其他 Spring 组件一样以编程方式配置 Logback 的正确方法是什么?
在我们的一个项目中,我们是这样编码的:
import java.io.IOException;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;
@Component
public class InitializationService implements ApplicationListener<ContextRefreshedEvent> {
@Value("${logbackErrorMailPassword}")
private String logbackErrorMailPassword;
@Value("${supportEmail}")
private String supportEmail;
@Value("${spring.profiles.active}")
private String env;
@Value("${log.dir}")
private String logDir;
@Value("${log.name}")
private String logName;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
try {
configureLogback();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void configureLogback() throws IOException {
// assume SLF4J is bound to logback in the current environment
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
try {
JoranConfigurator jc = new JoranConfigurator();
jc.setContext(context);
context.reset(); // override default configuration
// inject the name of the current application as "application-name"
// property of the LoggerContext
context.putProperty("LOG_DIR", logDir);
context.putProperty("LOG_NAME", logName);
context.putProperty("ERROR_MAIL_PASSWORD", logbackErrorMailPassword);
context.putProperty("SUPPORT_EMAIL_ID", supportEmail);
context.putProperty("ENV", env);
//jc .doConfigure(servletContext.getRealPath("/WEB-INF/my-logback.xml"));
jc.doConfigure(new ClassPathResource("my-logback.xml").getInputStream());
} catch (JoranException je) {
// StatusPrinter will handle this
}
StatusPrinter.printInCaseOfErrorsOrWarnings(context);
}
}
my-logback.xml
住在 src/main/resources
,看起来像这样:
<configuration debug="true" scan="true" scanPeriod="10 minutes">
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%date %level [%thread] %logger %msg%n</Pattern>
</encoder>
</appender>
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${LOG_DIR}${LOG_NAME}.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>
${LOG_DIR}${LOG_NAME}-%d.%i.log.gz
</FileNamePattern>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>10MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<Pattern>%date %level [%thread] %logger %msg%n</Pattern>
</encoder>
</appender>
<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- deny all events with a level below ERROR -->
<level>ERROR</level>
</filter>
<smtpHost>xxxxxx.bluehost.com</smtpHost>
<smtpPort>465</smtpPort>
<username>xxxxxxx+xxxxx.com</username>
<password>${ERROR_MAIL_PASSWORD}</password>
<SSL>true</SSL>
<to>${SUPPORT_EMAIL_ID}</to>
<!-- Multiple to elements are permitted -->
<from>xxxxx@xxxxx.com</from>
<subject>[${ENV}] ERROR in ${LOG_NAME}</subject>
<cyclicBufferTracker class="ch.qos.logback.core.spi.CyclicBufferTracker">
<bufferSize>1</bufferSize>
</cyclicBufferTracker>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%date %-5level %logger{35} - %message%n</pattern>
</layout>
</appender>
<logger name="javax.net" level="info"/>
<logger name="javax.management" level="info"/>
<logger name="org.springframework" level="info"/>
<logger name="org.compass" level="info"/>
<logger name="org.tuckey" level="info"/>
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ROLLING" />
<appender-ref ref="EMAIL" />
</root>
</configuration>
正如 orid 指出的那样,在 Spring 中使用 Logback 的官方方法是 the Logback Spring extension.
真正酷的是 Logback Spring 扩展在 Spring 或 servlet 之前启动并存储日志消息,直到配置 Appender。 (简单的附加程序将立即可用,而需要 Spring 的附加程序将通过 DelegatingLogbackAppender
代理)。
此外,您还可以:
- 使用 SLF4J 的 java.util.logging 桥。
- 使用 Spring resource path and system property 占位符指定
logback.xml
位置。 - 使用
logback.xml
内的预设系统属性webapp.root
(解压WAR目录的路径)设置日志文件路径等