点击上方“Java知音”,选择“置顶公众号”
技术文章第一时间送达!
作者:静默虚空
作者:静默虚空 juejin.im/post/5c8f35bfe51d4545cc650567 在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息。在 Java 世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子。
我们先来逐一了解一下主流日志工具。
日志框架
java.util.logging (JUL)
JDK1.4 开始,通过 java.util.logging 提供日志功能。
它能满足基本的日志需要,但是功能没有 Log4j 强大,而且使用范围也没有 Log4j 广泛。
Log4j
Log4j 是 apache 的一个开源项目,创始人 Ceki Gulcu。
Log4j 应该说是 Java 领域资格最老,应用最广的日志工具。从诞生之日到现在一直广受业界欢迎。
Log4j 是高度可配置的,并可通过在运行时的外部文件配置。它根据记录的优先级别,并提供机制,以指示记录信息到许多的目的地,诸如:数据库,文件,控制台,UNIX 系统日志等。
Log4j 中有三个主要组成部分:
- loggers - 负责捕获记录信息。
- appenders - 负责发布日志信息,以不同的首选目的地。
- layouts - 负责格式化不同风格的日志信息。
官网地址:
http://logging.apache.org/log4j/2.x/
Logback
Logback 是由 log4j 创始人 Ceki Gulcu 设计的又一个开源日记组件,目标是替代 log4j。
logback 当前分成三个模块:logback-core、logback-classic 和 logback-access。
- logback-core - 是其它两个模块的基础模块。
- logback-classic - 是 log4j 的一个 改良版本。此外 logback-classic 完整实现 SLF4J API 使你可以很方便地更换成其它日记系统如 log4j 或 JDK14 Logging。
- logback-access - 访问模块与 Servlet 容器集成提供通过 Http 来访问日记的功能。
官网地址:
Log4j2
官网地址:
http://logging.apache.org/log4j/2.x/
按照官方的说法,Log4j2 是 Log4j 和 Logback 的替代。
Log4j2 架构:
Log4j vs Logback vs Log4j2
按照官方的说法,Log4j2 大大优于 Log4j 和 Logback。
那么,Log4j2 相比于先问世的 Log4j 和 Logback,它具有哪些优势呢?
- Log4j2 旨在用作审计日志记录框架。Log4j 1.x 和 Logback 都会在重新配置时丢失事件。Log4j 2 不会。在 Logback 中,Appender 中的异常永远不会对应用程序可见。在 Log4j 中,可以将 Appender 配置为允许异常渗透到应用程序。
- Log4j2 在多线程场景中,异步 Loggers 的吞吐量比 Log4j 1.x 和 Logback 高 10 倍,延迟低几个数量级。
- Log4j2 对于独立应用程序是无垃圾的,对于稳定状态日志记录期间的 Web 应用程序来说是低垃圾。这减少了垃圾收集器的压力,并且可以提供更好的响应时间性能。
- Log4j2 使用插件系统,通过添加新的 Appender、Filter、Layout、Lookup 和 Pattern Converter,可以非常轻松地扩展框架,而无需对 Log4j 进行任何更改。
- 由于插件系统配置更简单。配置中的条目不需要指定类名。
- 支持自定义日志等级。
- 支持 lambda 表达式。
- 支持消息对象。
- Log4j 和 Logback 的 Layout 返回的是字符串,而 Log4j2 返回的是二进制数组,这使得它能被各种 Appender 使用。
- Syslog Appender 支持 TCP 和 UDP 并且支持 BSD 系统日志。
- Log4j2 利用 Java5 并发特性,尽量小粒度的使用锁,减少锁的开销。
日志门面
何谓日志门面?
日志门面是对不同日志框架提供的一个 API 封装,可以在部署的时候不修改任何配置即可接入一种日志实现方案。
common-logging
common-logging 是 apache 的一个开源项目。也称Jakarta Commons Logging,缩写 JCL。
common-logging 的功能是提供日志功能的 API 接口,本身并不提供日志的具体实现(当然,common-logging 内部有一个 Simple logger 的简单实现,但是功能很弱,直接忽略),而是在运行时动态的绑定日志实现组件来工作(如 log4j、java.util.loggin)。
官网地址:
http://commons.apache.org/proper/commons-logging/
slf4j
全称为 Simple Logging Facade for Java,即 java 简单日志门面。
什么,作者又是 Ceki Gulcu!这位大神写了 Log4j、Logback 和 slf4j,专注日志组件开发五百年,一直只能超越自己。
类似于 Common-Logging,slf4j 是对不同日志框架提供的一个 API 封装,可以在部署的时候不修改任何配置即可接入一种日志实现方案。但是,slf4j 在编译时静态绑定真正的 Log 库。使用 SLF4J 时,如果你需要使用某一种日志实现,那么你必须选择正确的 SLF4J 的 jar 包的集合(各种桥接包)。
官网地址:
common-logging vs slf4j
slf4j 库类似于 Apache Common-Logging。但是,他在编译时静态绑定真正的日志库。这点似乎很麻烦,其实也不过是导入桥接 jar 包而已。
slf4j 一大亮点是提供了更方便的日志记录方式:
不需要使用logger.isDebugEnabled()来解决日志因为字符拼接产生的性能问题。slf4j 的方式是使用{}作为字符串替换符,形式如下:
1 logger.debug("id: {}, name: {} ", id, name);logger.debug(“id: {}, name: {} “, id, name);
总结
综上所述,使用 slf4j + Logback 可谓是目前最理想的日志解决方案了。
接下来,就是如何在项目中实施了。
实施日志解决方案
使用日志解决方案基本可分为三步:
- 引入 jar 包
- 配置
- 使用 API
常见的各种日志解决方案的第 2 步和第 3 步基本一样,实施上的差别主要在第 1 步,也就是使用不同的库。
引入 jar 包
这里首选推荐使用 slf4j + logback 的组合。
如果你习惯了 common-logging,可以选择 common-logging+log4j。
强烈建议不要直接使用日志实现组件(logback、log4j、java.util.logging),理由前面也说过,就是无法灵活替换日志库。
还有一种情况:你的老项目使用了 common-logging,或是直接使用日志实现组件。如果修改老的代码,工作量太大,需要兼容处理。在下文,都将看到各种应对方法。
注:据我所知,当前仍没有方法可以将 slf4j 桥接到 common-logging。如果我孤陋寡闻了,请不吝赐教。
slf4j 直接绑定日志组件
slf4j + logback
添加依赖到 pom.xml 中即可。
logback-classic-1.0.13.jar 会自动将 slf4j-api-1.7.21.jar 和 logback-core-1.0.13.jar 也添加到你的项目中。
12345 dependency groupIdch.qos.logback/groupId artifactIdlogback-classic/artifactId version1.0.13/version/dependencydependency
groupIdch.qos.logback/groupId
artifactIdlogback-classic/artifactId
version1.0.13/version
/dependencyslf4j + log4j
添加依赖到 pom.xml 中即可。
slf4j-log4j12-1.7.21.jar 会自动将 slf4j-api-1.7.21.jar 和 log4j-1.2.17.jar 也添加到你的项目中。
12345 dependency groupIdorg.slf4j/groupId artifactIdslf4j-log4j12/artifactId version1.7.21/version/dependencydependency
groupIdorg.slf4j/groupId
artifactIdslf4j-log4j12/artifactId
version1.7.21/version
/dependencyslf4j + java.util.logging
添加依赖到 pom.xml 中即可。
slf4j-jdk14-1.7.21.jar 会自动将 slf4j-api-1.7.21.jar 也添加到你的项目中。
12345 dependency groupIdorg.slf4j/groupId artifactIdslf4j-jdk14/artifactId version1.7.21/version/dependencydependency
groupIdorg.slf4j/groupId
artifactIdslf4j-jdk14/artifactId
version1.7.21/version
/dependencyslf4j 兼容非 slf4j 日志组件
在介绍解决方案前,先提一个概念——桥接
什么是桥接呢
假如你正在开发应用程序所调用的组件当中已经使用了 common-logging,这时你需要 jcl-over-slf4j.jar 把日志信息输出重定向到 slf4j-api,slf4j-api 再去调用 slf4j 实际依赖的日志组件。这个过程称为桥接。下图是官方的 slf4j 桥接策略图:
从图中应该可以看出,无论你的老项目中使用的是 common-logging 或是直接使用 log4j、java.util.logging,都可以使用对应的桥接 jar 包来解决兼容问题。
slf4j 兼容 common-logging
12345 dependency groupIdorg.slf4j/groupId artifactIdjcl-over-slf4j/artifactId version1.7.12/version /dependencydependency
groupIdorg.slf4j/groupId
artifactIdjcl-over-slf4j/artifactId
version1.7.12/version
/dependencyslf4j 兼容 log4j
12345 dependency groupIdorg.slf4j/groupId artifactIdlog4j-over-slf4j/artifactId version1.7.12/version/dependencydependency
groupIdorg.slf4j/groupId
artifactIdlog4j-over-slf4j/artifactId
version1.7.12/version
/dependencyslf4j 兼容 java.util.logging
12345 dependency groupIdorg.slf4j/groupId artifactIdjul-to-slf4j/artifactId version1.7.12/version /dependencydependency
groupIdorg.slf4j/groupId
artifactIdjul-to-slf4j/artifactId
version1.7.12/version
/dependencyspring 集成 slf4j
做 java web 开发,基本离不开 spring 框架。很遗憾,spring 使用的日志解决方案是 common-logging + log4j。(系统的学习spring全家桶,可以在Java知音公众号内回复“Springboot聚合”)
所以,你需要一个桥接 jar 包:logback-ext-spring。
123456789101112131415 dependency groupIdch.qos.logback/groupId artifactIdlogback-classic/artifactId version1.1.3/version /dependency dependency groupIdorg.logback-extensions/groupId artifactIdlogback-ext-spring/artifactId version0.1.2/version /dependency dependency groupIdorg.slf4j/groupId artifactIdjcl-over-slf4j/artifactId version1.7.12/version /dependencydependency
groupIdch.qos.logback/groupId
artifactIdlogback-classic/artifactId
version1.1.3/version
/dependency
dependency
groupIdorg.logback-extensions/groupId
artifactIdlogback-ext-spring/artifactId
version0.1.2/version
/dependency
dependency
groupIdorg.slf4j/groupId
artifactIdjcl-over-slf4j/artifactId
version1.7.12/version
/dependencycommon-logging 绑定日志组件
common-logging + log4j
添加依赖到 pom.xml 中即可。
12345678910 dependency groupIdcommons-logging/groupId artifactIdcommons-logging/artifactId version1.2/version /dependency dependency groupIdlog4j/groupId artifactIdlog4j/artifactId version1.2.17/version /dependencydependency
groupIdcommons-logging/groupId
artifactIdcommons-logging/artifactId
version1.2/version
/dependency
dependency
groupIdlog4j/groupId
artifactIdlog4j/artifactId
version1.2.17/version
/dependency使用 API
slf4j 用法
使用 slf4j 的 API 很简单。使用LoggerFactory初始化一个Logger实例,然后调用 Logger 对应的打印等级函数就行了。
1234567891011121314 import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class App { private static final Logger log = LoggerFactory.getLogger(App.class); public static void main(String[] args) { String msg = "print log, current level: {}"; log.trace(msg, "trace"); log.debug(msg, "debug"); log.info(msg, "info"); log.warn(msg, "warn"); log.error(msg, "error"); } }import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class App {
private static final Logger log = LoggerFactory.getLogger(App.class);
public static void main(String[] args) {
String msg = “print log, current level: {}”;
log.trace(msg, “trace”);
log.debug(msg, “debug”);
log.info(msg, “info”);
log.warn(msg, “warn”);
log.error(msg, “error”);
}
}common-logging 用法
common-logging 用法和 slf4j 几乎一样,但是支持的打印等级多了一个更高级别的:fatal。
此外,common-logging 不支持{}替换参数,你只能选择拼接字符串这种方式了。
12345678910111213141516 import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class JclTest { private static final Log log = LogFactory.getLog(JclTest.class); public static void main(String[] args) { String msg = "print log, current level: "; log.trace(msg + "trace"); log.debug(msg + "debug"); log.info(msg + "info"); log.warn(msg + "warn"); log.error(msg + "error"); log.fatal(msg + "fatal"); } }import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;public class JclTest {
private static final Log log = LogFactory.getLog(JclTest.class);public static void main(String[] args) {
String msg = “print log, current level: “;
log.trace(msg + “trace”);
log.debug(msg + “debug”);
log.info(msg + “info”);
log.warn(msg + “warn”);
log.error(msg + “error”);
log.fatal(msg + “fatal”);
}
}log4j2 配置
log4j2 基本配置形式如下:
1234567891011121314151617181920212223 ?xml version="1.0" encoding="UTF-8"?; Configuration Properties Property name="name1"value/property Property name="name2" value="value2"/ /Properties Filter type="type" ... / Appenders Appender type="type" name="name" Filter type="type" ... / /Appender ... /Appenders Loggers Logger name="name1" Filter type="type" ... / /Logger ... Root level="level" AppenderRef ref="name"/ /Root /Loggers /Configuration?xml version=”1.0” encoding=”UTF-8”?;
Configuration
Properties
Property name=”name1”value/property
Property name=”name2” value=”value2”/
/Properties
Filter type=”type” … /
Appenders
Appender type=”type” name=”name”
Filter type=”type” … /
/Appender
…
/Appenders
Loggers
Logger name=”name1”
Filter type=”type” … /
/Logger
…
Root level=”level”
AppenderRef ref=”name”/
/Root
/Loggers
/Configuration配置示例:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 ?xml version="1.0" encoding="UTF-8"? Configuration status="debug" strict="true" name="XMLConfigTest" packages="org.apache.logging.log4j.test" Properties Property name="filename"target/test.log/Property /Properties Filter type="ThresholdFilter" level="trace"/ Appenders Appender type="Console" name="STDOUT" Layout type="PatternLayout" pattern="%m MDC%X%n"/ Filters Filter type="MarkerFilter" marker="FLOW" onMatch="DENY" onMismatch="NEUTRAL"/ Filter type="MarkerFilter" marker="EXCEPTION" onMatch="DENY" onMismatch="ACCEPT"/ /Filters /Appender Appender type="Console" name="FLOW" Layout type="PatternLayout" pattern="%C{1}.%M %m %ex%n"/!-- class and line number -- Filters Filter type="MarkerFilter" marker="FLOW" onMatch="ACCEPT" onMismatch="NEUTRAL"/ Filter type="MarkerFilter" marker="EXCEPTION" onMatch="ACCEPT" onMismatch="DENY"/ /Filters /Appender Appender type="File" name="File" fileName="${filename}" Layout type="PatternLayout" Pattern%d %p %C{1.} [%t] %m%n/Pattern /Layout /Appender /Appenders Loggers Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false" Filter type="ThreadContextMapFilter" KeyValuePair key="test" value="123"/ /Filter AppenderRef ref="STDOUT"/ /Logger Logger name="org.apache.logging.log4j.test2" level="debug" additivity="false" AppenderRef ref="File"/ /Logger Root level="trace" AppenderRef ref="STDOUT"/ /Root /Loggers /Configuration?xml version=”1.0” encoding=”UTF-8”?
Configuration status=”debug” strict=”true” name=”XMLConfigTest”
packages=”org.apache.logging.log4j.test”
Properties
Property name=”filename”target/test.log/Property
/Properties
Filter type=”ThresholdFilter” level=”trace”/Appenders
Appender type=”Console” name=”STDOUT”
Layout type=”PatternLayout” pattern=”%m MDC%X%n”/
Filters
Filter type=”MarkerFilter” marker=”FLOW” onMatch=”DENY” onMismatch=”NEUTRAL”/
Filter type=”MarkerFilter” marker=”EXCEPTION” onMatch=”DENY” onMismatch=”ACCEPT”/
/Filters
/Appender
Appender type=”Console” name=”FLOW”
Layout type=”PatternLayout” pattern=”%C{1}.%M %m %ex%n”/!– class and line number –
Filters
Filter type=”MarkerFilter” marker=”FLOW” onMatch=”ACCEPT” onMismatch=”NEUTRAL”/
Filter type=”MarkerFilter” marker=”EXCEPTION” onMatch=”ACCEPT” onMismatch=”DENY”/
/Filters
/Appender
Appender type=”File” name=”File” fileName=”${filename}”
Layout type=”PatternLayout”
Pattern%d %p %C{1.} [%t] %m%n/Pattern
/Layout
/Appender
/AppendersLoggers
Logger name=”org.apache.logging.log4j.test1” level=”debug” additivity=”false”
Filter type=”ThreadContextMapFilter”
KeyValuePair key=”test” value=”123”/
/Filter
AppenderRef ref=”STDOUT”/
/LoggerLogger name=”org.apache.logging.log4j.test2” level=”debug” additivity=”false”
AppenderRef ref=”File”/
/LoggerRoot level=”trace”
AppenderRef ref=”STDOUT”/
/Root
/Loggers/Configuration
logback 配置
configuration``
作用:
configuration
是 logback 配置文件的根元素。要点:它有
appender
、logger
、root
三个子元素。appender``
作用:将记录日志的任务委托给名为 appender 的组件。
要点:可以配置零个或多个;它有
file
、filter
、layout
、encoder
四个子元素。属性:
- name:设置 appender 名称。
- class:设置具体的实例化类。
file``
作用:设置日志文件路径。
filter``
作用:设置过滤器。
要点:可以配置零个或多个。
layout``
作用:设置 appender。
要点:可以配置零个或一个。
属性:
class:设置具体的实例化类。 encoder``
作用:设置编码。
要点:可以配置零个或多个。
属性:
class:设置具体的实例化类。
logger``
作用:设置 logger。
要点:可以配置零个或多个。
属性:
- name
- level:设置日志级别。不区分大小写。可选值:TRACE、DEBUG、INFO、WARN、ERROR、ALL、OFF。
- additivity:可选值:true 或 false。
appender-ref``
作用:appender 引用。
要点:可以配置零个或多个。
root``
作用:设置根 logger。
要点:只能配置一个;除了 level,不支持任何属性。level 属性和
logger
中的相同;有一个子元素appender-ref
,与logger
中的相同。完整的 logback.xml 参考示例
在下面的配置文件中,我为自己的项目代码(根目录:org.zp.notes.spring)设置了五种等级:
TRACE、DEBUG、INFO、WARN、ERROR,优先级依次从低到高。
因为关注 spring 框架本身的一些信息,我增加了专门打印 spring WARN 及以上等级的日志。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 ?xml version="1.0" encoding="UTF-8" ? !-- logback中一共有5种有效级别,分别是TRACE、DEBUG、INFO、WARN、ERROR,优先级依次从低到高 -- configuration scan="true" scanPeriod="60 seconds" debug="false" property name="DIR_NAME" value="spring-helloworld"/ !-- 将记录日志打印到控制台 -- appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender" encoder pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern /encoder /appender !-- RollingFileAppender begin -- appender name="ALL" class="ch.qos.logback.core.rolling.RollingFileAppender" !-- 根据时间来制定滚动策略 -- rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" fileNamePattern${user.dir}/logs/${DIR_NAME}/all.%d{yyyy-MM-dd}.log/fileNamePattern maxHistory30/maxHistory /rollingPolicy !-- 根据文件大小来制定滚动策略 -- triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy" maxFileSize30MB/maxFileSize /triggeringPolicy encoder pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern /encoder /appender appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender" !-- 根据时间来制定滚动策略 -- rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" fileNamePattern${user.dir}/logs/${DIR_NAME}/error.%d{yyyy-MM-dd}.log/fileNamePattern maxHistory30/maxHistory /rollingPolicy !-- 根据文件大小来制定滚动策略 -- triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy" maxFileSize10MB/maxFileSize /triggeringPolicy filter class="ch.qos.logback.classic.filter.LevelFilter" levelERROR/level onMatchACCEPT/onMatch onMismatchDENY/onMismatch /filter encoder pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern /encoder /appender appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender" !-- 根据时间来制定滚动策略 -- rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" fileNamePattern${user.dir}/logs/${DIR_NAME}/warn.%d{yyyy-MM-dd}.log/fileNamePattern maxHistory30/maxHistory /rollingPolicy !-- 根据文件大小来制定滚动策略 -- triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy" maxFileSize10MB/maxFileSize /triggeringPolicy filter class="ch.qos.logback.classic.filter.LevelFilter" levelWARN/level onMatchACCEPT/onMatch onMismatchDENY/onMismatch /filter encoder pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern /encoder /appender appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender" !-- 根据时间来制定滚动策略 -- rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" fileNamePattern${user.dir}/logs/${DIR_NAME}/info.%d{yyyy-MM-dd}.log/fileNamePattern maxHistory30/maxHistory /rollingPolicy !-- 根据文件大小来制定滚动策略 -- triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy" maxFileSize10MB/maxFileSize /triggeringPolicy filter class="ch.qos.logback.classic.filter.LevelFilter" levelINFO/level onMatchACCEPT/onMatch onMismatchDENY/onMismatch /filter encoder pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern /encoder /appender appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender" !-- 根据时间来制定滚动策略 -- rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" fileNamePattern${user.dir}/logs/${DIR_NAME}/debug.%d{yyyy-MM-dd}.log/fileNamePattern maxHistory30/maxHistory /rollingPolicy !-- 根据文件大小来制定滚动策略 -- triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy" maxFileSize10MB/maxFileSize /triggeringPolicy filter class="ch.qos.logback.classic.filter.LevelFilter" levelDEBUG/level onMatchACCEPT/onMatch onMismatchDENY/onMismatch /filter encoder pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern /encoder /appender appender name="TRACE" class="ch.qos.logback.core.rolling.RollingFileAppender" !-- 根据时间来制定滚动策略 -- rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" fileNamePattern${user.dir}/logs/${DIR_NAME}/trace.%d{yyyy-MM-dd}.log/fileNamePattern maxHistory30/maxHistory /rollingPolicy !-- 根据文件大小来制定滚动策略 -- triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy" maxFileSize10MB/maxFileSize /triggeringPolicy filter class="ch.qos.logback.classic.filter.LevelFilter" levelTRACE/level onMatchACCEPT/onMatch onMismatchDENY/onMismatch /filter encoder pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern /encoder /appender appender name="SPRING" class="ch.qos.logback.core.rolling.RollingFileAppender" !-- 根据时间来制定滚动策略 -- rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" fileNamePattern${user.dir}/logs/${DIR_NAME}/springframework.%d{yyyy-MM-dd}.log /fileNamePattern maxHistory30/maxHistory /rollingPolicy !-- 根据文件大小来制定滚动策略 -- triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy" maxFileSize10MB/maxFileSize /triggeringPolicy encoder pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern /encoder /appender !-- RollingFileAppender end -- !-- logger begin -- !-- 本项目的日志记录,分级打印 -- logger name="org.zp.notes.spring" level="TRACE" additivity="false" appender-ref ref="STDOUT"/ appender-ref ref="ERROR"/ appender-ref ref="WARN"/ appender-ref ref="INFO"/ appender-ref ref="DEBUG"/ appender-ref ref="TRACE"/ /logger !-- SPRING框架日志 -- logger name="org.springframework" level="WARN" additivity="false" appender-ref ref="SPRING"/ /logger root level="TRACE" appender-ref ref="ALL"/ /root !-- logger end -- /configuration?xml version=”1.0” encoding=”UTF-8” ?
!– logback中一共有5种有效级别,分别是TRACE、DEBUG、INFO、WARN、ERROR,优先级依次从低到高 –
configuration scan=”true” scanPeriod=”60 seconds” debug=”false”property name=”DIR_NAME” value=”spring-helloworld”/
!– 将记录日志打印到控制台 –
appender name=”STDOUT” class=”ch.qos.logback.core.ConsoleAppender”
encoder
pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern
/encoder
/appender!– RollingFileAppender begin –
appender name=”ALL” class=”ch.qos.logback.core.rolling.RollingFileAppender”
!– 根据时间来制定滚动策略 –
rollingPolicy class=”ch.qos.logback.core.rolling.TimeBasedRollingPolicy”
fileNamePattern${user.dir}/logs/${DIR_NAME}/all.%d{yyyy-MM-dd}.log/fileNamePattern
maxHistory30/maxHistory
/rollingPolicy!– 根据文件大小来制定滚动策略 –
triggeringPolicy class=”ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy”
maxFileSize30MB/maxFileSize
/triggeringPolicyencoder
pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern
/encoder
/appenderappender name=”ERROR” class=”ch.qos.logback.core.rolling.RollingFileAppender”
!– 根据时间来制定滚动策略 –
rollingPolicy class=”ch.qos.logback.core.rolling.TimeBasedRollingPolicy”
fileNamePattern${user.dir}/logs/${DIR_NAME}/error.%d{yyyy-MM-dd}.log/fileNamePattern
maxHistory30/maxHistory
/rollingPolicy!– 根据文件大小来制定滚动策略 –
triggeringPolicy class=”ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy”
maxFileSize10MB/maxFileSize
/triggeringPolicyfilter class=”ch.qos.logback.classic.filter.LevelFilter”
levelERROR/level
onMatchACCEPT/onMatch
onMismatchDENY/onMismatch
/filterencoder
pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern
/encoder
/appenderappender name=”WARN” class=”ch.qos.logback.core.rolling.RollingFileAppender”
!– 根据时间来制定滚动策略 –
rollingPolicy class=”ch.qos.logback.core.rolling.TimeBasedRollingPolicy”
fileNamePattern${user.dir}/logs/${DIR_NAME}/warn.%d{yyyy-MM-dd}.log/fileNamePattern
maxHistory30/maxHistory
/rollingPolicy!– 根据文件大小来制定滚动策略 –
triggeringPolicy class=”ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy”
maxFileSize10MB/maxFileSize
/triggeringPolicyfilter class=”ch.qos.logback.classic.filter.LevelFilter”
levelWARN/level
onMatchACCEPT/onMatch
onMismatchDENY/onMismatch
/filterencoder
pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern
/encoder
/appenderappender name=”INFO” class=”ch.qos.logback.core.rolling.RollingFileAppender”
!– 根据时间来制定滚动策略 –
rollingPolicy class=”ch.qos.logback.core.rolling.TimeBasedRollingPolicy”
fileNamePattern${user.dir}/logs/${DIR_NAME}/info.%d{yyyy-MM-dd}.log/fileNamePattern
maxHistory30/maxHistory
/rollingPolicy!– 根据文件大小来制定滚动策略 –
triggeringPolicy class=”ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy”
maxFileSize10MB/maxFileSize
/triggeringPolicyfilter class=”ch.qos.logback.classic.filter.LevelFilter”
levelINFO/level
onMatchACCEPT/onMatch
onMismatchDENY/onMismatch
/filterencoder
pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern
/encoder
/appenderappender name=”DEBUG” class=”ch.qos.logback.core.rolling.RollingFileAppender”
!– 根据时间来制定滚动策略 –
rollingPolicy class=”ch.qos.logback.core.rolling.TimeBasedRollingPolicy”
fileNamePattern${user.dir}/logs/${DIR_NAME}/debug.%d{yyyy-MM-dd}.log/fileNamePattern
maxHistory30/maxHistory
/rollingPolicy!– 根据文件大小来制定滚动策略 –
triggeringPolicy class=”ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy”
maxFileSize10MB/maxFileSize
/triggeringPolicyfilter class=”ch.qos.logback.classic.filter.LevelFilter”
levelDEBUG/level
onMatchACCEPT/onMatch
onMismatchDENY/onMismatch
/filterencoder
pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern
/encoder
/appenderappender name=”TRACE” class=”ch.qos.logback.core.rolling.RollingFileAppender”
!– 根据时间来制定滚动策略 –
rollingPolicy class=”ch.qos.logback.core.rolling.TimeBasedRollingPolicy”
fileNamePattern${user.dir}/logs/${DIR_NAME}/trace.%d{yyyy-MM-dd}.log/fileNamePattern
maxHistory30/maxHistory
/rollingPolicy!– 根据文件大小来制定滚动策略 –
triggeringPolicy class=”ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy”
maxFileSize10MB/maxFileSize
/triggeringPolicyfilter class=”ch.qos.logback.classic.filter.LevelFilter”
levelTRACE/level
onMatchACCEPT/onMatch
onMismatchDENY/onMismatch
/filterencoder
pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern
/encoder
/appenderappender name=”SPRING” class=”ch.qos.logback.core.rolling.RollingFileAppender”
!– 根据时间来制定滚动策略 –
rollingPolicy class=”ch.qos.logback.core.rolling.TimeBasedRollingPolicy”
fileNamePattern${user.dir}/logs/${DIR_NAME}/springframework.%d{yyyy-MM-dd}.log
/fileNamePattern
maxHistory30/maxHistory
/rollingPolicy!– 根据文件大小来制定滚动策略 –
triggeringPolicy class=”ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy”
maxFileSize10MB/maxFileSize
/triggeringPolicyencoder
pattern%d{HH:mm:ss.SSS} [%thread] [%-5p] %c{36}.%M - %m%n/pattern
/encoder
/appender
!– RollingFileAppender end –!– logger begin –
!– 本项目的日志记录,分级打印 –
logger name=”org.zp.notes.spring” level=”TRACE” additivity=”false”
appender-ref ref=”STDOUT”/
appender-ref ref=”ERROR”/
appender-ref ref=”WARN”/
appender-ref ref=”INFO”/
appender-ref ref=”DEBUG”/
appender-ref ref=”TRACE”/
/logger!– SPRING框架日志 –
logger name=”org.springframework” level=”WARN” additivity=”false”
appender-ref ref=”SPRING”/
/loggerroot level=”TRACE”
appender-ref ref=”ALL”/
/root
!– logger end –/configuration
log4j 配置
完整的 log4j.xml 参考示例
log4j 的配置文件一般有 xml 格式或 properties 格式。这里为了和 logback.xml 做个对比,就不介绍 properties 了,其实也没太大差别。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546 ?xml version="1.0" encoding="UTF-8"? !DOCTYPE log4j:configuration SYSTEM "log4j.dtd" log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' appender name="STDOUT" class="org.apache.log4j.ConsoleAppender" layout class="org.apache.log4j.PatternLayout" param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] [%t] %c{36}.%M - %m%n"/ /layout !--过滤器设置输出的级别-- filter class="org.apache.log4j.varia.LevelRangeFilter" param name="levelMin" value="debug"/ param name="levelMax" value="fatal"/ param name="AcceptOnMatch" value="true"/ /filter /appender appender name="ALL" class="org.apache.log4j.DailyRollingFileAppender" param name="File" value="${user.dir}/logs/spring-common/jcl/all"/ param name="Append" value="true"/ !-- 每天重新生成日志文件 -- param name="DatePattern" value="'-'yyyy-MM-dd'.log'"/ !-- 每小时重新生成日志文件 -- !--param name="DatePattern" value="'-'yyyy-MM-dd-HH'.log'"/-- layout class="org.apache.log4j.PatternLayout" param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] [%t] %c{36}.%M - %m%n"/ /layout /appender !-- 指定logger的设置,additivity指示是否遵循缺省的继承机制-- logger name="org.zp.notes.spring" additivity="false" level value="error"/ appender-ref ref="STDOUT"/ appender-ref ref="ALL"/ /logger !-- 根logger的设置-- root level value="warn"/ appender-ref ref="STDOUT"/ /root /log4j:configuration?xml version=”1.0” encoding=”UTF-8”?
!DOCTYPE log4j:configuration SYSTEM “log4j.dtd”log4j:configuration xmlns:log4j=’http://jakarta.apache.org/log4j/'
appender name=”STDOUT” class=”org.apache.log4j.ConsoleAppender”
layout class=”org.apache.log4j.PatternLayout”
param name=”ConversionPattern”
value=”%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] [%t] %c{36}.%M - %m%n”/
/layout!–过滤器设置输出的级别–
filter class=”org.apache.log4j.varia.LevelRangeFilter”
param name=”levelMin” value=”debug”/
param name=”levelMax” value=”fatal”/
param name=”AcceptOnMatch” value=”true”/
/filter
/appenderappender name=”ALL” class=”org.apache.log4j.DailyRollingFileAppender”
param name=”File” value=”${user.dir}/logs/spring-common/jcl/all”/
param name=”Append” value=”true”/
!– 每天重新生成日志文件 –
param name=”DatePattern” value=”‘-‘yyyy-MM-dd’.log’”/
!– 每小时重新生成日志文件 –
!–param name=”DatePattern” value=”‘-‘yyyy-MM-dd-HH’.log’”/–
layout class=”org.apache.log4j.PatternLayout”
param name=”ConversionPattern”
value=”%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] [%t] %c{36}.%M - %m%n”/
/layout
/appender!– 指定logger的设置,additivity指示是否遵循缺省的继承机制–
logger name=”org.zp.notes.spring” additivity=”false”
level value=”error”/
appender-ref ref=”STDOUT”/
appender-ref ref=”ALL”/
/logger!– 根logger的设置–
root
level value=”warn”/
appender-ref ref=”STDOUT”/
/root
/log4j:configuration参考
http://www.slf4j.org/manual.html http://logback.qos.ch/ http://logging.apache.org/log4j/1.2/ http://commons.apache.org/proper/commons-logging/ http://blog.csdn.net/yycdaizi/article/details/8276265
原文始发于微信公众号(Java知音):细说 Java 主流日志工具库