- logback 组成
-
logback-core:核心模块
-
logback-classis:log4j的改良版本,完整地实现了slf4j API 使你可以很方便的更换其他日志系统如log4j 或者jdk4logging ,代码层面都不需要动,直接替换jar包即可
-
logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能
从上面可知,一般情况下只需要导入logback-core 和 logback-classis ,再配合具体的slf4j 即可完成日志框架的搭建。
//logback 中的 Logger 类的声明
public final class Logger implements org.slf4j.Logger, LocationAwareLogger, AppenderAttachable<ILoggingEvent>, Serializable {
private static final long serialVersionUID = 5454405123156820674L; // 8745934908040027998L;
- logback的配置
官方配置手册
- 配置文件加载顺序:
- 在classpath 下查找 logback-test.xml ,没查找到继续下一步
- 查找 logback.groovy ,没查找到继续下一步
- 查找 logback.xml ,没查找到 如果是jdk6 ,那么会继续查找下 META-INF\services\ch.qos.logback.classic.spi.Configurator 否则下一步
- 如果上述配置都没查找到,将自动使用默认配置,将日志信息输出到 ConsoleAppender(控制台)类似于下面的配置
<configuration >
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<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>
-
配置项三大组成:Logger、 Appender 、Layout
Logger对象就是用来处理日志信息的(决定输出什么日志信息,日志级别),Appender 用来管理日志输出目标源和输出策略(日志往哪输出,日志文件如何管理)、Layout 布局器,用来指定日志内容输出格式(日志输出内容如何格式化)。
Logger属于logback-classic 中,Appender 和 Layout 属于 logback-core 中
每个Logger都要关联到 LoggerContext 中去,其中Logger 是根据命名空间来区分的,比如 com.foo 和 com.foo.Bar ,大小写敏感,而且com.foo 是 com.foo.Bar 的父节点,全部的Logger 在LoggerContext 中类似树形一样。
其中的根Logger 是 rootLogger
Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
-
日志级别:TRACE<DEBUG<INFO<WARN <ERROR (由低到高,等于或高于配置的日志级别的信息就会输出到Appender指定的目标)
没有指定日志级别时,会跟随父节点的日志等级,比如com.foo 指定的级别是 INFO ,那么com.foo.Bar 如果指定了日志级别WARN,那么就是WARN,如果没有指定日志级别就默认是INFO -
日志打印:推荐使用占位符 {}
//依次传入多个参数
logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);
//直接准备参数数组
Object[] paramArray = {newVal, below, above};
logger.debug("Value {} was inserted between {} and {}.", paramArray);
- 完整配置和解释
- Configuration 配置
<!-- debug 开启是为了输出 logback的启动情况:输出配置文件查找过程,配置文件是否符合规范-->
<configuration debug="true" scan="true" scanPeriod="30 secondds" packagingData="true">
<!--scan 是让logback间隔一段时间定期扫描配置文件(启动一个ReconfigureOnChangeTask ),重新配置
默认间隔是 1分钟,如果需要配置间隔时间,可使用 间隔加时间单位进行配置,默认时间单位milliseconds,
其他的时间单位还有 seconds, minutes or hours -->
<!--packagingData="true" 打印异常中的堆栈信息时,将类的jar包名也输出-->
<!--默认 context name是 default ,也可以自定义 -->
<contextName>myAppName</contextName>
<!--自定义参数 可以使用 ${USER_HOME}的方式使用参数 ${USER_HOME:-home} 如果user_home 不存在就会使用默认值 home-->
<property name="USER_HOME" value="/home/sebastien" />
<!--输出到控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<withJansi>true</withJansi>
<!-- encoders are by default assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
<encoder>
<!--级别字段会高亮-->
<pattern>%d{HH:mm:ss.SSS} [%thread] %-%highlight(5level) %logger{36} - %msg%n %contextName</pattern>
</encoder>
</appender>
<!--单独指定logger级别 -->
<!--输出到root -->
<logger name="chapters.configuration" level="INFO" />
<!--指定appender additivity=false 不往上一级传递-->
<logger name="chapters.configuration.Foo" level="DEBUG" additivity="false">
<appender-ref ref="FILE" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
- Appender 配置
<!--控制台Console -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
</encoder>
</appender>
<!--输出到单个文件 -->
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<append>是否使用追加的方式写文件,默认为 true</append>
<file>myApp.log 日志文件</file>
<immediateFlush>产生logEvent时是否立即刷新,默认为true;在日志量很大的时候建议设置为 false</immediateFlush>
<encoder> <!--输出格式-->
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
</encoder>
</appender>
<!--按时间滚动输出日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logFile.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 文件名格式- 示例如下
/wombat/%d{yyyy/MM}/foo.txt 每月滚动一次
/wombat/foo.%d{yyyy-ww}.log 每周第一天滚动一次
/wombat/foo.%d 每晚上滚动一次
/wombat/foo%d{yyyy-MM-dd_HH}.log 每小时滚动一次
/wombat/foo%d{yyyy-MM-dd_HH-mm}.log 每分钟滚动一次
如果是需要进行日志文件压缩,日志文件名以使用 .gz/zip结束即可 /wombat/foo.%d.gz
->
<fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- keep 30 days' worth of history capped at 3GB total size -->
<!--最大文件个数,是文件个数 不是天数/月数 -->
<maxHistory>30</maxHistory>
<!--日志文件最大空间 -->
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
</encoder>
</appender>
<!--按时间和大小滚动输出日志文件 -->
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>mylog.txt</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- rollover daily -->
<!-- i% 表示第几个 从0 开始-->
<fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.txt</fileNamePattern>
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
<!--单个文件最大 100MB-->
<maxFileSize>100MB</maxFileSize>
<maxHistory>60</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%msg%n</pattern>
</encoder>
</appender>
<!--通过socket 将日志信息发走 -->
<appender name="SOCKET" class="ch.qos.logback.classic.net.SocketAppender">
<remoteHost>${host}</remoteHost>
<port>${port}</port>
<reconnectionDelay>10000</reconnectionDelay>
<includeCallerData>${includeCallerData}</includeCallerData>
</appender>
<!--通过SSL 将日志信息发走 -->
<appender name="SOCKET" class="ch.qos.logback.classic.net.SSLSocketAppender">
<remoteHost>${host}</remoteHost>
<port>${port}</port>
<reconnectionDelay>10000</reconnectionDelay>
<ssl>
<trustStore>
<location>${truststore}</location>
<password>${password}</password>
</trustStore>
</ssl>
</appender>
<!--通过邮件将日志信息发走 -->
<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
<smtpHost>ADDRESS-OF-YOUR-SMTP-HOST</smtpHost>
<to>EMAIL-DESTINATION</to>
<to>ANOTHER_EMAIL_DESTINATION</to> <!-- additional destinations are possible -->
<from>SENDER-EMAIL</from>
<subject>TESTING: %logger{20} - %m</subject>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%date %-5level %logger{35} - %message%n</pattern>
</layout>
</appender>
- Layout 配置
用得最多的就是 PatternLayout ,接下来以 PatternLayout为例子,解释每个关键字的意义
-
c{length} 、lo{length}、logger{length}、C{length}、class{length} : 打印logger的名字
-
d{pattern}、 date{pattern}、d{pattern, timezone}、date{pattern, timezone}:打印时间
-
L / line 行号
-
m / msg / message 日志信息
-
M / method 产生日志的类中的方法
-
n 换行符
-
p / le / level 日志级别
-
t / thread 线程号
-
r / relative 应用启动到日志输出的事件间隔 单位 milliseconds
-
ex 异常信息 ex{2} 2层深度异常 ex{full} 全部 ex 默认全部
//自定义Layout布局器
package chapters.layouts;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.LayoutBase;
public class MySampleLayout extends LayoutBase<ILoggingEvent> {
public String doLayout(ILoggingEvent event) {
StringBuffer sbuf = new StringBuffer(128);
sbuf.append(event.getTimeStamp() - event.getLoggingContextVO.getBirthTime());
sbuf.append(" ");
sbuf.append(event.getLevel());
sbuf.append(" [");
sbuf.append(event.getThreadName());
sbuf.append("] ");
sbuf.append(event.getLoggerName();
sbuf.append(" - ");
sbuf.append(event.getFormattedMessage());
sbuf.append(CoreConstants.LINE_SEP);
return sbuf.toString();
}
}
- 实时在网页上查看日志输出信息
在web.xml 中添加如下配置
<servlet>
<servlet-name>ViewStatusMessages</servlet-name>
<servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ViewStatusMessages</servlet-name>
<url-pattern>/lbClassicStatus</url-pattern>
</servlet-mapping>
打开访问地址,可以看到如下的效果
- 生产环境和测试环境不同配置(参考)
<configuration debug="true">
<if condition='property("HOSTNAME").contains("torino")'>
<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>%d %-5level %logger{35} - %msg %n</pattern>
</encoder>
</appender>
<root level="ERROR">
<appender-ref ref="FILE" />
</root>
</configuration>