Configurator
接口的实现类的全限定类名。默认的配置
public void configure(LoggerContext lc) {
addInfo("Setting up default configuration.");
ConsoleAppender<ILoggingEvent> ca = new ConsoleAppender<ILoggingEvent>();
ca.setContext(lc);
ca.setName("console");
LayoutWrappingEncoder<ILoggingEvent> encoder = new LayoutWrappingEncoder<ILoggingEvent>();
encoder.setContext(lc);
// same as
// PatternLayout layout = new PatternLayout();
// layout.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n");
TTLLLayout layout = new TTLLLayout();
layout.setContext(lc);
layout.start();
encoder.setLayout(layout);
ca.setEncoder(encoder);
ca.start();
Logger rootLogger = lc.getLogger(Logger.ROOT_LOGGER_NAME);
rootLogger.addAppender(ca);
}
layout 的格式
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%npattern>
encoder>
appender>
<root level="debug">
<appender-ref ref="STDOUT" />
root>
configuration>
private static void test4(){
Logger logger = LoggerFactory.getLogger(Main.class);
LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);
logger.info("Entering application.");
}
日志打印
23:31:06,033 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
23:31:06,033 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
23:31:06,033 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/Users/xxx/IdeaProjects/logbackTest/target/classes/logback.xml]
23:31:06,121 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set
23:31:06,122 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
23:31:06,130 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT]
23:31:06,137 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.encoder.PatternLayoutEncoder] for [encoder] property
23:31:06,188 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to DEBUG
23:31:06,188 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]
23:31:06,188 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - End of configuration.
23:31:06,190 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@4bb4de6a - Registering current configuration as safe fallback point
也可以在 xm 配置中设置为 debug 模式
也会打印如上的日志信息、这个 debug = true 内部实现机制就是一个 StatusListener 。等同如下
<configuration>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
configuration>
public class OnConsoleStatusListener extends OnPrintStreamStatusListenerBase {
@Override
protected PrintStream getPrintStream() {
return System.out;
}
}
java -Dlogback.configurationFile=/path/to/config.xml 启动类
或者在启动之前通过 System 设置
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.util.ContextInitializer;
public class ServerMain {
static {
System.setProperty(ContextInitializer.CONFIG_FILE_PROPERTY, "configurationFile.xml");
}
private static final Logger LOGGER = LoggerFactory.getLogger(ServerMain.class);
public static void main(String[] args) {
LOGGER.info("xxxxxxxx");
}
}
<configuration scan="true" scanPeriod="30 seconds"
...
</configuration>
默认是 一分钟扫描一次、看文件是否更改、如果没有指定时间单位、默认为毫秒
如何确定文件是否更新了
public boolean changeDetected() {
int len = fileWatchList.size();
for (int i = 0; i < len; i++) {
long lastModified = lastModifiedList.get(i);
File file = fileWatchList.get(i);
if (lastModified != file.lastModified()) {
return true;
}
}
return false;
// return (lastModified != fileToScan.lastModified() && lastModified != SENTINEL);
}
更新整个 LoggerContext
private void performXMLConfiguration(LoggerContext lc, URL mainConfigurationURL) {
JoranConfigurator jc = new JoranConfigurator();
jc.setContext(context);
StatusUtil statusUtil = new StatusUtil(context);
List<SaxEvent> eventList = jc.recallSafeConfiguration();
URL mainURL = ConfigurationWatchListUtil.getMainWatchURL(context);
lc.reset();
long threshold = System.currentTimeMillis();
try {
jc.doConfigure(mainConfigurationURL);
if (statusUtil.hasXMLParsingErrors(threshold)) {
fallbackConfiguration(lc, eventList, mainURL);
}
} catch (JoranException e) {
fallbackConfiguration(lc, eventList, mainURL);
}
}
为根元素、包含 0 或多个
元素,其后跟 0 或多个
元素,其后再跟最多只能存在一个的
元素
在配置文件的开始定义了一个变量,之后通过引用这个变量指定了日志文件的路径。
<configuration>
<property name="USER_NAME" value="/data/logs" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_NAME}/myApp.logfile>
<encoder>
<pattern>%msg%npattern>
encoder>
appender>
<root level="debug">
<appender-ref ref="FILE" />
root>
configuration>
也可以在启动命令中指定变量值
java -DUSER_HOME="/data/logs" MyApp3
也可以将其放置到一个配置文件中
<property file="F:\project\logback-examples\src\main\resources\variables1.properties"/>
<property resource="resource1.properties" />
一个是绝对路径、一个是 classpath 下的资源
<configuration debug ="true">
<property name="local" scope="local" value="local-value" />
<property name="context" scope="context" value="context-value" />
<property name="system" scope="system" value="system-value" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${local}====%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
private static void test6(){
Logger logger = LoggerFactory.getLogger(Main.class);
logger.info("print local value");
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
logger.info("print context value:{}", loggerContext.getProperty("context"));
logger.info("print system value:{}", System.getProperty("system"));
}
打印
local-value====20:09:40.055 [main] INFO com.demo.test.Main - print local value
local-value====20:09:40.057 [main] INFO com.demo.test.Main - print context value:context-value
local-value====20:09:40.059 [main] INFO com.demo.test.Main - print system value:system-value
在进行变量替换的时候,会先从本地范围去找,再从上下文去找,再从系统属性中去找,最后会去系统的环境变量中去找。
在某些情况下,如果某个变量没有被声明,或者为空,默认值则非常有用。在 bash shell 中,默认值可以通过 “:-” 来指定。例如:假设变量 aName 没有被定义,"${aNme:-golden}" 会被解释成 “golden” 。
<configuration>
<include file="src/main/resources/includedConfig.xml" />
<include url="http://some.host.com/includedConfig.xml"/>
<root level="DEBUG">
<appender-ref ref="includedConsole" />
root>
configuration>
目标文件必须是由
元素包裹的。
<included>
<appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d - %m%npattern>
encoder>
appender>
included>
如果目标未见是可选的
<include optional="true" ..../>