LogBack简易教程
1.简介
LogBack是一个日志框架,它与Log4j可以说是同出一源,都出自Ceki Gülcü之手。(log4j的原型是早前由Ceki Gülcü贡献给Apache基金会的)
1.1 LogBack,Slf4j,Log4j之间的关系
Slf4j是The Simple Logging Facade for Java的简称,是一个简单日志门面抽象框架,它本身只提供了日志Facade API和一个简单的日志类实现,一般常配合Log4j,LogBack,java.util.logging使用。Slf4j作为应用层的Log接入时, 程序可以根据实际应用场景动态调整底层的日志实现框架(Log4j/LogBack/JdkLog...);
LogBack和Log4j都是开源日记工具库,LogBack是Log4j的改良版本,比Log4j拥有更多的特性,同时也带来很大性能提升。详细数据可参照下面地址:Reasons to prefer logback over log4j
LogBack官方建议配合Slf4j使用,这样可以灵活地替换底层日志框架。
(note: 为了优化log4j,以及更大性能的提升,Apache基金会已经着手开发了log4j 2.0, 其中也借鉴和吸收了logback的一些先进特性,目前log4j2还处于beta阶段)
1.2 LogBack的结构
LogBack被分为3个组件,logback-core, logback-classic 和 logback-access.
其中logback-core提供了LogBack的核心功能,是另外两个组件的基础。
logback-classic则实现了Slf4j的API,所以当想配合Slf4j使用时,需要将logback-classic加入classpath.
logback-access是为了集成Servlet环境而准备的,可提供HTTP-access的日志接口;
2. Slf4j+Logback的快速实践
2.1 资源准备
现在常用的是将slf4j+Logback进行配套使用,所以需要将slf4j-api.jar, logback-core.jar, log-classic.jar加入classpath.
之后编写logback.xml配置文件,同样该文件要加入classpath中,这样LogBack启动的时候会自动扫描到并加载。
(note: 若LogBack无法检索到相关的配置文件,则会启用默认配置,将日志按照默认格式输出于控制台)
2.2 logback.xml配置
LogBack的配置大概包括3部分,Appender,Logger,Root的配置。

