为什么我的5S后面充电有显示却充不上电的A1533却不能用电信

Log4J日志配置详解和自定义log4j日志级别及输出日志到不同文件实现方法 - 博客频道 - CSDN.NET
如果你去做,你会找到一个方法,如果你不做,你会找到一个借口。
分类:java
Log4J日志配置详解
一、Log4j简介&
& & &&Log4j有三个主要的组件:Loggers(记录器),Appenders(输出源)和Layouts(布局)。这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出。综合使用这三个组件可以轻松地记录信息的类型和级别,并可以在运行时控制日志输出的样式和位置。
1、Loggers
& & &Loggers组件在此系统中被分为五个级别:DEBUG、INFO、WARN、ERROR和FATAL。这五个级别是有顺序的,DEBUG & INFO & WARN & ERROR & FATAL,分别用来指定这条日志信息的重要程度,明白这一点很重要,Log4j有一个规则:只输出级别不低于设定级别的日志信息,假设Loggers级别设定为INFO,则INFO、WARN、ERROR和FATAL级别的日志信息都会输出,而级别比INFO低的DEBUG则不会输出。
2、Appenders
& & &禁用和使用日志请求只是Log4j的基本功能,Log4j日志系统还提供许多强大的功能,比如允许把日志输出到不同的地方,如控制台(Console)、文件(Files)等,可以根据天数或者文件大小产生新的文件,可以以流的形式发送到其它地方等等。
常使用的类如下:
org.apache.log4j.ConsoleAppender(控制台)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
配置模式:
log4j.appender.appenderName = className
log4j.appender.appenderName.Option1 = value1
log4j.appender.appenderName.OptionN = valueN
3、Layouts
& & &有时用户希望根据自己的喜好格式化自己的日志输出,Log4j可以在Appenders的后面附加Layouts来完成这个功能。Layouts提供四种日志输出样式,如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式。
常使用的类如下:
org.apache.log4j.HTMLLayout(以HTML表格形式布局)
org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)
配置模式:
log4j.appender.appenderName.layout =className
log4j.appender.appenderName.layout.Option1 = value1
log4j.appender.appenderName.layout.OptionN = valueN
二、配置详解
& & &在实际应用中,要使Log4j在系统中运行须事先设定配置文件。配置文件事实上也就是对Logger、Appender及Layout进行相应设定。Log4j支持两种配置文件格式,一种是XML格式的文件,一种是properties属性文件。下面以properties属性文件为例介绍log4j.properties的配置。
1、配置根Logger:
log4j.rootLogger = [ level ] , appenderName1, appenderName2, …
log4j.additivity.org.apache=false:表示Logger不会在父Logger的appender里输出,默认为true。
level :设定日志记录的最低级别,可设的值有OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别,Log4j建议只使用中间四个级别。通过在这里设定级别,您可以控制应用程序中相应级别的日志信息的开关,比如在这里设定了INFO级别,则应用程序中所有DEBUG级别的日志信息将不会被打印出来。
appenderName:就是指定日志信息要输出到哪里。可以同时指定多个输出目的地,用逗号隔开。
例如:log4j.rootLogger=INFO,A1,B2,C3
2、配置日志信息输出目的地(appender):
log4j.appender.appenderName = className
appenderName:自定义appderName,在log4j.rootLogger设置中使用;
className:可设值如下:
(1)org.apache.log4j.ConsoleAppender(控制台)
(2)org.apache.log4j.FileAppender(文件)
(3)org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
(4)org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
(5)org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
(1)ConsoleAppender选项:
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Target=System.err:默认值是System.out。
(2)FileAppender选项:
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件中。
(3)DailyRollingFileAppender选项:
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
File=D:/logs/logging.log4j:指定当前消息输出到logging.log4j文件中。
DatePattern='.'yyyy-MM:每月滚动一次日志文件,即每月产生一个新的日志文件。当前月的日志文件名为logging.log4j,前一个月的日志文件名为logging.log4j.yyyy-MM。
另外,也可以指定按周、天、时、分等来滚动日志文件,对应的格式如下:
1)'.'yyyy-MM:每月
2)'.'yyyy-ww:每周
3)'.'yyyy-MM-dd:每天
4)'.'yyyy-MM-dd-a:每天两次
5)'.'yyyy-MM-dd-HH:每小时
6)'.'yyyy-MM-dd-HH-mm:每分钟
(4)RollingFileAppender选项:
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件中。
MaxFileSize=100KB:后缀可以是KB, MB 或者GB。在日志文件到达该大小时,将会自动滚动,即将原来的内容移到logging.log4j.1文件中。
MaxBackupIndex=2:指定可以产生的滚动文件的最大数,例如,设为2则可以产生logging.log4j.1,logging.log4j.2两个滚动文件和一个logging.log4j文件。
3、配置日志信息的输出格式(Layout):
log4j.appender.appenderName.layout=className
className:可设值如下:
(1)org.apache.log4j.HTMLLayout(以HTML表格形式布局)
(2)org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
(3)org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
(4)org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
(1)HTMLLayout选项:
LocationInfo=true:输出java文件名称和行号,默认值是false。
Title=My Logging: 默认值是Log4J Log Messages。
(2)PatternLayout选项:
ConversionPattern=%m%n:设定以怎样的格式显示消息。
格式化符号说明:
%p:输出日志信息的优先级,即DEBUG,INFO,WARN,ERROR,FATAL。
%d:输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,如:%d{yyyy/MM/dd HH:mm:ss,SSS}。
%r:输出自应用程序启动到输出该log信息耗费的毫秒数。
%t:输出产生该日志事件的线程名。
%l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数。例如:test.TestLog4j.main(TestLog4j.java:10)。
%c:输出日志信息所属的类目,通常就是所在类的全名。
%M:输出产生日志信息的方法名。
%F:输出日志消息产生时所在的文件名称。
%L::输出代码中的行号。
%m::输出代码中指定的具体日志信息。
%n:输出一个回车换行符,Windows平台为&rn&,Unix平台为&n&。
%x:输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%:输出一个&%&字符。
另外,还可以在%与格式字符之间加上修饰符来控制其最小长度、最大长度、和文本的对齐方式。如:
1) c:指定输出category的名称,最小的长度是20,如果category的名称长度小于20的话,默认的情况下右对齐。
2)%-20c:&-&号表示左对齐。
3)%.30c:指定输出category的名称,最大的长度是30,如果category的名称长度大于30的话,就会将左边多出的字符截掉,但小于30的话也不会补空格。
附:Log4j比较全面的配置
Log4j配置文件实现了输出到控制台、文件、回滚文件、发送日志邮件、输出到数据库日志表、自定义标签等全套功能。
log4j.rootLogger=DEBUG,console,dailyFile,im
log4j.additivity.org.apache=true
# 控制台(console)
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%-5p] %d(%r) --& [%t] %l: %m %x %n
# 日志文件(logFile)
log4j.appender.logFile=org.apache.log4j.FileAppender
log4j.appender.logFile.Threshold=DEBUG
log4j.appender.logFile.ImmediateFlush=true
log4j.appender.logFile.Append=true
log4j.appender.logFile.File=D:/logs/log.log4j
log4j.appender.logFile.layout=org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=[%-5p] %d(%r) --& [%t] %l: %m %x %n
# 回滚文件(rollingFile)
log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.Threshold=DEBUG
log4j.appender.rollingFile.ImmediateFlush=true
log4j.appender.rollingFile.Append=true
log4j.appender.rollingFile.File=D:/logs/log.log4j
log4j.appender.rollingFile.MaxFileSize=200KB
log4j.appender.rollingFile.MaxBackupIndex=50
log4j.appender.rollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=[%-5p] %d(%r) --& [%t] %l: %m %x %n
# 定期回滚日志文件(dailyFile)
log4j.appender.dailyFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.dailyFile.Threshold=DEBUG
log4j.appender.dailyFile.ImmediateFlush=true
log4j.appender.dailyFile.Append=true
log4j.appender.dailyFile.File=D:/logs/log.log4j
log4j.appender.dailyFile.DatePattern='.'yyyy-MM-dd
log4j.appender.dailyFile.layout=org.apache.log4j.PatternLayout
log4j.appender.dailyFile.layout.ConversionPattern=[%-5p] %d(%r) --& [%t] %l: %m %x %n
# 应用于socket
log4j.appender.socket=org.apache.log4j.RollingFileAppender
log4j.appender.socket.RemoteHost=localhost
log4j.appender.socket.Port=5001
log4j.appender.socket.LocationInfo=true
# Set up for Log Factor 5
log4j.appender.socket.layout=org.apache.log4j.PatternLayout
log4j.appender.socket.layout.ConversionPattern=[%-5p] %d(%r) --& [%t] %l: %m %x %n
# Log Factor 5 Appender
log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
# 发送日志到指定邮件
log4j.appender.mail=org.apache.log4j.net.SMTPAppender
log4j.appender.mail.Threshold=FATAL
log4j.appender.mail.BufferSize=10
log4j.appender.mail.From =
log4j.appender.mail.
log4j.appender.mail.Subject=Log4J Message
log4j.appender.mail.To=
log4j.appender.mail.layout=org.apache.log4j.PatternLayout
log4j.appender.mail.layout.ConversionPattern=[%-5p] %d(%r) --& [%t] %l: %m %x %n
# 应用于数据库
log4j.appender.database=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.database.URL=jdbc:mysql://localhost:3306/test
log4j.appender.database.driver=com.mysql.jdbc.Driver
log4j.appender.database.user=root
log4j.appender.database.password=
log4j.appender.database.sql=INSERT INTO LOG4J (Message) VALUES('=[%-5p] %d(%r) --& [%t] %l: %m %x %n')
log4j.appender.database.layout=org.apache.log4j.PatternLayout
log4j.appender.database.layout.ConversionPattern=[%-5p] %d(%r) --& [%t] %l: %m %x %n
# 自定义Appender
log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
log4j.appender.im.host = mail.cybercorlin.net
log4j.appender.im.username = username
log4j.appender.im.password = password
log4j.appender.im.recipient =
log4j.appender.im.layout=org.apache.log4j.PatternLayout
log4j.appender.im.layout.ConversionPattern=[%-5p] %d(%r) --& [%t] %l: %m %x %n
log4j的强大功能无可置疑,但实际应用中免不了遇到某个功能需要输出独立的日志文件的情况,怎样才能把所需的内容从原有日志中分离,形成单独的日志文件呢?其实只要在现有的log4j基础上稍加配置即可轻松实现这一功能。
先看一个常见的log4j.properties文件,它是在控制台和myweb.log文件中记录日志:
log4j.rootLogger=DEBUG, stdout, logfile
log4j.category.org.springframework=ERROR
log4j.category.org.apache=INFO
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
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=${myweb.root}/WEB-INF/log/myweb.log
log4j.appender.logfile.MaxFileSize=512KB
log4j.appender.logfile.MaxBackupIndex=5
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
如果想对不同的类输出不同的文件(以cn.com.Test为例),先要在Test.java中定义:
private static Log logger = LogFactory.getLog(Test.class);
然后在log4j.properties中加入:
.com.Test= DEBUG, test
log4j.appender.test=org.apache.log4j.FileAppender
log4j.appender.test.File=${myweb.root}/WEB-INF/log/test.log
log4j.appender.test.layout=org.apache.log4j.PatternLayout
log4j.appender.test.layout.ConversionPattern=%d %p [%c] - %m%n
也就是让cn.com.Test中的logger使用log4j.appender.test所做的配置。
但是,如果在同一类中需要输出多个日志文件呢?其实道理是一样的,先在Test.java中定义:
private static Log logger1 = LogFactory.getLog(&myTest1&);
private static Log logger2 = LogFactory.getLog(&myTest2&);
然后在log4j.properties中加入:
log4j.logger.myTest1= DEBUG, test1
log4j.appender.test1=org.apache.log4j.FileAppender
log4j.appender.test1.File=${myweb.root}/WEB-INF/log/test1.log
log4j.appender.test1.layout=org.apache.log4j.PatternLayout
log4j.appender.test1.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.logger.myTest2= DEBUG, test2
log4j.appender.test2=org.apache.log4j.FileAppender
log4j.appender.test2.File=${myweb.root}/WEB-INF/log/test2.log
log4j.appender.test2.layout=org.apache.log4j.PatternLayout
log4j.appender.test2.layout.ConversionPattern=%d %p [%c] - %m%n
也就是在用logger时给它一个自定义的名字(如这里的&myTest1&),然后在log4j.properties中做出相应配置即可。别忘了不同日志要使用不同的logger(如输出到test1.log的要用(&abc&))。
  还有一个问题,就是这些自定义的日志默认是同时输出到log4j.rootLogger所配置的日志中的,如何能只让它们输出到自己指定的日志中呢?别急,这里有个开关:
