参考
Logback配置加载
- 类路径下寻找
- 寻找顺序为:logback-test.xml->logback.groovy->logback.xml->Configer的实现类->使用默认的BasicConfigurator
- BasicConfigurator的等同xml配置
<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>
可以明显看出配置了一个appender,并且root的打印级别为debug,root的logger打印输出为为Std的Appender
4. 监控日志上下文
public class MyApp2 {
public static final Logger LOGGER = LoggerFactory.getLogger(MyApp2.class);
public static void main(String[] args) {
LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);
LOGGER.info("Entering application.");
Foo foo = new Foo();
foo.doIt();
LOGGER.info("Exiting application.");
}
}
Slf4j中提过了获取LoggerFactory的实现,而在logback中的实现为LoggerContext,可以用StatusPrinter来进行打印
<configuration debug="true">
</configuration>
打印logback的上下文信息只需要在配置xml文件中将configuration中设置debug,设置debug为true等于设置如下
<configuration>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<!-- 剩下的配置跟之前的相同 -->
</configuration>
配置文件修改自动扫描的配置方法为如下
<configuration scan="true" scanPeriod="30 seconds"
...
</configuration
增加一个扫描为true,并且扫描时间可以配置为30S,默认为1分钟扫描一次
可以设置在堆栈中展示jar包相关信息
<configuration packagingData="true">
...
</configuration>
配置自己的扫描规则
logback 的默认配置机制为:通过 JoranConfigurator在类路径上寻找默认的配置文件。你可以通过直接调用 JoranConfigurator 的方式来重写 logback 的默认配置机制。
public class MyApp3 {
private static final Logger LOGGER = LoggerFactory.getLogger(MyApp3.class);
public static void main(String[] args) {
LoggerContext context = (LoggerContext)LoggerFactory.getILoggerFactory();
JoranConfigurator joranConfigurator = new JoranConfigurator();
joranConfigurator.setContext(context);
context.reset();
try {
joranConfigurator.doConfigure(args[0]);
} catch (JoranException e) {
e.printStackTrace();
}
StatusPrinter.printInCaseOfErrorsOrWarnings(context);
LOGGER.info("Entering application");
Foo foo = new Foo();
foo.doIt();
LOGGER.info("Exiting application");
}
}
配置文件的语法
- logback 最基本的结构为 元素,包含 0 或多个 元素,其后跟 0 或多个 元素,其后再跟最多只能存在一个的 元素。基本结构图如下:
- 标签名大小写敏感
- 对于指定的标签名不区分大小写
- 对于非定义的使用驼峰式命名
- logger配置
- logger中需要一个确定的名称,一个可选的level属性,一个可选的additivity属性。当level的属性为null或inherited则会强制从父辈继承
- logger中至少包含0个或多得Appender-ref元素
<logger name="" level="" additivity='true'>
<appender-ref></appender-ref>
</logger>
- Appender配置规则
- Appender需要强制有name和class属性
- Appender包含0个或一个Layout元素
- Appender包含0个或多个encoder元素,0个或多个filter元素
- Layout元素可以包含对应的JavaBean属性,默认为PattenLayout,如果为该Layout可以忽略layout的Class类
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>myApp.log</file>
<encoder>
<pattern>
%date %level [%thread] %logger{10} [%file:%line] %msg%n
</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%msg%n
</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
- appender 通过 appender-ref 元素附加到 root logger 上。每一个 appender 都有自己 encoder。encoder 通常不会设计成给所有的 appender 共享。对于 layout 也是如此。因此,logback 不会提供任何共享 encoder 和 layout 的语法。
- 在默认的情况下,appender 是可以重复使用的:logger 可以通过附加到本身的 appender 输出日志,同样的也可以附加到起祖先的身上,并输出日志。因此,如果同一个 appender 附加到多个 logger 身上,那么就导致日志重复打印。
<?xml version="1.0" encoding="UTF-8"?>
<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>
<logger name="chapters.configuration">
<appender-ref ref="STDOUT" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
- 可以通过Appender设置特定的打印
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>foo.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file : %line] %msg%n</pattern>
</encoder>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<logger name="chapters.configuration.Foo" additivity="false">
<appender-ref ref="FILE" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
- 设置日志的应用名字
<configuration>
<contextName>myAppName</contextName>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %contextName [%t] %level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
当多个应用输出到同一个日志的时候可以更好的区分来源于的应用
变量替换
- 配置文件可以使用变量来配置,这个变量可以来源于配置文件,外部文件,外部资源文件甚至动态定义
<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>
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/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
<configuration>
<property file="F:\project\logback-examples\src\main\resources\variables1.properties"/>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
<configuration>
<property resource="resource1.properties" />
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${USER_HOME}/myApp.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
作用域
可以通过 、、 元素的 scope 属性来设置变量的作用范围。scope 属性可能的值为:local,context,system。如果没有指定,则默认为 local。
<configuration>
<property scope="context" name="nodeId" value="firstNode"/>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/data/${nodeId}/myApp.log</file>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
变量相关:
- 在某些情况下,如果某个变量没有被声明,或者为空,默认值则非常有用。在 bash shell 中,默认值可以通过 “:-” 来指定。例如:假设变量 aName 没有被定义,"${aNme:-golden}" 会被解释成 “golden” 。
- 一个变量的值可以包含对其它变量的引用。
- 默认值嵌套:一个变量的默认值可以引用另一个变量。例如:假设变量 “id” 没有被定义,变量 “userid” 的值为 “alice”,那么表达式 “KaTeX parse error: Expected '}', got 'EOF' at end of input: {id:-{userid}}” 的值为 “alice”。
- 配置文件中的条件处理
开发,测试和生产。这些配置文件有大量相同的地方,只有少数地方不同。为了避免重复,logback 在配置文件中支持通过 、、 元素作为条件语句来区分不同的环境。条件处理需要 Janino 环境的支持。
<if condition="条件表达式">
<then>
...
</then>
</if>
<if condition="条件表达式">
<then>
...
</then>
<else>
...
</else>
</if>
条件表达式只能是上下文变量或者系统变量。因为值是通过参数传递的,property() 方法或者其等价的 p() 方法属性的值。例如:如果要获取变量 “k” 的值,可以通过 property(“k”) 或者 p(“k”) 来获取。如果 “k” 没有定义,那么方法将会返回空字符串。所以不需要去判断是否为 null。
isDefined() 方法可以用来判断变量是否已经被定义。例如:可以通过 isDefined(“k”) 来判断 k 是否已经定义。还可以通过 isNull() 方法来判断变量是否为 null。例如:isNull(“k”)。
<configuration debug="true">
<if condition='property("HOSTNAME").contains("volong")'>
<then>
<appender name="CON" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %-5level %logger{35} - %msg %n</pattern>
</encoder>
</appender>
<root>
<appender-ref ref="CON" />
</root>
</then>
</if>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>${randomOutputDir}/conditional.log</file>
<encoder>
<pattern>${HOSTNAME} %d %-5level %logger{35} - %msg %n</pattern>
</encoder>
</appender>
<root level="ERROR">
<appender-ref ref="FILE" />
</root>
</configuration>