<?xml version="1.0" encoding="UTF-8"?> <configuration debug="true" scan="true" scanPeriod="30 seconds"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are by default assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%level] - %m%n</pattern> <!-- 常用的Pattern变量,大家可打开该pattern进行输出观察 -->
<!--
<pattern>
%d{yyyy-MM-dd HH:mm:ss} [%level] - %msg%n
Logger: %logger
Class: %class
File: %file
Caller: %caller
Line: %line
Message: %m
Method: %M
Relative: %relative
Thread: %thread
Exception: %ex
xException: %xEx
nopException: %nopex
rException: %rEx
Marker: %marker
%n </pattern>
-->
</encoder>
</appender> <!-- 按日期区分的滚动日志 -->
<appender name="ERROR-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/error.log</file> <encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
</encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>error.%d{yyyy-MM-dd}.log.zip</fileNamePattern> <!-- keep 30 days' worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender> <!-- 按文件大小区分的滚动日志 -->
<appender name="INFO-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/info.log</file> <encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
</encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>info.%i.log</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy> </appender> <!-- 按日期和大小区分的滚动日志 -->
<appender name="DEBUG-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/debug.log</file> <encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
</encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- or whenever the file size reaches 100MB -->
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> </appender> <!-- 级别阀值过滤 -->
<appender name="SUM-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/sum.log</file> <encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
</encoder> <!-- deny all events with a level below INFO, that is TRACE and DEBUG -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- or whenever the file size reaches 100MB -->
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> </appender> <root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="ERROR-OUT" />
<appender-ref ref="INFO-OUT" />
<appender-ref ref="DEBUG-OUT" />
<appender-ref ref="SUM-OUT" />
</root>
</configuration>
另一个更简单的:
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="true" scan="false" scanPeriod="30 seconds"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are by default assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%level] - %m%n</pattern>
</encoder>
</appender> <!-- 按日期区分的滚动日志 -->
<appender name="APP" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file> <encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
</encoder> <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- daily rollover -->
<fileNamePattern>app.%d{yyyy-MM-dd}.log</fileNamePattern> <!-- keep 30 days' worth of history -->
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender> <!-- 按日期和大小区分的滚动日志 -->
<appender name="DEBUG-OUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/debug.log</file> <encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%class:%line] - %m%n</pattern>
</encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- rollover daily -->
<fileNamePattern>debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- or whenever the file size reaches 100MB -->
<maxFileSize>30MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy> </appender> <root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="APP" />
<appender-ref ref="DEBUG-OUT" />
</root>
</configuration>
2.3 示例
public class Slf4jTest {
private static Logger Log = LoggerFactory.getLogger(Slf4jTest.class);
@Test
public void testLogBack(){
Log.debug("Test the MessageFormat for {} to {} endTo {}", 1,2,3);
Log.info("Test the MessageFormat for {} to {} endTo {}", 1,2,3);
Log.error("Test the MessageFormat for {} to {} endTo {}", 1,2,3);
try{
throw new IllegalStateException("try to throw an Exception");
}catch(Exception e){
Log.error(e.getMessage(),e);
}
}
}
输出:
-- :: [DEBUG] - Test the MessageFormat for to endTo
-- :: [INFO] - Test the MessageFormat for to endTo
-- :: [ERROR] - Test the MessageFormat for to endTo
-- :: [ERROR] - try to throw an Exception
java.lang.IllegalStateException: try to throw an Exception
at logs.Slf4jTest.testLogBack(Slf4jTest.java:) ~[bin/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.6.0_18]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:) ~[na:1.6.0_18]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:) ~[na:1.6.0_18]
at java.lang.reflect.Method.invoke(Method.java:) ~[na:1.6.0_18]
at org.junit.runners.model.FrameworkMethod$.runReflectiveCall(FrameworkMethod.java:) [junit.jar:na]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:) [junit.jar:na]
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:) [junit.jar:na]
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:) [junit.jar:na]
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:) [junit.jar:na]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:) [junit.jar:na]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:) [junit.jar:na]
at org.junit.runners.ParentRunner$.run(ParentRunner.java:) [junit.jar:na]
at org.junit.runners.ParentRunner$.schedule(ParentRunner.java:) [junit.jar:na]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:) [junit.jar:na]
at org.junit.runners.ParentRunner.access$(ParentRunner.java:) [junit.jar:na]
at org.junit.runners.ParentRunner$.evaluate(ParentRunner.java:) [junit.jar:na]
at org.junit.runners.ParentRunner.run(ParentRunner.java:) [junit.jar:na]
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:) [.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:) [.cp/:na]
LogBack简易教程的更多相关文章
- Java Logback简易教程
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可. 一.前言 本文以一个简单的项目为例,一步步展示logback的同步和异步配置方法,并且配置的日志要求满足阿里巴巴Java开发手册- ...
- 生活科技两相宜:(一)Win7使用微软SkyDrive网盘简易教程
今天得写一个Win7使用微软SkyDrive网盘的简易教程,主要是给我老婆看,顺便贴出来给大家共享一下:) 使用微软SkyDrive网盘有两个层次.一个是使用网页版,这个跟使用163或者QQ网盘 ...
- JavaScript简易教程(转)
原文:http://www.cnblogs.com/yanhaijing/p/3685304.html 这是我所知道的最完整最简洁的JavaScript基础教程. 这篇文章带你尽快走进JavaScri ...
- Emacs简易教程
Emacs简易教程阅读: 命令: $emacs 进入之后,输入: C-h t 这里,C-h表示按住[Ctrl]键的同时按h ####### 20090620 *退出: 输入“C-x C-c” *撤销: ...
- 文件上传利器SWFUpload入门简易教程
凡做过网站开发的都应该知道表单file的确鸡肋. Ajax解决了不刷新页面提交表单,但是却没有解决文件上传不刷新页面,当然也有其它技术让不刷新页面而提交文件,该技术主要是利用隐藏的iFrame, 较A ...
- 【转】Delphi内嵌ASM简易教程
Delphi内嵌ASM简易教程 作者:heiying2006-03-19 18:33分类:默认分类标签: 前言 Delphi作为一个快速高效的开发平台,使用的人越来越多,但熟悉在Delphi代码中嵌入 ...
- Ant 简易教程
转载:http://www.cnblogs.com/jingmoxukong/p/4433945.html Ant 简易教程 Apache Ant,是一个将软件编译.测试.部署等步骤联系在一起加以自动 ...
- Intellj IDEA 简易教程
Intellj IDEA 简易教程 目录 JDK 安装测试 IDEA 安装测试 调试 单元测试 重构 Git Android 其他 参考资料 Java开发IDE(Integrated Developm ...
- MetaProducts Offline Explorer使用简易教程
MetaProducts Offline Explorer使用简易教程 by windtrace 20170419 最近想下载一个网站上的内容打包成chm文件,以便离线浏览,webzip太长时间不更 ...
随机推荐
- 【JQ基础】数组
each() 方法规定为每个匹配元素规定运行的函数.
- 报错:You need to use a Theme.AppCompat theme (or descendant) with this activity.
学习 Activity 生命周期时希望通过 Dialog 主题测试 onPause() 和 onStop() 的区别,点击按钮跳转 Activity 时报错: E/AndroidRuntime: FA ...
- [OC] NSURLSession
有的程序员老了,还没听过NSURLSession 有的程序员还嫩,没用过NSURLConnection 有的程序员很单纯,他只知道AFN. NSURLConnection在iOS9被宣布弃用,NSUR ...
- 开源 iOS 项目分类索引大全 - 待整理
开源 iOS 项目分类索引大全 GitHub 上大概600个开源 iOS 项目的分类和介绍,对于你挑选和使用开源项目应该有帮助 系统基础库 Category/Util sstoolkit 一套Cate ...
- 15个C++项目列表
实验楼上有很多C++的实战项目,从简单到进阶,学习每个项目都可以掌握相应的知识点. 如果你还是C++新手的话,那么这个C++的项目列表你可以拿去练手实战开发,毕竟学编程动手实践是少不了的! 如果你不知 ...
- 写个Fragment方便的抽象基类 BaseFragment
package com.zb.zhihuianyang.base; import android.app.Activity; import android.os.Bundle; import andr ...
- 作为前端er,写在年末的一些话
写惯了技术类的文章,这种总结和唠嗑型的我基本也就在年末才来一篇.说实话,这种轻松类的文章往往比技术类的要受欢迎的多,因为其受众更广,看起来也不烧脑. 说来愧疚,这一年其实产出有点低,大致就写了不到二十 ...
- Java泛型的历史
为什么Java泛型会有当前的缺陷? 之前的章节里已经说明了Java泛型擦除会导致的问题,C++和C#的泛型都是在运行时存在的,难道Java天然不支持“真正的泛型”吗? 事实上,在Java1.5在200 ...
- 用lucene替代mysql读库的尝试
采用lucene对mysql中的表建索引,并替代全文检索操作. 备注:代码临时梳理很粗糙,后续修改. import java.io.File; import java.io.IOException; ...
- 淘宝UWP中的100个为什么
从淘宝UWP第一版发布到现在,已经有十个月了,期间收到了用户各种各样的反馈,感谢这些用户的反馈,指导我们不断的修正.完善应用.但是也有一部分需求或建议,由于资源或技术的限制,目前确实无法做到,只能对广 ...