尽管slf4j+logback看起来很不错。但是,由于自己熟悉的很多项目都还是用log4j。而且springmvc默认使用log4j。所以 自己还是学习总结下。
我习惯到官网去看资料学习使用。我觉得这样不会让我在众多转来转去文章中。搞得晕头转向,而不得要领。
log4j apache官网手册页面。
手册页上有一段话,吸引了我的注意。本来下午的时候,我还在想理由解释为什么要使用日志。下面这段话太经典了。
As Brian W. Kernighan and Rob Pike put it in their truly excellent book "The Practice of Programming"
/**
As personal choice, we tend not to use debuggers beyond getting a
stack trace or the value of a variable or two. One reason is that it
is easy to get lost in details of complicated data structures and
control flow; we find stepping through a program less productive
than thinking harder and adding output statements and self-checking
code at critical places. Clicking over statements takes longer than
scanning the output of judiciously-placed displays. It takes less
time to decide where to put print statements than to single-step to
the critical section of code, even assuming we know where that
is. More important, debugging statements stay with the program;
debugging sessions are transient.
**/
Log4j有三大主要组件:loggers,appends,layouts
这三种类型的组件协同工作使得开发者可以根据消息类型和级别来log信息,并可以在运行时指定信息如何格式化及输出到哪里。
一: Logger 的层次结构
Logger是具名实体,Logger名大小写敏感。遵循下面的规则。
如一个名为"com.foo.Bar"的Logger是一个名为"com.foo"的Logger的子Logger。
即"com.foo"Logger是"com.foo.Bar"的父Logger。
root Logger处于Logger层次结构的顶层。它有两个特殊的地方。
1. root Logger永远存在。
2. root Logger不能通过名字访问到。
通过类静态方法Logger.getRootLogger()可以访问root Logger。
所以其它的Logger实例可以通过类静态方法Logger.getLogger(String name)有过Logger名作为参数来获得。
//Logger类的outline如下
org.apache.log4j.Logger
org.apache.log4j.Logger.FQCN
org.apache.log4j.Logger.Logger(String)
org.apache.log4j.Logger.getLogger(String)
org.apache.log4j.Logger.getLogger(Class)
org.apache.log4j.Logger.getRootLogger()
org.apache.log4j.Logger.getLogger(String, LoggerFactory)
org.apache.log4j.Logger.trace(Object)
org.apache.log4j.Logger.trace(Object, Throwable)
org.apache.log4j.Logger.isTraceEnabled()
Logger的级别。
以下是Logger级别 Level类的outline
org.apache.log4j.Level
org.apache.log4j.Level.TRACE_INT
org.apache.log4j.Level.OFF
org.apache.log4j.Level.FATAL
org.apache.log4j.Level.ERROR
org.apache.log4j.Level.WARN
org.apache.log4j.Level.INFO
org.apache.log4j.Level.DEBUG
org.apache.log4j.Level.TRACE
org.apache.log4j.Level.ALL
org.apache.log4j.Level.serialVersionUID
org.apache.log4j.Level.Level(int, String, int)
org.apache.log4j.Level.toLevel(String)
org.apache.log4j.Level.toLevel(int)
org.apache.log4j.Level.toLevel(int, Level)
org.apache.log4j.Level.toLevel(String, Level)
org.apache.log4j.Level.readObject(ObjectInputStream)
org.apache.log4j.Level.writeObject(ObjectOutputStream)
org.apache.log4j.Level.readResolve()
上面outline的声明中,的顺序也是控制log输出的顺序。
Logger级别的继承:
一个名为C的Logger它的级别等于第一个在继承层级中非空的层级。
Logger的层次结构是一颗倒挂的树。Logger如果没有声明一个层级的话,会向上递归向上查找父Logger的层次并继承。
注意:以同一个名字调用getLogger(String name)方法会返回同一个logger对象。
二: Appenders
在log4j中一个Appender就是一个log信息输出目的地。
一个Logger可以对应多个Appender。
addAppendar()方法可以为Logger添加一个指定的Appender。
任何一个被接受的Logging请求都会被发送到Logger所有的Appendar中,以及继承自此层级的Appender中。(也就是说跟Logger的层级级别可以继承一样。Appender也可以)
注意可以通过设置一个Logger的Appender的additivity flag为false,来阻止logging请求消息向子appender传播。
Appenders接口的outline如下:
org.apache.log4j.Appender
org.apache.log4j.Appender.addFilter(Filter)
org.apache.log4j.Appender.getFilter()
org.apache.log4j.Appender.clearFilters()
org.apache.log4j.Appender.close()
org.apache.log4j.Appender.doAppend(LoggingEvent)
org.apache.log4j.Appender.getName()
org.apache.log4j.Appender.setErrorHandler(ErrorHandler)
org.apache.log4j.Appender.getErrorHandler()
org.apache.log4j.Appender.setLayout(Layout)
org.apache.log4j.Appender.getLayout()
org.apache.log4j.Appender.setName(String)
org.apache.log4j.Appender.requiresLayout()
三:Layouts
Appender来设置log消息输出的目的地。而Layouts则是用来设置输出的log消息的格式的。
可以通过为一个Appender关联一个Layout来完成这个目的。
PatternLayout是log4j的一个标准输出组件。它允许用户以类似于C语言printf风格的模式来指定输出样式。在log4j附加部分中有一个EnhancedPatternLayout。应该优先使用。
log4j的输出模式如下:
%[modifiers]conversion_char
即以一个百分号开头,带一个可选的修饰符和一个转换字符。
假设模式是“%-5p [%t]: %m%n"并且log4j的Layout选择是PatternLayout。
那么下面的代码
Category root = Category.getRoot();
root.debug("Message 1");
root.warn("Message 2");
将产生如下输出:
/**
DEBUG [main]: Message 1
WARN [main]: Message 2
**/
%-5p表示logging 事件的优先级应当以5个字符的宽度左对齐
关于配置的更多信息可以参与如下文章,此文章下面例出的其它文章也可以参考:
log4j详解与实战
根据org.apache.log4j.PatternLayout类的JavaDoc。
我简单概括下各种模式字符的用法:
%c{n} 输出loggineEvent的类别名。c后面跟以花括号括住的精确符例如类别名"a.b.c"模式名%c{2}将会输出"b.c"
%C{n} 同上作用于类别,警告:此模式字符会影响性能。
%d{SimpleDateFormat} 用于输出日志产生时间。日期格式化模式用java中的SimpleDateFormat类。
%F 输出首先log请求的文件名。警告:会影响性能。
%I 输出产生log的调用位置。位置log取决于JVM实现,但通包括调用方法的全称。注意:这种log很有用。但是会更大的影响性能。
%L 输出产生log的代码行。 警告:严重影响性能
%m 用于输出程序指明的日志信息。 最基本的。
%M 输出产生log请求的方法。警告:会影响性能。
%n 换行
%p 输出logging 事件。如debug,info,warn,error
%r 输出构造log使用的时间
%t 输出产生log请求的线程名。
%x 用于输出与产生log线程关联的NDC。
%X 用于输出MDC
%% 输出百分号。
设置log消息输出到文件中也有几个log4j自带的Appender可用,
如:org.apache.log4j.DailyRollingFileAppender
基本设置如下:
<!-- 日志文件输出设置 -->
<appender name="file" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="logs/app_log.log"/>
<param name="DatePattern" value=".yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%-5p] %d{yyyy-MM-dd HH:mm:ss} %c{3} - %m%n" />
</layout>
</appender>
值得注意的一个问题就是:
在我的spring框架下的web环境下。
日志文件输出的地方。在我的Ubuntu系统下。
它输出的位置地在主目录下的logs目录下。
在windows系统中应该是指在我的文档处吧。
而在一般的java程序配置下时,它的输出在
项目根目录下。
关于过滤日志级别的配置可以参考以下iteye帖子:
log4j不同级别日志分不同文件记录
一个错误:
Caused by: java.io.FileNotFoundException: /home/banxi1988/work/posterWallworkspace/LogDemo/src/log4j.dtd (No such file or directory)
原因是在log4j.xml所在目录下多出来一个log4j.out.xml文件。
我奇怪的是为什么的我的日志文件加日期名配置就是不成功:
下面的代码我也尝试了还几种写法。
<param name="DatePattern" value=".yyyy-MM-dd"/>
<!-- 下面的也尝试过。-->
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
再尝试换一个属性,报如下信息。看来我是暂时没有办法了。
log4j:WARN No such property [fileNamePattern] in org.apache.log4j.DailyRollingFileAppender.
使用学习暂时到此,未完待续-----------
分享到:
相关推荐
详细介绍了log4j的使用方法,介绍了java中日志记录如何写入数据库,对于初学者来说很不错的一个文档
使用log4j2实现日志数据脱敏
日志打印文件log4j日志打印文件log4j日志打印文件log4j日志打印文件log4j日志打印文件log4j
演示了java记录通过log4j2记录日志到mysql数据库中
Java日志全面示例,可以下载运行,简洁易懂,能说明问题。 用maven构建,Java中普通加载log4j,普通web项目加载log4j,Spring项目加载log4j,让你彻底清除Java日志的配置和集成
Java 日志工具 Log4j 示例源代码
log4j2配置文件,按照文件大小划分日志,保存日期天数内的日志,指纹日志命名规则,日志输出等级等功能
根据项目需要,要求日志文件名及输出的日志内容头为特殊的格式,因此重写了log4j的一些方法,如要求的格式和项目不同,可根据示例参考进行再次的修改
Loggers组件的主要功能是提供相应API,根据不同配置的loggers将不同级别的log输入到控制台或文件,类似于java中经常用到的System.out.println,但是log4j封装后的loggers组件能够输出更丰富的信息,包括时间,线程,...
log4j.rar java写LOG日志的驱动 java log4j 驱动
Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务 器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出...
禁用与使用日志请求只是Log4j其中的一个小小的地方,Log4j日志系统允许把日志输出到不同的地方,如控制台(Console)、文件(Files)、根据天数或者文件大小产生新的文件、以流的形式发送到其它地方等等。...
log4j中配置日志文件相对路径方法分析 方法一、 解决的办法自然是用相对路径代替绝对路径,其实log4j的FileAppender本身就有这样的机制,如:log4j.appender.logfile.File=${WORKDIR}/logs/app.log 其中“${...
使用Log4j进行日志操作,LOG4J是记录日志文件的强大工具,非常方便较大系统的开发。
Java Log4j 1,2 所需Jar包,一个完整的软件,日志是必不可少的。程序从开发、测试、维护、运行等环节,都需 要向控制台或文件等位置输出大量信息。这些信息的输出,在很多时候是使用 System.out.println()无法完成的。 ...
Java驱动包,log4j-1.2.14,日志文档 Java驱动包,log4j-1.2.14,日志文档 Java驱动包,log4j-1.2.14,日志文档 Java驱动包,log4j-1.2.14,日志文档 Java驱动包,log4j-1.2.14,日志文档 Java驱动包,log4j-1.2.14,日志文档
本项目既有对Java本身Logger的使用还有对log4j的使用.
由公司的项目需要根据日期和文件大小切分log4j日志,所以实现来该appender。本人测试通过,并且在公司的其它项目中已有线上使用,暂时还没发现问题。本人代码有写得不好或者错误的地方,欢迎大家指正,谢谢!!!
Log4J 日志文件输出Demo