logback manual
介绍
logback 依赖包
slf4j-api.jar, logback-core.jar, logback-classic.jar
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.3</version>
</dependency>
架构
相关的概念
- logger context
logger event
logger的输出
logger
logger 是命名实体,包含一个logger name. logger name显示了logger的父子或者继承关系. 例如 logger “com.personal” 是logger “com.personal.task”的父亲。 其中继承父子关系以”.”作为分隔符. logger有一个默认的root logger,是所有logger的祖先.
logger 有5个level, trace, debug, info,warn, error. 级别从低到高一次排列. 如果logger的level没有指定, logger使用离其最近的祖先logger的level.
一个logger可以包含很多appender, appender代表logger事件的输出地,目的地. 一个logger的所有appender集合默认包含了其祖先的appender列表。 如果不想包含父的appender,设置additivity属性为false.
appender
log event 的输出地
layouts
格式化输出log event
logger 的调用顺序
Get the filter chain decision
TurboFilter chain
Apply the basic selection rule
compare logger level
- Create a LoggingEvent object
- Invoking appenders
- Formatting the output
- Sending out the LoggingEvent
logback configuration
配置文件的加载顺序
logback 可以通过程序配置也可通过配置文件配置, 下面列出来配置文件的加载顺序:
- logback.groovy
- logback-test.xml
- logback.xml
- 使用logback.configurationFile环境变量指定配置文件url
- 默认使用 BasicConfigurator
appenders
console appender
class="ch.qos.logback.core.ConsoleAppender"
FileAppender
class="ch.qos.logback.core.FileAppender"
RollingFileAppender
class="ch.qos.logback.core.rolling.RollingFileAppender"
RollingFileAppender
最重要最常用的appender, 包含: file, append, encoder, rollingPolicy, triggeringPolicy等常用属性.
TimeBasedRollingPolicy
继承了rolling pollicy和trigger policy.包含 fileNamePattern和maxHistory场景属性. 参考下面的例子:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logFile.log</file>
<append>true</append>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
- file: 指定活动的文件名
- append: 表示在文件尾部append还是overwrite文件.
- rollingPolicy:指定 “ch.qos.logback.core.rolling.TimeBasedRollingPolicy”
- fileNamePattern: rolling file 文件格式. 必须包含: %d 指示符. “{}”指定时间格式,与java.text.SimpleDateFormat中的日期格式相同. 上面的例子中表示按照”天” rolling。
- maxHistory: 保持的rolling文件的最大数. 上面表示保存30天的文件.
FixedWindowRollingPolicy和SizeBasedTriggeringPolicy
FixedWindowRollingPolicy和SizeBasedTriggeringPolicy经常联合使用, 指定当文件到指定大小事滚动. 参考下面的例子:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>test.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>tests.%i.log</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
- fileNamePattern : 文件命名格式,一定要包含%i指示符.
- minIndex : %i , i的最小值
- maxIndex: %i , i的最大值
- maxFileSize: 文件的最大size
SizeAndTimeBasedFNATP size和时间结合使用
参考下面的例子:
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>mylog.txt</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
- fileNamePattern : 一定要包含%d和%i指示符
- timeBasedFileNamingAndTriggeringPolicy : class=”ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP”
SiftingAppender
SiftingAppender能按照给定的运行时属性,对记录进行分离或筛选。例如,SiftingAppender能根据用户会话对记录事件进行分离,这样,每个用户生成的记录会进入不同的记录文件,一个用户一个文件. 参考下面的例子,根据user id分文件:
代码:
logger.debug("Application started");
MDC.put("userid", "Alice");
logger.debug("Alice says hello");
appender:
<appender name="SIFT" class="ch.qos.logback.classic.sift.SiftingAppender">
<discriminator>
<key>userid</key>
<defaultValue>unknown</defaultValue>
</discriminator>
<sift>
<appender name="FILE-${userid}" class="ch.qos.logback.core.FileAppender">
<file>${userid}.log</file>
<append>false</append>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d [%thread] %level %mdc %logger{35} - %msg%n</pattern>
</layout>
</appender>
</sift>
</appender>
encoder和layout
encoder: 默认是指 PatternLayoutEncoder.
pattern: 默认指pattern layout
pattern的指示符:
- logger{length}: logger 名字, length: logger的长度
- contextName: logger context name
- date{pattern},date{pattern, timezone} : 日期
- L / line: 代码所处的行
- m / msg / message : log 消息
- M / method: 所处的方法名
- n:打印换行
- p / le / level : 输出logger 的level
- t / thread: 线程
- X{key:-defaultVal}, mdc{key:-defaultVal} : 打印mdc的key的内容
- property{key} : 属性
Groovy Configuration
default imports
import ch.qos.logback.core.*;
import ch.qos.logback.core.encoder.*;
import ch.qos.logback.core.read.*;
import ch.qos.logback.core.rolling.*;
import ch.qos.logback.core.status.*;
import ch.qos.logback.classic.net.*;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
针对logback.groovy的特别扩展
root(Level level, List appenderNames = [])
设置root logger, 带两个参数,最后一个是可选参数. 例如: root(INFO, [“CONSOLE”, “FILE”]).如果appenderNames为空,用符号[]表示
logger(String name, Level level, List appenderNames = [],Boolean additivity = null)
设置logger, 四个参数,最后两个是可选的. name: logger的名称. Level: logger的级别.参考下面例子:
logger(“com.foo”, INFO)
logger(“com.foo”, DEBUG, [“CONSOLE”])
logger(“com.foo”, DEBUG, [“CONSOLE”], false)
appender(String name, Class clazz, Closure closure = null)
定义appender, name: appender的名称, clazz: appender的实现类, closure: 包括将来的可扩展定义, 可以忽略.
一个appender可能需要很多属性和子组件. 属性使用”=”赋值,子组件作为一个命名的函数,并使用class定义初始化. 参考下面的例子:
appender("FILE", FileAppender) {
file = "testFile.log"
append = true
encoder(PatternLayoutEncoder) {
pattern = "%level %logger - %msg%n"
}
}
root(DEBUG, ["FILE"])
timestamp(String datePattern, long timeReference = -1)
获取时间. datePattern 遵循SimpleDateFormat格式. timeReference: 可选字段, 默认为-1,表示当前时间. 参看下面的例子:
def bySecond = timestamp("yyyyMMdd'T'HHmmss")
appender("FILE", FileAppender) {
file = "log-${bySecond}.txt"
encoder(PatternLayoutEncoder) {
pattern = "%logger{35} - %msg%n"
}
}
root(DEBUG, ["FILE"])
conversionRule(String conversionWord, Class converterClass)
引入自己编写的conversion, 参考下面的例子:
import chapters.layouts.MySampleConverter
conversionRule("sample", MySampleConverter)
appender("STDOUT", ConsoleAppender) {
encoder(PatternLayoutEncoder) {
pattern = "%-4relative [%thread] %sample - %msg%n"
}
}
root(DEBUG, ["STDOUT"])
scan(String scanPeriod = null)
启用scan功能, logback将会动态的scan logback.groovy 文件. 默认为每分钟一次. 如果不声明时间单位, 默认是毫秒.
scan()
scan("30 seconds")
statusListener(Class listenerClass)
注册status listener.
import chapters.layouts.MySampleConverter
// We highly recommended that you always add a status listener just
// after the last import statement and before all other statements
statusListener(OnConsoleStatusListener)
jmxConfigurator(String name)
注册JMXConfigurator MBean
groovy 的世界
变量定义和GString
使用def 定义变量, 使%{}在字符串中引用变量
def USER_HOME = System.getProperty("user.home")
appender("FILE", FileAppender) {
// make use of the USER_HOME variable
file = "${USER_HOME}/myApp.log"
encoder(PatternLayoutEncoder) {
pattern = "%msg%n"
}
}
root(DEBUG, ["FILE"])
在控制台打印信息
使用 println 打印信息
def USER_HOME = System.getProperty("user.home");
println "USER_HOME=${USER_HOME}"
appender("FILE", FileAppender) {
println "Setting [file] property to [${USER_HOME}/myApp.log]"
file = "${USER_HOME}/myApp.log"
encoder(PatternLayoutEncoder) {
pattern = "%msg%n"
}
}
root(DEBUG, ["FILE"])
保留字段
hostname
hostname 只能在最上层引用, 如果需要在全文引用hostname,需要将hostname赋值给另外一个变量。
// define HOSTNAME by assigning it hostname
def HOSTNAME=hostname
// will print "hostname is x" where x is the current host's name
println "Hostname is ${HOSTNAME}"
appender("STDOUT", ConsoleAppender) {
// will print "hostname is x" where x is the current host's name
println "Hostname is ${HOSTNAME}"
}
log context aware
logback.groovy 在一个ContextWare的一个对象中执行。 因此可以使用”context”访问档期的
Context,而且可以使用addInfo(),addWarn(),addError()发送消息到context的StatusManager。
/ always a good idea to add an on console status listener
statusListener(OnConsoleStatusListener)
// set the context's name to wombat
context.name = "wombat"
// add a status message regarding context's name
addInfo("Context name has been set to ${context.name}")
def USER_HOME = System.getProperty("user.home");
// add a status message regarding USER_HOME
addInfo("USER_HOME=${USER_HOME}")
appender("FILE", FileAppender) {
// add a status message regarding the file property
addInfo("Setting [file] property to [${USER_HOME}/myApp.log]")
file = "${USER_HOME}/myApp.log"
encoder(PatternLayoutEncoder) {
pattern = "%msg%n"
}
}
root(DEBUG, ["FILE"])
有条件的配置
使用groovy语法针对不同的环境指定不同的logger
// always a good idea to add an on console status listener
statusListener(OnConsoleStatusListener)
def appenderList = ["ROLLING"]
def WEBAPP_DIR = "."
def consoleAppender = true;
// does hostname match pixie or orion?
if (hostname =~ /pixie|orion/) {
WEBAPP_DIR = "/opt/myapp"
consoleAppender = false
} else {
appenderList.add("CONSOLE")
}
if (consoleAppender) {
appender("CONSOLE", ConsoleAppender) {
encoder(PatternLayoutEncoder) {
pattern = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
}
}
}
appender("ROLLING", RollingFileAppender) {
encoder(PatternLayoutEncoder) {
Pattern = "%d %level %thread %mdc %logger - %m%n"
}
rollingPolicy(TimeBasedRollingPolicy) {
FileNamePattern = "${WEBAPP_DIR}/log/translator-%d{yyyy-MM}.zip"
}
}
root(INFO, appenderList)