网络异常,图片无法展示
|
logback 的配置
- logback 会在类路径下寻找名为 logback-test.xml 的文件。
- 如果没有找到,logback 会继续寻找名为 logback.groovy 的文件。
- 如果没有找到,logback 会继续寻找名为 logback.xml 的文件。
- 如果没有找到,将会通过 JDK 提供的 ServiceLoader 工具在类路径下寻找文件 META-INFO/services/ch.qos.logback.classic.spi.Configurator,该文件的内容为实现了
Configurator
接口的实现类的全限定类名。 - 如果以上都没有成功,logback 会通过 BasicConfigurator 为自己进行配置,并且日志将会全部在控制台打印出来。
默认的配置
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%n</pattern> </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 模式
<configuration debug ="true"> 复制代码
也会打印如上的日志信息、这个 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); } } 复制代码
配置文件元素
<configuration>
为根元素、包含 0 或多个 <appender>
元素,其后跟 0 或多个 <logger>
元素,其后再跟最多只能存在一个的 <root>
元素
网络异常,图片无法展示
|
变量
在配置文件的开始定义了一个变量,之后通过引用这个变量指定了日志文件的路径。
<configuration> <property name="USER_NAME" value="/data/logs" /> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${USER_NAME}/myApp.log</file> <encoder> <pattern>%msg%n</pattern> </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 下的资源
作用域
- local 本地范围的属性存在配置文件的加载过程中、配置文件每加载一次、变量就会被重新定义一次
- context 作用域的范围延伸至 loggerContext 中
- system 作用域整个 JVM 都有效
<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>
元素包裹的。
<included> <appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d - %m%n</pattern> </encoder> </appender> </included> 复制代码
如果目标未见是可选的
<include optional="true" ..../>