slf4j是一系列的日志接口,而log4j logback是具体实现了的日志框架。slf4j译为简单日志门面(The Simple Logging Facade for Java ),是日志框架的抽象。而log4j和logback是众多日志框架中的几种。也就是说我们在具体开发中,需要绑定一个日志框架,才能正常的使用slf4j。
而log4j和logback就是两个受欢迎的日志框架。
- log4j是apache实现的一个开源日志组件。(Wrapped implementations)
- logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架。是slf4j的原生实现。(Native implementations)
log4j例子:
pom.xml中添加:
<!-- log4j support -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
添加log4j.properties:
对于Java app, log4j.properties文件放在 project/classes/ 目录。
对于Java web applications, log4j.properties文件放在 WEB-INF/classes/或src/main/resource/ 目录。
1.根日志的级别定义为 DEBUG,并将名为 stdout,D,E 的 appender 添加其上。
log4j.rootLogger = debug,stdout,D,E
2.将名为 stdout,D,E 的 appender 设置为合法的 appender。
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
3.设置 appender stdout,D,E 的 layout。
完整例子:
### 设置###
log4j.rootLogger = debug,stdout,D,E
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
### 输出DEBUG 级别以上的日志到=/home/duqi/logs/debug.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = /home/duqi/logs/debug.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 输出ERROR 级别以上的日志到=/home/admin/logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =/home/admin/logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
使用:
日志分别记录到了控制台(三条),debug.log(两条)和error.log(一条)。
public class Log4JTest {
private static final Logger logger = LoggerFactory.getLogger(Log4JTest.class);
public static void main(String[] args) {
// 记录debug级别的信息
logger.debug("This is debug message.");
// 记录info级别的信息
logger.info("This is info message.");
// 记录error级别的信息
logger.error("This is error message.");
/*try{
obj.divide();
}catch(ArithmeticException ex){
logger.error("Sorry, something wrong!", ex);
}*/
}
配置文件:
log4j.rootLogger = [ level ] , appenderName, appenderName, …
日志级别从低到高为:ALL,TRACE,DEBUG,INFO,WARN,ERROR,FATAL。比如定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。如果不在appender中过滤自己的level(大于等于root level),默认使用rootLogger的level。
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
Log4j提供的appender有以下几种:
- org.apache.log4j.ConsoleAppender(控制台),
- org.apache.log4j.FileAppender(文件),
- org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
- org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
- org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
log4j.appender.D.layout = org.apache.log4j.PatternLayout
Appender的layout有以下几种:
- org.apache.log4j.HTMLLayout(以HTML表格形式布局),
- org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
- org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
- org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
记录Mybatis语句:
如果你的应用部署在一个包含Commons Logging的环境(如:Tomcat,Websphere), 而你又想用其他的日志框架,你可以通过在MyBatis的配置文件mybatis-config.xml里面添加一项setting(配置)来选择一个不同的日志实现。
在ApplicationConetxt.xml中:
<configuration>
<properties>
<property name="dialect" value="mysql" />
</properties>
<settings>
<setting name="logImpl" value="LOG4J" />
</settings>
</configuration>
log4j.properties:
log4j.rootLogger=info,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] -%m%n
# 打印sql语句:debug; 执行结果:trace
## 指定mapper配置文件中的namespace
log4j.logger.MyMapperNS =TRACE
mapper的配置文件:
<mapper namespace="MyMapperNS.user">
<select id="selectUser" parameterType="int" resultType="User">
<![CDATA[
select * from user where id = #{id}
]]>
</select>
</mapper>
你也可以只记录一个方法:log4j.logger.org.mybatis.example.BlogMapper.user.selectUser=TRACE
与此相对,可以对一组mapper接口记录日志,只要对mapper接口所在的包开启日志功能即可:
log4j.logger.MyMapperNS=TRACE
某些查询可能会返回大量的数据,只想记录其执行的SQL语句该怎么办?为此,Mybatis中SQL语 句的日志级别被设为DEBUG(JDK Logging中为FINE),结果日志的级别为TRACE(JDK Logging中为FINER)。所以,只要将日志级别调整为DEBUG即可达到目的:
log4j.logger.MyMapperNS=DEBUG
logback例子:
pom.xml添加依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.13</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.7</version>
</dependency>
用法和slf4j+logback一致:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SimpleDemo {
private static final Logger logger = LoggerFactory.getLogger(SimpleDemo.class);
public static void main(String[] args) {
logger.info("111");
logger.debug("222");
logger.error("3333");
logger.trace("4444");
}
}
配置文件logback.xml。文件须放下在 resources 根目录下,文件名不能修改:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 根标签 -->
<!-- 三个属性
scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="true" scanPeriod="30 seconds">
<!-- 用来全局定义变量值,它有两个属性name和value,通过<property>定义的值会被插入到logger上下文中,可以使“${}”来使用变量 -->
<!-- 日志文件保存路径 -->
<property name="logPath" value="d:\\log"/>
<!-- 子节点<appender>:负责写日志的组件,它有两个必要属性name和class。name指定appender名称,class指定appender的全限定名-->
<!-- ConsoleAppender 把日志输出到控制台,有以下子节点: -->
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。有以下子节点:
<file>:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。
<append>:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。
<rollingPolicy>:当发生滚动时,决定RollingFileAppender的行为,涉及文件移动和重命名。属性class定义具体的滚动策略类-->
<!-- 记录日志文件 -->
<appender name="testLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${logPath}/test.log</file>
<append>true</append>
<!-- class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy": 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。有以下子节点:
<fileNamePattern>:必要节点,包含文件名及“%d”转换符,“%d”可以包含一个java.text.SimpleDateFormat指定的时间格式,如:%d{yyyy-MM}。
如果直接使用 %d,默认格式是 yyyy-MM-dd。RollingFileAppender的file字节点可有可无,通过设置file,可以为活动文件和归档文件指定不同位置,当前日志总是记录到file指定的文件(活动文件),活动文件的名字不会改变;
如果没设置file,活动文件的名字会根据fileNamePattern 的值,每隔一段时间改变一次。“/”或者“\”会被当做目录分隔符。
-->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${logPath}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!-- <maxHistory>可选节点,
控制保留的归档文件的最大数量,超出数量就删除旧文件。
假设设置每个月滚动,且<maxHistory>是6,则只保存最近6个月的文件,删除之前的旧文件。
注意,删除旧文件是,那些为了归档而创建的目录也会被删除。
-->
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<!--
<encoder>:对记录事件进行格式化。负责两件事,一是把日志信息转换成字节数组,二是把字节数组写入到输出流。
PatternLayoutEncoder 是唯一有用的且默认的encoder ,
有一个<pattern>节点,用来设置日志的输入格式。使用“%”加“转换符”方式,如果要输出“%”,则必须用“\”对“\%”进行转义。
-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!--
子节点<loger>:用来设置某一个包或具体的某一个类的日志打印级别、以及指定<appender>。
<loger>仅有一个name属性,一个可选的level和一个可选的addtivity属性。
可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个loger
name: 用来指定受此loger约束的某一个包或者具体的某一个类。
level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。 如果未设置此属性,那么当前loger将会继承上级的级别。
addtivity: 是否向上级loger传递打印信息。默认是true。同<loger>一样,可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个loger。
-->
<logger name="testLog" additivity="false" level="INFO">
<appender-ref ref="STDOUT" />//大小写敏感,和appender的name一致
<appender-ref ref="testLogAppender" />
</logger>
<!--
子节点<root>:它也是<loger>元素,但是它是根loger,是所有<loger>的上级。
只有一个level属性,因为name已经被命名为"root",且已经是最上级了。
level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL和OFF,
不能设置为INHERITED或者同义词NULL。 默认是DEBUG。
-->
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
其他:
避免重复打印日志,浪费磁盘空间,务必在log4j.xml中设置additivity=false。additivity默认为true,即通过该logger输出的日志会同时输出到root logger,如果还为该logger指定了独立的appender,就会导致这部分日志重复输出。
异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么通过关键字throws往上抛出。
正例:
logger.error(各类参数或者对象toString + "_" + e.getMessage(), e);
记录异常日志的常见错误:
logger.error(e);
logger.error(e.getMessage());
logger.error("上下文"+e.getMessage());
上面这几种都是错的!请确保使用的是两个入参的API,如error(String s, Throwable t)。
参考:
https://mengkang.net/594.html
http://www.jianshu.com/p/c6c543e4975e
http://wiki.jikexueyuan.com/project/log4j/logging-files.html
https://www.mkyong.com/logging/log4j-hello-world-example/