日志记录---log4j详解
通常的日志记录的缺点是会减慢程序的运行速度,如果用普通的System.out的话影响视觉效果,另外解耦度也不好,而log4j的设计则使得日志记录变得可靠快速和可拓展性好。
log4j是用文件来配置的,学习曲线低。
Log4j有三个组件: loggers(日志写出器,供程序员输出日志信息), appenders(日志输出地) 和layouts(展现方式)。这三个组件是一块工作的,使开发者通过日志类型和日志等级记录日志,同时使得这些日志格式化。
log4j类图

- Logger - 日志写出器,供程序员输出日志信息
- Appender - 日志目的地,把格式化好的日志信息输出到指定的地方去
- ConsoleAppender - 目的地为控制台的
- AppenderFileAppender - 目的地为文件的
- AppenderRollingFileAppender - 目的地为大小受限的文件的Appender
- Layout - 日志格式化器,用来把程序员的logging request格式化成字符串
- PatternLayout - 用指定的pattern格式化logging request的Layout
java是java.util的父亲,是java.util.vector的祖先
root logger一般在log树的顶端,一般是不存在的,也不能通过名字来获取,但是可以调用 static Logger.getRootLogger来获取,通过调用public static Logger Logger.getLogger(String name)或者public static Logger Logger.getLogger(Class clazz)获得(或者创建)一个named logger。后者相当于调用Logger.getLogger(clazz.getName())。在某对象中,用该对象所属的类为参数,调用Logger.getLogger(Class clazz)以获得logger被认为是目前所知的最理智的命名logger的方法。
package org.apache.log4j;
public class Logger {
// Creation & retrieval methods:
public static Logger getRootLogger();
public static Logger getLogger(String name);
// printing methods:
public void trace(Object message);
public void debug(Object message);
public void info(Object message);
public void warn(Object message);
public void error(Object message);
public void fatal(Object message);
// generic printing method:
public void log(Level l, Object message);
}
level预定义了5个等级DEBUG,INFO,WARN,ERROR和FATAL。
日志级别为:ALL<DEBUG<INFO<WARN<ERROR<FATAL<OFF。定义在org.apache.log4j.Level这个类中,如果一个给定的loger没有指定等级,会继承最近的一个祖先然后得到一个等级。
为了确保所有的logger可以继承一个等级,root logger一定有一个分配好的等级,如果一个logger没有设置最低等级,会继承直接父logger的最低等级。如果所有的logger都分配好了等级,那么就不需要等级继承了。
每条输出到logger的日志请求(logging request)也都有一个level,如果该request的level大于等于该logger的level,则该request将被处理(称为enabled);否则该request将被忽略。故可得知:
- logger的level越低,表示该logger越详细
- logging request的level越高,表示该logging request越优先输出
一个输出的目的地叫appender,当前而已,appender 主要存在于console, file等。一个logger里面可以添加多个appender。
对于Appender的继承:一个Logger除了配置给它的Appender之外,它会继承它所有父Logger的Appender,除非它的Additivity属性设为false。看表
| Logger Name |
Added Appenders |
Additivity Flag |
Output Targets | Comment |
|---|---|---|---|---|
| root | A1 | not applicable | A1 | The root logger is anonymous but can be accessed with the Logger.getRootLogger() method. There is no default appender attached to root. |
| x | A-x1, A-x2 | true | A1, A-x1, A-x2 | Appenders of "x" and root. |
| x.y | none | true | A1, A-x1, A-x2 | Appenders of "x" and root. |
| x.y.z | A-xyz1 | true | A1, A-x1, A-x2, A-xyz1 | Appenders in "x.y.z", "x" and root. |
| security | A-sec | false | A-sec | No appender accumulation since the additivity flag is set to false. |
| security.access | none | true | A-sec | Only appenders of "security" because the additivity flag in "security" is set to false. |
ConsoleAppender可以使用ConsoleAppender对象把日志输出到控制台。
// Log4j APIs : class ConsoleAppender extends WriterAppender // 构造方法,使用一个Layout对象构造一个ConsoleAppender对象
// 默认情况下,ConsoleAppender的target是System.out
public ConsoleAppender(Layout layout); // 构造方法,使用一个Layout对象和一个target字符串构造ConsoleAppender对象
// target的可能取值为ConsoleAppender.SYSTEM_OUT和ConsoleAppender.SYSTEM_ERR
public ConsoleAppender(Layout layout, String target);
FileAppender可以使用FileAppender对象把日志输出到一个指定的日志文件中去。
/ Log4j APIs : class FileAppender extends WriterAppender // 构造方法,使用一个Layout对象和日志文件名构造一个FileAppender对象
public FileAppender(Layout layout, String filename)
throws IOException;
public FileAppender(Layout layout, String filename, boolean append)
throws IOException;
RollingFileAppender可以使用FileAppender的子类RollingFileAppender对象,把日志输出到一个指定的日志文件中。不同的是该日志文件的大 小受到限制,当日志内容超出最大的尺寸时,该文件将向上滚动(最老的日志被擦除)。还可以在该类对象中指定为日志文件做多少个备份。
// Log4j APIs : class RollingFileAppender extends FileAppender // 构造方法,使用一个Layout对象和日志文件名构造一个RollingFileAppender对象
public RollingFileAppender(Layout layout, String filename)
throws IOException;
public RollingFileAppender(Layout layout, String filename, boolean append)
throws IOException; // 获得和设置日志备份文件的个数
public int getMaxBackupIndex();
public void setMaxBackupIndex(int index); // 获得和设置滚动日志文件的最大尺寸
public long getMaximumFileSize();
public void setMaximumFileSize(long size);
org.apache.log4j.PatternLayout主要是设置输出的格式。设置详细地址为:http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html
| 参数 | 说明 | 例子 | |
|---|---|---|---|
| %c | 列出logger名字空间的全称,如果加上{<层数>}表示列出从最内层算起的指定层数的名字空间 | log4j配置文件参数举例 | 输出显示媒介 |
| 假设当前logger名字空间是"a.b.c" | |||
| %c | a.b.c | ||
| %c{2} | b.c | ||
| %20c | (若名字空间长度小于20,则左边用空格填充) | ||
| %-20c | (若名字空间长度小于20,则右边用空格填充) | ||
| %.30c | (若名字空间长度超过30,截去多余字符) | ||
| %20.30c | (若名字空间长度小于20,则左边用空格填充;若名字空间长度超过30,截去多余字符) | ||
| %-20.30c | (若名字空间长度小于20,则右边用空格填充;若名字空间长度超过30,截去多余字符) | ||
| %C | 列出调用logger的类的全名(包含包路径) | 假设当前类是"org.apache.xyz.SomeClass" | |
| %C | org.apache.xyz.SomeClass | ||
| %C{1} | SomeClass | ||
| %d | 显示日志记录时间,{<日期格式>}使用ISO8601定义的日期格式 | %d{yyyy/MM/dd HH:mm:ss,SSS} | 2005/10/12 22:23:30,117 |
| %d{ABSOLUTE} | 22:23:30,117 | ||
| %d{DATE} | 12 Oct 2005 22:23:30,117 | ||
| %d{ISO8601} | 2005-10-12 22:23:30,117 | ||
| %F | 显示调用logger的源文件名 | %F | MyClass.java |
| %l | 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数 | %l | MyClass.main(MyClass.java:129) |
| %L | 显示调用logger的代码行 | %L | 129 |
| %m | 显示输出消息 | %m | This is a message for debug. |
| %M | 显示调用logger的方法名 | %M | main |
| %n | 当前平台下的换行符 | %n | Windows平台下表示rn UNIX平台下表示n |
| %p | 显示该条日志的优先级 | %p | INFO |
| %r | 显示从程序启动时到记录该条日志时已经经过的毫秒数 | %r | 1215 |
| %t | 输出产生该日志事件的线程名 | %t | MyClass |
| %x | 按NDC(Nested Diagnostic Context,线程堆栈)顺序输出日志 | 假设某程序调用顺序是MyApp调用com.foo.Bar | |
| %c %x - %m%n | MyApp - Call com.foo.Bar. com.foo.Bar - Log in Bar MyApp - Return to MyApp. |
||
| %X | 按MDC(Mapped Diagnostic Context,线程映射表)输出日志。通常用于多个客户端连接同一台服务器,方便服务器区分是那个客户端访问留下来的日志。 | %X{5} | (记录代号为5的客户端的日志) |
| %% | 显示一个百分号 | %% | % |
PatternLayout是Layout的一个子类,用来使用类似C语言的printf函数中使用的格式控制字符串来控制日志的输出格式。
// Log4j APIs : class PatternLayout extends Layout // 无参数构造方法,使用DEFAULT_CONVERSION_PATTERN构造一个PatternLayout
// 注意:DEFAULT_CONVERSION_PATTERN为"%m%n",只打印消息信息
public PatternLayout(); // 构造方法,使用自定义的pattern构造一个PatternLayout
public PatternLayout(String pattern); // 获得和设置PatternLayout对象的日志pattern
public String getConversionPattern();
public void setConversionPattern(String pattern);
举个例子
#log4j config
log4j.rootLogger=DEBUG,OUTPUT log4j.appender.OUTPUT.layout=org.apache.log4j.PatternLayout
log4j.appender.OUTPUT.layout.ConversionPattern=%d{DATE} %-4r [%t] %-5p %c %x - %m%n
则输出的可能是
12 Oct 2005 22:23:30,117 0 [main] INFO MyApp - Entering application
对log4j环境的配置就是对root logger的配置,包括把root logger设置为哪个级别(level);为它增加哪些appender,等等。这些可以通过设置系统属性的方法来隐式地完成,也可以在程序里调用 XXXConfigurator.configure()方法来显式地完成。
默认的log4j初始化过程
Logger类的静态初始化块(static initialization block)中对log4j的环境做默认的初始化。注意:如果程序员已经通过设置系统属性的方法来配置了log4j环境,则不需要再显式地调用XXXConfigurator.configure()方法来配置log4j环境了。
Logger的静态初始化块在完成初始化过程时将检查一系列log4j定义的系统属性。它所做的事情如下:
- 检查系统属性log4j.defaultInitOverride,如果该属性被设置为false,则执行初始化;否则(只要不是false,无论是什么值,甚至没有值,都是否)跳过初始化。
- 把系统属性log4j.configuration的值赋给变量resource。如果该系统变量没有被定义,则把resource赋值为"log4j.properties"。注意:在apache的log4j文档中建议使用定义log4j.configuration系统属性的方法来设置默认的初始化文件是一个好方法。
- 试图把resource变量转化成为一个URL对象url。如果一般的转化方法行不通,就调用org.apache.log4j.helpers.Loader.getResource(resource, Logger.class)方法来完成转化。
- 如果url以".xml"结尾,则调用方法DOMConfigurator.configure(url)来完成初始化;否则,则调用方法 PropertyConfigurator.configure(url)来完成初始化。如果url指定的资源不能被获得,则跳出初始化过程。
BasicConfigurator.configure()
BasicConfigurator.configure()方法使用最简的方法配置log4j环境。注:所谓配置log4j环境,就是指配置root logger,因为所有其它的logger都是root logger的后代,所以它们(默认情况下)都将继承root logger的性质。
BasicConfigurator.configure()完成的任务是:
- 用默认pattern创建PatternLayout对象p:
PatternLayout p = new PatternLayout("%-4r[%t]%-5p%c%x - %m%n"); - 用p创建ConsoleAppender对象a,目标是system.out,标准输出设备:
ConsoleAppender a = new ConsoleAppender(p,ConsoleAppender.SYSTEM_OUT); - 为root logger增加一个ConsoleAppender p:
rootLogger.addAppender(p);
- 用默认pattern创建PatternLayout对象p:
举个例子,两个类
package log.bar; import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger; public class MyApp {
static Logger log=Logger.getLogger(MyApp.class);
public static void main(String[] args) {
BasicConfigurator.configure();
log.info("Entering application.");
Bar bar = new Bar();
bar.doIt();
log.info("Exiting application.");
} }
package log;
import org.apache.log4j.Logger;
public class Bar {
static Logger log = Logger.getLogger(Bar.class);
public void doIt() {
log.debug("Did it again!");
}
}
输出结果为
0 [main] INFO log.MyApp - Entering application.
2 [main] DEBUG log.Bar - Did it again!
2 [main] INFO log.MyApp - Exiting application.
配置根Logger,其语法为:
log4j.rootLogger = [ level ] , appenderName, appenderName, …
appenderName就是指日志信息输出到哪个地方。您可以同时指定多个输出目的地。
输出到appender语句为:
log4j.appender.stdout(这个是自定义的AppenderName)=org.apache.log4j.ConsoleAppender
其中,Log4j提供的appender有
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
布局语句为
log4j.appender.stdout(这个是自定义的appenderName).layout=org.apache.log4j.PatternLayout(布局中的一个)
配置日志信息的格式(布局),其语法为:
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
格式化语句为
log4j.appender.stdout(自定义appenderName).layout.ConversionPattern=%d %p [%c:%L] - <%m>%n
设置为日志文件存储地址语句为
log4j.appender.logfile(自定义appenderName).File=/home/ismp/log/ismpweb.log(自定义地址)
例:
#log4j.rootCategory=DEBUG, stdout,logfile
#log4j.category.org.springframework=WARN,stdout,logfile
#log4j.category.net.sf.cindy=WARN,stdout,logfile
log4j.rootCategory=DEBUG, stdout log4j.logger.httpclient=error
log4j.logger.org.apache=error
log4j.category.org.springframework=error
log4j.category.net.sf.cindy=WARN,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c:%L] - <%m>%n log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.File=/home/ismp/log/ismpweb.log
log4j.appender.logfile.DatePattern=.yyyy-MM-dd
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c:%L] - <%m>%n
上面category已经废弃了,logger是category的子类,但废弃了也是可以用的。
log4j是专门用于打印日志信息的组件,通过配置可以把特定的日志信息通过指定的格式输出到指定的地方。
总结一下:
- Logger类:完成日志记录,设置日志信息级别
- Appender类:决定日志去向,终端、DB、硬盘
- Layout类:决定日志输出的样式,例如包含当前线程、行号、时间
log4j.rootLogger=日志级别,appender1, appender2, ….
- 日志级别:ALL<DEBUG<INFO<WARN<ERROR<FATAL<OFF,不区分大小写
- 注意,需在控制台输入,只需将其中一个appender定义为stdout即可
- 注意,rootLogger默认是对整个工程生效
- 注意,如果只想对某些包操作,那么:log4j.logger.com.hutu=info, stdout,表示该日志对package com.hutu生效
- 注意,这样做可以区分dev/线上,也可以减小性能影响:if(log.isDebugEnabled()){log.debug();}
log4j.appender.appender1=org.apache.log4j.日志输出到哪儿
- ConsoleAppender(控制台)
- FileAppender(文件)
- DailyRollingFileAppender(每天产生一个日志文件)
- RollingFileAppender(文件大小到达指定尺寸时产生一个新的文件)
- WriteAppender(将日志信息以流格式发送到任意指定的地方)
- JDBCAppender(将日志信息保存到数据库中)
log4j.appender.appender1.File=文件目录及文件
${user.home}/logs/...
log4j.appender.appender1.MaxFileSize=最大文件大小
log4j.appender.appender1.MaxBackupIndex=备份文件个数
- 其中,appender1是在第一行定义过的;
- 文件目录及文件,例如,/home/admin/logs/hutudan.log
- 最大文件大小,例如,100KB
- 备份文件个数,例如,1
log4j.appender.ServerDailyRollingFile.DatePattern=日志后缀格式
- 例如,'.'yyyy-MM-dd
log4j.appender.appender1.layout=org.apache.log4j.日志布局格式
- HTMLLayout(以HTML表格形式布局)
- SimpleLayout(包含日志信息的级别和信息字符串)
- TTCCLayout(包含日志产生的时间,执行绪,类别等信息)
- PatternLayout(可以灵活的指定布局格式,常用)
log4j.appender.appender1.layout.ConversionPattern=日志输出格式
- 例如,%d - %m%n或%d{yyyy-MM-dd HH:mm:ss} %p [%c] %m%n
- %c 输出日志信息所属的类的全名
- %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy-M-dd HH:mm:ss },输出类似:2002-10-18- 22:10:28
- %f 输出日志信息所属的类的类名
- %l 输出日志事件的发生位置,即输出日志信息的语句处于它所在的类的第几行
- %m 输出代码中指定的信息,如log(message)中的message
- %n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
- %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL。如果是调用debug()输出的,则为DEBUG,依此类推
- %r 输出自应用启动到输出该日志信息所耗费的毫秒数
- %t 输出产生该日志事件的线程名
- 可参考:http://blog.sina.com.cn/s/blog_4e4dd5570100qowy.html
log4j.appender.ServerDailyRollingFile.Append=true
例子:
log4j.rootLogger=debug, stdout
log4j.category.org.apache.zookeeper=error
log4j.category.org.springframework=error
log4j.category.org.hibernate=error
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c:%L] - %m%n
作者: lostblog
出处: http://www.cnblogs.com/jayit/>
关于作者:专注java服务器端开发,请多多赐教!
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 原文链接 如有问题, 可邮件(1073019917@qq.com)咨询.
日志记录---log4j详解的更多相关文章
- Java学习-007-Log4J 日志记录配置文件详解及实例源代码
此文主要讲述在初学 Java 时,常用的 Log4J 日志记录配置文件详解及实例源代码整理.希望能对初学 Java 编程的亲们有所帮助.若有不足之处,敬请大神指正,不胜感激!源代码测试通过日期为:20 ...
- nginx 日志记录 自定义详解(分析上报用)
nginx 日志记录 自定义详解 1.log_format 普通格式 log_format main '$remote_addr - $remote_user [$time_local] $req ...
- (4.7)mysql备份还原——深入解析二进制日志(3)binlog的三种日志记录模式详解
关键词:binlog模式,binlog,二进制日志,binlog日志 目录概述 0.binlog概述 查看binlog日志参数设置: show variables like '%log_bin%'; ...
- 《手把手教你》系列基础篇(八十六)-java+ selenium自动化测试-框架设计基础-Log4j实现日志输出(详解教程)
1.简介 自动化测试中如何输出日志文件.任何软件,都会涉及到日志输出.所以,在测试人员报bug,特别是崩溃的bug,一般都要提供软件产品的日志文件.开发通过看日志文件,知道这个崩溃产生的原因,至少知道 ...
- java log4j基本配置及日志级别配置详解
java log4j日志级别配置详解 1.1 前言 说出来真是丢脸,最近被公司派到客户公司面试外包开发岗位,本来准备了什么redis.rabbitMQ.SSM框架的相关面试题以及自己做过的一些项目回顾 ...
- 【转载】log4j详解使用
log4j详解 日志论 在应用程序中输出日志有有三个目的:(1)监视代码中变量的变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作. (2)跟踪代码运行进轨迹,作为日后审计的依据. ...
- log4j详解与实战
[转自] http://www.iteye.com/topic/378077 log4j是一个非常强大的log记录软件,下面我们就来看看在项目中如何使log4j. 首先当然是得到log4j的jar档, ...
- (转)nginx日志配置指令详解
这篇文章主要介绍了nginx日志配置指令详解,nginx有一个非常灵活的日志记录模式,每个级别的配置可以有各自独立的访问日志,需要的朋友可以参考下日志对于统计排错来说非常有利的.本文总结了nginx日 ...
- nginx日志配置指令详解
这篇文章主要介绍了nginx日志配置指令详解,nginx有一个非常灵活的日志记录模式,每个级别的配置可以有各自独立的访问日志,需要的朋友可以参考下日志对于统计排错来说非常有利的.本文总结了nginx日 ...
随机推荐
- link_to和其对应要跳转的的url,用path和直接路由方法
link_to和其对应要跳转的的url,用path和直接路由方法 看看link_to <% @order.each do |oo| %> <div> <%= oo.nam ...
- 谈API网关的背景、架构以及落地方案
Chris Richardson曾经在他的博客上详细介绍过API网关,包括API网关的背景.解决方案以及案例.对于大多数基于微服务的应用程序而言,API网关都应该是系统的入口,它会负责服务请求路由.组 ...
- stos
add <?php /* 添加脚本 参数:u=用户名 v=城市名 为用户添加城市标签 */ header("Content-Type:text/html; charset=utf-8& ...
- numpy得到数组的index
itemindex = numpy.where(array==item)
- 1077. Kuchiguse (20)【字符串处理】——PAT (Advanced Level) Practise
题目信息 1077. Kuchiguse (20) 时间限制100 ms 内存限制65536 kB 代码长度限制16000 B The Japanese language is notorious f ...
- 修改查看MYSQL字符集(charset)
From: http://www.cnblogs.com/fengqingtao/archive/2010/11/23/1885220.html 查看mysql的字符集 mysql> show ...
- 支付宝(移动支付)服务端java版
所需支付宝jar包: sdk2-2.0.jar(点击下载) 工具类目录结构: 点击下载 商户信息已经公钥私钥的配置(公钥私钥的生成与支付宝商户平台配置请看官方文档:https://doc.open ...
- (转)fiddler模拟post请求
转自:https://www.cnblogs.com/xiaoxi-3-/p/7612254.html 前言: Fiddler是一个简单的http协议调试代理工具,它界面友好,易于操作,是模拟http ...
- .Net中的序列化和反序列化详解
序列化通俗地讲就是将一个对象转换成一个字节流的过程,这样就可以轻松保存在磁盘文件或数据库中.反序列化是序列化的逆过程,就是将一个字节流转换回原来的对象的过程. 然而为什么需要序列化和反序列化这样的机制 ...
- mysql数据库binary log中的事件到底是什么?
需求描述: 最近看mysql备份恢复的时候,基于时间点恢复,提到了binary log中存的是"事件" 那么到底什么是事件呢 概念解释: binary log中存的是事件(even ...