Log4js配置详解
基于log4js 0.6.14版本
Log4js总共三篇博客
《Log4js原理解析》http://blog.csdn.net/hfty290/article/details/42844085
《Log4js配置详解》http://blog.csdn.net/hfty290/article/details/42843737
《Log4js多进程陷阱与避免》http://blog.csdn.net/hfty290/article/details/42843303
一、概述
log4js配置非常灵活,各种方式配置都可以,但是作者并没有给出清晰的文档说明。有时候不免困惑,为什么这样写也可以,那样也可以。js的灵活性有时候也会成为负担,人们的思维比较习惯一种固定模式,太多的选择性反而无所适从。那么本篇,将把log4js的几种配置方式详细进行说明,希望看过这篇文章的同学,不会再有这种困惑。
二、配置方式
log4js总体来说有三种配置方式,1)直接使用函数调用的方式,渐进地配置日志;2)提供一个配置对象,通过该对象一次性配置;3)提供一个配置文件,通过配置文件一次性配置。当然2、3两种配置之后,还可以通过函数调用方式进行修改。
1、函数调用渐进配置
基本过程:loadAppender、addAppender、getLogger、logger.setLevel;
1)log4js提供了多种多样的Appender,每种Appender提供不同的写入方式,所有的Appender只有加载之后才可以被使用(console会默认被加载,因此不需要为console调用loadAppender);
loadAppender时需要提供type,目前有file、datefile、multiprocess、console、clustered、gelf、hookio、loggly、smtp可以使用。
2)一个Appender加载之后,就可以创建对应的实例,通过addAppender函数将该实例添加到log4js之中,添加时需要指定该实例关联的类别。(类别名称可以取all之外的任何名字)。
创建appender实例有两种方法,分别是通过log4js.appenders; log4js.appenderMakers; 前者通过提供函数参数(对应每个Appender导出的appender),后者提供配置对象(对应每个Appender导出的configure);推荐使用后者;
一个类别最多创建一个logger实例,一个类别可以有多个关联的appender实例(一个实例也可以关联多个类别),这些关联的appender会监听这个logger实例的log事件,all类别的appender会监听所有logger实例的log事件。
当调用logger.info函数时,首先进行日志级别判断,当INFO级别小于日志级别时会直接返回。否则,会触发该logger的log事件,与他关联的所有appender会得到调用,all类型的appender也会得到调用。
如下代码中,创建的logger,没写一次日志,会在三个地方出现。分别是cheese.log;cheese1.log;console;因为console是为all类别的appender,所有的logger触发的log事件都会被监听到。
logging.loadAppender("file");
logging.addAppender(logging.appenderMakers['file']({
filename:"cheese1.log",
}), 'cheese');
logging.addAppender(logging.appenderMakers['file']({
filename:"cheese.log",
}), 'cheese');
var log = logging.getLogger("cheese");
log.setLevel('TRACE'); //set the Level
log.trace("trace me" );
4)setLevel用于指定一个logger的日志级别,日志级别可以直接使用字符串,也可以使用log4js中导出的对象,建议使用前者;
log.setLevel('TRACE'); //set the Level
log.setLevel(logging.levels.TRACE);
2、使用配置对象的方式
var log4js = require('log4js');
log4js.configure({
appenders: [
{ type: 'console' },
{ type: 'file', filename: 'cheese.log', category: 'cheese' },
{ type: 'file', filename: 'cheese1.log', category: 'cheese' }
],
levels: {
cheese: 'INFO',
},
});
var log = logging.getLogger("cheese");
log.trace("trace me" );
通过log4js.configure函数实现配置,只要将整个配置对象传递给他即可。对象内部有两个成员分别是appenders用于配置所有的appender,levels用于配置每个category对应logger的日志级别。
3、使用配置文件的方式
配置文件与配置对象很类似,只不过是将配置对象的内容放置到一个json文件之中;(注意:不能直接将上述的配置对象放入一个json文件中,因为那不是合法的json格式。json中所有的变量都使用双引号,并且最后一个成员不能使用逗号)修改后如下:
logging.configure('logconfig.json');
var log = logging.getLogger("cheese");
log.trace("trace me" );
logconfig.json内容如下:
{
"appenders": [
{ "type": "console" },
{ "type": "file", "filename": "cheese.log", "category": "cheese" },
{ "type": "file", "filename": "cheese1.log", "category": "cheese" }
],
"levels": {
"cheese": "TRACE"
}
}
三、Appender详细配置
通过上面的介绍,已经了解了log4js整体配置,但是还差一个细节,那就是每个Appender的创建参数。现在详细说明下各种Appender实例的创建。此处将讲述五种Appender的创建,每种Appender有两种创建方式,上面已经做过介绍,此处将一一例举。
在说明Appender实例的创建之前,还得说明下Layout的创建,因为任何一个Appender都需要一个Layout实例进行日志格式化。
1、Layout实例创建
多数情况下,并不需要处理Layout实例的创建,因此在创建Appender时若没有指定Layout实例,会默认创建一个basicLayout实例,来格式化日志。
logging.addAppender(logging.appenderMakers['file']({
filename:"cheese.log",layout: {type:'basic'},}), 'cheese');
logging.configure({
appenders: [{type: 'file', filename: 'cheese.log',
layout: {type:'basic'}, category: 'cheese' },
],});
目前总共有五种类型的Layout,basicLayout、messagePassThroughLayout、colouredLayout、coloredLayout、patternLayout,前面四种都只需要提供一个type即可创建,最后一个patternLayout还有其他参数,如下:
layout: {type:’basic'}
layout: {type:’messagePassThrough'}
layout: {type:’colored'}
layout: {type:’coloured’}
layout: {type:'pattern',
"pattern": "%[%r (%x{pid}) %p %c -%] %m%n",
"tokens": {"pid" : function() { return process.pid; }}
}
类型为pattern的Layout可以自定义格式化样式,目前提供的标示符有:
'c': categoryName,
'd': formatAsDate,
'h': hostname,
'm': formatMessage,
'n': endOfLine,
'p': logLevel,
'r': startTime,
'[': startColour,
']': endColour,
'%': percent,
'x': userDefined
上例中的 "pattern": "%[%r (%x{pid}) %p %c -%] %m%n",
其中自定义了tokens为pid,通过%x{pid}来引用。注意pattern的的 %[ 与 %] 表示颜色的开始于结束。上述配置打印出来的日志如下:
1、console创建
console实例的Appender只需要一个可选的layout参数
logging.addAppender(logging.appenderMakers['console']({
layout: {type:'messagePassThrough'}
}), 'cheese');
logging.configure({
appenders: [{ type: 'console' ,layout: {type:'messagePassThrough'}}],
});
2、file创建
file实例的Appender只需要一个filename和几个可选的参数。实现将日志写入到文件,支持按照文件大小进行滚动。
logging.addAppender(logging.appenderMakers['file']({
filename:"cheese2.log",
layout: {type:'basic'},
maxLogSize: 10000000,
backups:5
}), 'cheese');
logging.configure({
appenders: [{ type: 'file', filename: 'cheese.log',
layout: {type:'basic'},
maxLogSize: 10, backups:5, category: 'cheese' },]
});
配置中的layout、maxLogSize、backups都是可选的。其中maxLogSize表示单个日志文件最大大小,若设置该值,那么当日志大小超过时,会进行滚动。backups表示进行滚动时最多保存的文件个数。
3、datefile创建
datefile实例的Appender只需要一个filename和几个可选的参数。时间将日志写入到文件,根据时间进行滚动。非常灵活的一种滚动方式。
logging.configure({
appenders: [{ type: 'datefile', filename: 'cheese.log',
layout: {type:'basic'},pattern: '.yyyy-MM-dd',
alwaysIncludePattern: true, category: 'cheese' },]
});
log4js.addAppender(log4js.appenderMakers['datefile']({
filename:"cheese.log",layout: {type:'basic'},
pattern: '.yyyy-MM-dd',alwaysIncludePattern: true,
}), 'cheese');
其中的pattern参数用于获取时间数据,同时也根据该值进行日志滚动操作。上面例子使用 .yyyy-MM-dd 表示按天进行滚动,如果时间取得更小一点,比如,.yyyy-MM-dd-hh 则按照小时滚动,.yyyy-MM-dd-hh-mm 按照分钟滚动,.yyyy-MM-dd-hh-mm-ss 按照秒进行滚动。
alwaysIncludePattern参数表示是否在文件名末尾直接添加上时间,如果为true则日志名为:cheese.log.2015-01-18,否则日志名为cheese.log。
4、multiprocess配置
实现多进程同步方式写日志,在master上开启tcp监听,worker进程将日志发送给master,master实现将日志内容写入文件。multiprocess的配置分成master与worker:
master配置如下:
log4js.addAppender(log4js.appenderMakers['multiprocess']({
mode: "master", loggerPort: 5000, loggerHost: "localhost",
appender: {
type: "datefile", filename:"cheese.log",layout: {type:'basic'},
patterm: '.yyyy-MM-dd',alwaysIncludePattern: true
}
}), 'cheese');
log4js.configure({
appenders: [{
type: 'multiprocess', mode: "master", loggerPort: 5000, loggerHost: "localhost",category: 'cheese',
appender: {
type: "datefile", filename:"cheese.log",layout: {type:'basic'},
patterm: '.yyyy-MM-dd',alwaysIncludePattern: true,
}
}],
});
在master端,mode必须配置成master,loggerPort默认为5000,loggerHost默认为localhost,后面的appender为真实用到的appender,这个appender的配置参考上面说明。
worker配置如下:
log4js.addAppender(log4js.appenderMakers['multiprocess']({
loggerPort: 5000, loggerHost: "localhost",
}), 'cheese');
log4js.configure({
appenders: [{
type: 'multiprocess', loggerPort: 5000, loggerHost: "localhost",
category: 'cheese',
}],
});
在worker端配置比较简单,只需要配置master的端口与host即可。
5、clustered配置
用于在cluster环境中使用,在master进程上创建真正的appender,而worker进程也是将日志发送给master,由master将日志写入到文件中,总之和multiprocess很类似。clustered的配置在master与worker可以是完全一样的。
log4js.addAppender(log4js.appenderMakers['clustered']({
appenders: [{
type: "datefile", filename:"cheese.log",layout: {type:'basic'},
patterm: '.yyyy-MM-dd',alwaysIncludePattern: true}
]
}), 'cheese');
log4js.configure({
appenders: [{
type: "clustered",appenders: [{
type: "datefile", filename:"cheese.log",layout: {type:'basic'},
patterm: '.yyyy-MM-dd',alwaysIncludePattern: true}],
}]
});
clustered的配置很简单,就是一个appenders数组,里面配置一个真实地appender即可。
四、清除默认的console输出
log4js默认会加载console,并且其类别为all,意味着如果采用函数渐进方式来配置日志,那么所有的写日志操作,都会在控制台删除。要清除这种多余的逻辑很简单,只要在配置日志前调用 log4js.clearAppenders 函数清除掉所有的appender即可。而如果采用log4js.configure方式来配置,那么会configure函数内部就会调用log4js.clearAppenders,因此就不会产生控制台输出。
<span style="font-size:12px;"> log4js.clearAppenders();
log4js.loadAppender('clustered');
log4js.addAppender(log4js.appenderMakers['clustered']({
appenders: [{
type: "datefile", filename:"cheese.log",layout: {type:'basic'},
patterm: '.yyyy-MM-dd',alwaysIncludePattern: true}
]
}), 'cheese');</span>
Log4js总共三篇博客
《Log4js原理解析》http://blog.csdn.net/hfty290/article/details/42844085
《Log4js配置详解》http://blog.csdn.net/hfty290/article/details/42843737
《Log4js多进程陷阱与避免》http://blog.csdn.net/hfty290/article/details/42843303