log4j.additivity.myTest1 = false
  它用来设置是否同时输出到log4j.rootLogger所配置的日志中,设为false就不会输出到其它地方啦!注意这里的&myTest1&是你在程序中给logger起的那个自定义的名字!
如果你说,我只是不想同时输出这个日志到log4j.rootLogger所配置的logfile中,stdout里我还想同时输出呢!那也好办,把你的log4j.logger.myTest1 = DEBUG, test1改为下式就OK啦!
log4j.logger.myTest1=DEBUG, test1
下面是文件上传时记录文件类型的log日志,并输出到指定文件的配置
log4j.rootLogger=INFO, stdout
######################### logger ##############################
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.conversionPattern = %d [%t] %-5p %c - %m%n
log4j.logger.extProfile=INFO, extProfile#日志级别是INFO,标签是extProfile
log4j.additivity.extProfile=#输出到指定文件extProfile.log中
#userProfile log\uff08\u8bb0\u5f55\u4fee\u\u7801\uff0c\u627e\u56de\u5bc6\u7801\uff0c\u4fee\u6539\u90ae\u7bb1\uff0c\u4fee\ub\u673a\u53f7\uff09
log4j.appender.extProfile=org.apache.log4j.RollingFileAppender
log4j.appender.extProfile.File=logs/extProfile.log#输出到resin根目录的logs文件夹,log4j会自动生成目录和文件
log4j.appender.extProfile.MaxFileSize=20480KB#超过20M就重新创建一个文件
log4j.appender.extProfile.MaxBackupIndex=10
log4j.appender.extProfile.layout=org.apache.log4j.PatternLayout
log4j.appender.extProfile.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
以上内容转自/ITtangtang/p/3926665.html加在这里方便我以后查阅
自定义log4j日志级别及输出日志到不同文件实现方法
自定义日志类
package com.jo.work.log4j;
import java.util.E
import org.apache.log4j.A
import org.apache.log4j.FileA
import org.apache.log4j.L
import org.apache.log4j.L
import org.apache.log4j.PatternL
import org.apache.log4j.RollingFileA
import org.apache.log4j.net.SyslogA
* 自定义日志级别和 
public class CustomLog {
private static CustomLog log = new CustomLog();
private CustomLog(){}
public static CustomLog getInstance() {
* 继承Level自定义级别
private static class CustomLogLevel extends Level{
private static final long serialVersionUID = 1L;
protected CustomLogLevel(int level, String levelStr, int syslogEquivalent) {
super(level, levelStr, syslogEquivalent);
* 自定义级别名称,以及级别范围
private static final Level CustomerLevel = new CustomLogLevel(20050, &CUSTOMER&, SyslogAppender.LOG_LOCAL0);
* 生成日志对象
* @param filePath 日志输出路径
* @param fileName 日志文件名
* @param conversionPattern log的输出形式
* @param flag true:在已存在log文件后面追加 false:新log覆盖以前的log
public Logger createLogger(String filePath, String fileName, String conversionPattern, boolean flag){
// 生成新的Logger
// 如果已经有了一个Logger实例则返回
Logger logger = Logger.getLogger(fileName);
// 清空Appender。特別是不想使用现存实例时一定要初期化
logger.removeAllAppenders();
// 设计定Logger级别。
logger.setLevel(Level.DEBUG);
// 设定是否继承父Logger。
// 默认为true。继承root输出。
// 设定false后将不输出root。
logger.setAdditivity(false);
// 生成新的Appender
FileAppender appender = new RollingFileAppender();
// log的输出形式
PatternLayout layout = new PatternLayout();
layout.setConversionPattern(conversionPattern+&%m%n&);
appender.setLayout(layout);
// log输出路径
appender.setFile(filePath+ fileName + &.log&);
// log的文字码
appender.setEncoding(&UTF-8&);
// true:在已存在log文件后面追加 false:新log覆盖以前的log
appender.setAppend(flag);
// 适用当前配置
appender.activateOptions();
// 将新的Appender加到Logger中
logger.addAppender(appender);
* 使用自定义日志打印logger中的log方法
* @param logger 日志对象
* @param objLogInfo:日志内容
public void customLog(Logger logger, Object objLogInfo){
logger.log(CustomerLevel, objLogInfo);
* 关闭自定义log
* @param logger 日志对象
@SuppressWarnings(&unchecked&)
public void closeCustomLog(Logger logger){
for (Enumeration&Appender& appenders=logger.getAllAppenders(); appenders.hasMoreElements();) {
Appender appender=appenders.nextElement();
appender.close();
package com.jo.work.log4j.
import org.apache.log4j.L
import com.jo.work.log4j.CustomL
public class Test {
public static void main(String[] args) {
Logger logger = CustomLog.getInstance().createLogger(&d:/log/&, &test&, &---&&, false);
CustomLog.getInstance().customLog(logger,&测试&);
Logger logger1 = CustomLog.getInstance().createLogger(&d:/log/&, &test1&, &---&&, false);
CustomLog.getInstance().customLog(logger1,&测试1&);
CustomLog.getInstance().closeCustomLog(logger);
CustomLog.getInstance().closeCustomLog(logger1);
huiwenjie168
排名:第10090名
(23)(4)(5)(2)(7)(10)(4)(2)
(137853)Log4j日志记录水平调整 -
- ITeye博客
最近研究了一下Log4j这个被广发使用的日志组件,缘于三个问题:日志水平调整问题,日志运行时配置修改和日志模块化问题。Log4j不是一天两天的了,相信早就会有相应的解决方法。
先来看第一个问题。生产运行中考虑到日常资源消耗和运行性能是不宜开启低水平日志记录的。然而,一旦生产运行环境出现异常,没有相当详细程度的日志信息的话,要进行快速的定位分析准确的排查判断几乎是不可能的。这个矛盾令人十分纠结,是应该提高日志水平减少不必要的日志输出消耗呢,降低日志水平还是管它有理无理尽量详细记录呢。我的想法是两者都要兼顾,如果要做一个折衷的话,日志组件能够根据运行的记录水平,对日志内容进行细粒度输出控制。
一种解决思路是自定义PatternLayout能够根据当前的日志记录水平来进行不同格式的日志输出。可以在Log4j配置中划定高水平和低水平的日志界限(Threshold),低水平记录(对应于警告及其以下)和高水平记录(对应于错误及其以上)分别采用详细的日志格式和粗略的日志格式。我的扩展实现如下, 像所在文件和所在行数等信息,要获取这些信息需要通过运行时反射得到,对日志性能影响甚大,因而,凡是警告及其以下低级别的日志不予输出,而对于错误及其以上高级别的日志则记录。
public class LogLevelThresholdPatternLayout extends Layout {
private Level threshold =
Level.WARN;
private static final String DEFAULT_LOW_LEVEL_PATTERN = "%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] %m%n";
private static final String DEFAULT_HIGH_LEVEL_PATTERN = "%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] %t %l %m%n";
private PatternLayout lowLevelPatternL
private PatternLayout highLevelPatternL
public void setThreshold(Level threshold) {
this.threshold =
public void setLowLevelConversionPattern(String lowLevelConversionPattern){
lowLevelPatternLayout = new PatternLayout(lowLevelConversionPattern);
public void setHighLevelConversionPattern(String highLevelConversionPattern){
highLevelPatternLayout = new PatternLayout(highLevelConversionPattern);
public void activateOptions() {
if (lowLevelPatternLayout == null) {
lowLevelPatternLayout = new PatternLayout(DEFAULT_LOW_LEVEL_PATTERN);
lowLevelPatternLayout.activateOptions();
if (highLevelPatternLayout == null) {
highLevelPatternLayout = new PatternLayout(DEFAULT_HIGH_LEVEL_PATTERN);
highLevelPatternLayout.activateOptions();
public String format(LoggingEvent event) {
if (threshold.isGreaterOrEqual(event.getLevel())) {
return lowLevelPatternLayout.format(event);
return highLevelPatternLayout.format(event);
public boolean ignoresThrowable() {
这时候 Log4j的XML配置就像如下便可:
&appender name="RollingLogFile" class="org.apache.log4j.DailyRollingFileAppender"&
&param name="File" value="test.log" /&
&layout class="xxx.yyy.zzz.LogLevelThresholdPatternLayout"&
&param name="highLevelConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] %t %l %m%n" /&
&param name="lowLevelConversionPattern" value="%d{HH:mm:ss} [%-5p] %m%n" /&
&/appender&
在查看Log4j的Javadoc进行配置的时候发现了另外一个问题。Log4j在版本1.2.16引入了一个新的类org.apache.log4j.EnhancedPatternLayout来替代原有使用的org.apache.log4j.PatternLayout。如果条件允许,特别是在新的部署环境应该优先使用。于是,上面的配置因此可以改成如下这样:
public class LogLevelThresholdPatternLayout extends Layout {
private Level threshold =
Level.WARN;
private EnhancedPatternLayout lowLevelPatternL
private EnhancedPatternLayout highLevelPatternL
public void setThreshold(Level threshold) {
this.threshold =
public void setLowLevelConversionPattern(String lowLevelConversionPattern){
lowLevelPatternLayout = new EnhancedPatternLayout(lowLevelConversionPattern);
public void setHighLevelConversionPattern(String highLevelConversionPattern){
highLevelPatternLayout = new EnhancedPatternLayout(highLevelConversionPattern);
除此之外,旧版本的的org.apache.log4j.DailyRollingFileAppender同org.apache.log4j.PatternLayout一样,应该优先使用org.apache.log4j.rolling.RollingFileAppender作为替代,这个可以从Apache Logging另外一个子项目apache-log4j-extra找到的。于是去下载log4j-extra来玩一下,刚好发现log4j-extra最近有了更新。apache-log4j-extra基于Log4j1.2版本,其大部分源码源于已经停止继续维护的Log4j-1.3版本。同原有的org.apache.log4j.DailyRollingFileAppender相比,配置上的主要区别是专门分出出一个的org.apache.log4j.rolling.TimeBasedRollingPolicy的类来对文件滚动细节进行具体控制。配置如下:
&appender name="RollingLogFile" class="org.apache.log4j.rolling.RollingFileAppender"&
&rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy"&
&param name="ActiveFileName" value="test.log" /&
&param name="FileNamePattern" value="test.log.%d{yyyy-MM-dd}" /&
&/rollingPolicy&
&/appender&
回到最初的日志水平调整问题,另外一种解决思路可以通过配置Logger的多个Appender,每个Appender再配置相应的Layout来实现。为了避免多个Appender重复记录,还需要配置对应的Filter和Threshold来过滤相应的日志水平。这种方式会导致配置有点繁琐,但好处是仅通过对Log4j的进行适当配置便可,无需额外扩展代码实现。具体下面的配置如下。
&?xml version="1.0" encoding="UTF-8"?&
&!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"&
&log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"&
&appender name="HIGHLOG" class="org.apache.log4j.DailyRollingFileAppender"&
&param name="File" value="test.log" /&
&layout class="org.apache.log4j.PatternLayout"&
&param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] %m%n" /&
&filter class="org.apache.log4j.varia.LevelRangeFilter"&
&param name="LevelMin" value="INFO" /&
&/appender&
&appender name="LOWLOG" class="org.apache.log4j.DailyRollingFileAppender"&
&param name="Threshold" value="WARN"/&
&param name="File" value="test.log" /&
&layout class="org.apache.log4j.PatternLayout"&
&param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] %t %l %m%n" /&
&/appender&
&logger name="xxx.yyy.zzz"&
&appender-ref ref="HIGHLOG" /&
&appender-ref ref="LOWLOG" /&
&/log4j:configuration&
像上面的配置经过简单试验,是可以达到同上一种方式PatternLayout自定义扩展一样的效果的。然而,这样配置存在一个隐患,在文件滚动的时候多个FileAppender包装下对同一个文件的,能否做到滚动在Appender之间做到同步,能否不会因I/O异常而出现死锁等等是很值得怀疑的,特别是文件发生滚动时又发生大量日志输出的时候,会不会导致整个系统长时间停顿等等。具体的触发机制很难深究,我又没做过实际试验研究不好妄下结论。默认设置下的每日滚动,是发生在每日凌晨这个时间点。这时候一般是业务空闲时期,相信实际中也很难触发文件同步或者数据丢失问题。为了保险起见应该使用由log4j-extra提供的org.apache.log4j.rolling.RollingFileAppender。按照Javadoc的说法,应该是修复了先前的DailyRollingFileAppender表现出的数据同步和丢失问题。
下面来看第二个问题日志配置运行时修改。为了观察系统运行状态,捕捉和监控系统缺陷源头,往往需要对记录水平等等日志配置项进行运行时调整,而最重要的前提是系统服务不能停止。Log4j提供两种方式来解决。第一种就是定期重新加载Log4j配置文件。这种方式使用很简单,加载时候调用如下方法之一,并指定文件重新加载间隔便可。
DOMConfigurator.configureAndWatch(String configFilename, long delay)
PropertyConfigurator.configureAndWatch(configFilename, delay)
个人不很推荐这种方式,把所有配置重新加载一次,Log4j内部会不会对Logger/Appender进行一定的同步处理,会不会做成大范围的系统停顿要打个问号,特别在日志输出很频繁的情况下。很多时候,我们往往只需要运行时调整一下日志记录水平参数,没必要像第一种那样将配置全部重新Load一次,第二种方式JMX就排上用场了。Log4j是内置JMX的支持,对于这个问题是有很好的解决的。只需要把相应的Log4j对象包装到MBean中去并注册到MBean服务器中去便可通过相应MBean管理环境来进行日志记录水平运行时调整。具体实现可以参考由Log4j提供的如下类:
org.apache.log4j.jmx.HierarchyDynamicMBean
org.apache.log4j.jmx.AppenderDynamicMBean
org.apache.log4j.jmx.LoggerDynamicMBean
org.apache.log4j.jmx.LayoutDynamicMBean
向mbean服务器注册Logger可以是类似如下的大致上可以像如下的实现。
MBeanServer mbeansServer = MBeanServerFactory.createMBeanServer();
LoggerRepository hierarchy = LogManager.getLoggerRepository();
Enumeration&?& loggerEnumeration = hierarchy.getCurrentLoggers();
while (loggerEnumeration.hasMoreElements()) {
Logger logger = (Logger)loggerEnumeration.nextElement();
LoggerDynamicMBean loggerDynamicMBean =
new LoggerDynamicMBean(logger);
mbeansServer.registerMBean(loggerDynamicMBean,
createObjectName("logger", logger.getName()));
} catch (InstanceAlreadyExistsException e) {
// TODO output log ?
} catch (MBeanRegistrationException e) {
// TODO output log ?
} catch (NotCompliantMBeanException e) {
// TODO output log ?
private ObjectName createObjectName(String typeName, String objName) {
ObjectName objectName =
objectName =new ObjectName(
"org.apache.log4j.default:type=" + typeName + ",name=" + objName);
} catch (MalformedObjectNameException e) {
// TODO output log ?
} catch (NullPointerException e) {
// TODO output log ?
return objectN
下面开始要说的是日志模块化的问题。分别准备两个Log4j配置文件log4j-1.xml 和log4j-2.xml,并分别加载运行,测试代码可以像如下的代码。
URL url1 =
Thread.currentThread()
.getContextClassLoader()
.getResource("xxx/yyy/log4j/log4j-1.xml");
Logger logger = LogManager.getLogger("xxx.yyy.zzz");
DOMConfigurator.configure(url1);
("test log 1 here");
URL url2 =
Thread.currentThread()
.getContextClassLoader()
.getResource("xxx/yyy/zzz/log4j/log4j-2.xml");
DOMConfigurator.configure(url1);
("test log 2 here");
运行后会发现后面加载的Log4j-2.xml的配置会覆盖前面的Log4j-1.xml的配置,如果有相同名字的Logger或者Appender的话。如果均使用默认类路径下的配置文件(log4j.xml/log4j.properties)或者同一个配置文件的话,又或者Logger和Appender没有重名的话,就 不会存在这样的问题。但是,在应用程序多模块环境下, 是很容易发生日志配置文件冲突的,这时候就需要一定的隔离机制。Log4j内部的org.apache.log4j.Hierarchy管理不同的Logger就是通过这样的完全限定名来管理Logger配置的层级继承关系的。因而,绝大部分情况下模块可以根据包名来唯一区分,最简单最直接的隔离就是在定义名称的时候用包名来限定,这样就不会被其他模块干扰到。
&appender name="xxx.yyy.zzz.STDOUT" class="org.apache.log4j.ConsoleAppender"&
&layout class="org.apache.log4j.PatternLayout"&
&param name="ConversionPattern"
value="%d{yyyy-MM-dd HH:mm:ss} [Log-1] [%-5p] [%c{1}] %m%n" /&
&/appender&
&logger name="xxx.yyy.zzz"&
&appender-ref ref="xxx.yyy.zzz.STDOUT" /&
还有一种思路是对Log4j进行适当扩展。Log4j使用org.apache.log4j.spi.LoggerRepository来维护管理不同的Logger状态。可以用不同的LoggerRepository来划分模块的界限。org.apache.log4j.spi.LoggerRepository的具体实现就是org.apache.log4j.Hierarchy。当用户代码调用LogManager#getLogger的时候,就会通过LogManager#getLoggerRepository来返回一个默认的Hierarchy类实例。默认的Hierarchy实例在LogManager静态初始化块中中实例化,Hierarchy内部维护一个用来存储Logger的Hashtable,返回给上层的LogManager#getLogger的调用。LogManager提供一个方法setRepositorySelector来设定选择器,可以用来改变调用getLoggerRepository时所返回的默认Hiearchy实例。实现自己的RepositorySelector可能类似如下。
public class MultipleModulesRepositorySelector extends DefaultRepositorySelector {
private static final Map&String, LoggerRepository& repositories =
Collections.synchronizedMap(new HashMap&String, LoggerRepository&());
public MultipleModulesRepositorySelector(LoggerRepository defaultRepository) {
super(defaultRepository);
public LoggerRepository getLoggerRepository() {
LoggerRepository loggerRepository = repositories.get(getModuleName());
if (loggerRepository != null) {
return loggerR
// not found and create a new LoggerRepository
LoggerRepository hierarchy = new Hierarchy(new RootLogger((Level) Level.DEBUG));
repositories.put(moduleName, hierarchy);
// returns the default repository
return super.getLoggerRepository();
protected String getModuleName() {
// detail implementation here
// 用户扩展代码如下,静态初始化RepositorySelector。
LoggerRepository defaultLoggerRepository = LogManager.getLoggerRepository();
MultipleModulesRepositorySelector selector =
new MultipleModulesRepositorySelector(defaultLoggerRepository);
LogManager.setRepositorySelector(
RepositorySelector selector, new Object()); // only can be invoked once
这种实现实际上不甚理想,Logger实例如果是作为类的静态成员变量就有可能仅仅从默认的LoggerRepository中生成并获取,而非从对应模块的LoggerRepository中拿到。这种实现必须要求Logger只能是类普通的非静态成员变量。还是老老实实采用完全限定名来避免冲突。最后不得不提一下Logback,一个由Log4j原作者所推出新的日志组件对此日志模块化的解决方案。
在Logback中,可以通过设置每个配置文件的上下文名称(contextName)来划定模块界限。其配置是类似这样的:
&configuration&
&contextName&myAppName&/contextName&
&appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"&
&pattern&%d %contextName [%t] %level - %msg%n&/pattern&
&/encoder&
&/appender&
&root level="DEBUG"&
&appender-ref ref="STDOUT" /&
&/configuration&
再在一个总的配置文件中分别导入各子模块的配置,而用户代码只需要导入一个总入口文件便可。
&configuration&
&include file="xxx/yyy/zzz/configuration/module1.xml"/&
&include file="xxx/yyy/zzz/configuration/module2.xml"/&
&/configuration&
除此之外,对于运行在JavaEE容器的多应用,Logback还可以根据应用初始化上下文来指定上下文名称来达到隔离目的。
&configuration&
&insertFromJNDI env-entry-name="java:comp/env/appName" as="appName" /&
&contextName&${appName}&/contextName&
&/configuration&
最好结尾跟Logback宣传一下,一些不被Log4j直接支持的新特性
自动清除日志滚动的历史存档
配置更灵活,如与Ant配置类似的子文件引入,变量替代,配置文件条件动态化
根据运行时属性切换目标输出文件,如某种特定的访问记录到单独的文件
打印异常堆栈所在包
浏览: 43392 次
来自: 广州
kjwxj 写道发现问题了,xml是可以直接这样引用的,但是在 ...
发现问题了,xml是可以直接这样引用的,但是在编译的时候xml ...
又诡异了,没做任何修改,就这样整,放在main下面又可以直接引 ...
那hibernate的xml的怎么加载呢,这个都是放在main ...

我要回帖

更多关于 充电有显示却充不上电 的文章

 

随机推荐