nodejs之日志管理
开发一个项目时,可以通过控制台输出或者debug来获取到项目的运行信息。当项目上线时,我们就需要通过日志来分析。如同Java的log4j,nodejs中也有相关的log4js。使用过log4j的同学应该对此不会陌生。
1、日志级别
log4js共有6种日志级别,分别为:trace、debug、info、warn、error、fatal。权值从小到大,其初始化代码为:
TRACE: new Level(5000, "TRACE"),
DEBUG: new Level(10000, "DEBUG"),
INFO: new Level(20000, "INFO"),
WARN: new Level(30000, "WARN"),
ERROR: new Level(40000, "ERROR"),
FATAL: new Level(50000, "FATAL"),
假如设置默认的日志级别为info,那么权值小于info的日志不会被记录下来,也就是说只有调用log.info(), log.warn(), log.error()或者log.fatal()才会触发记录日志。该部分代码在lib/logger.js中。
Logger.prototype.log = function() {
var args = Array.prototype.slice.call(arguments)
, logLevel = levels.toLevel(args.shift())
, loggingEvent;
if (this.isLevelEnabled(logLevel)) {
loggingEvent = new LoggingEvent(this.category, logLevel, args, this);
this.emit("log", loggingEvent);
}
};
2、集成express
log4js可以作为express的一个中间件来使用。首先需要引入log4js
var express = require("express");
var log4js = require("log4js"); var app = express();
接着配置log4js
log4js.configure({
appenders: [
{ type: 'console' },
{ type: 'file', filename: 'cheese.log', category: 'cheese' }
]
});
该配置的意思是console是默认的appender,使用cheese这个appender时会将日志记录文件中,日志文件名为cheese.log。
然后用use连接到中间件,我们默认使用的是cheese这个appender,级别为info。
app.use(log4js.connectLogger(log4js.getLogger("cheese"), {level: log4js.levels.INFO}));
其输出与此类似:
[2014-07-04 20:27:21.205] [INFO] cheese - 127.0.0.1 - - "GET / HTTP/1.1" 200 22896 "" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36"
......
3、再修改一下中间件
上面的做法是可以的,只是当中间件太多的时候,都写在同一个文件中也许感觉会有些丑陋。所以我倾向于将其分离出来作为单独的一个模块,也就是一个单独的文件。然后对外暴露接口。
var path = require("path");
var log4js = require("log4js"); /**
* 日志配置
*/
exports.configure = function() {
log4js.configure(path.join(__dirname, "log4js.json"));
} /**
* 暴露到应用的日志接口,调用该方法前必须确保已经configure过
* @param name 指定log4js配置文件中的category。依此找到对应的appender。
* 如果appender没有写上category,则为默认的category。可以有多个
* @returns {Logger}
*/
exports.logger = function(name) {
var dateFileLog = log4js.getLogger(name);
dateFileLog.setLevel(log4js.levels.INFO);
return dateFileLog;
} /**
* 用于express中间件,调用该方法前必须确保已经configure过
* @returns {Function|*}
*/
exports.useLog = function() {
return log4js.connectLogger(log4js.getLogger("app"), {level: log4js.levels.INFO});
}
log4js.json文件内容如下
{
"appenders": [
{
"type": "console"
},
{
"type": "dateFile",
"filename": "logs/booklist.log",
"pattern": "-yyyy-MM-dd",
"alwaysIncludePattern": true
}
]
}
配置很简单,配置了两个appender,一个是控制台的,一个是dateFile,意思是每天都产生一个日志文件。注意到我这里并没有配置category,这样的话当没有找到对应的appender时,这两个appender就是默认的appender。有些时候明明感觉配置没有错,但是日志文件并没有产生日志,往往问题就出在这里。
然后在app.js中我们修改为如下
var express = require("express");
// 这个是我们上面自定义的模块
var log4js = require("./log"); var app = express();
app.configure(); app.use(log4js.useLog()); ...
4、单进程与多进程
好了,上面对于单进程是适用的,但是如果你的nodejs应用是多进程的,使用上面的配置你会看到日志的输出有点奇怪,比如:
感觉有点像是资源抢占了。
log4js的wiki中有给出multiprocess的配置。但是当时使用的时候也会有问题,当时没有细究。不过社区中有人建立了另外一种方式,我采用了这种。可以参看一下这个issue。下面我们来配置一下。修改我们在上面修改的log模块文件,变为:
var path = require("path");
var log4js = require("log4js"); /**
* 多进程的日志配置
*/
exports.configure = function(mode) {
if (mode === "master") {
log4js.configure(path.join(__dirname, "./log4js-master.json"));
} else {
// 多进程的配置项
log4js.configure(path.join(__dirname, "./log4js-worker.json"));
// 单进程的配置项
// log4js.configure(path.join(__dirname, "../config/log4js.json"));
}
} /**
* 暴露到应用的日志接口,调用该方法前必须确保已经configure过
* @param name 指定log4js配置文件中的category。依此找到对应的appender。
* 如果appender没有写上category,则为默认的category。可以有多个
* @returns {Logger}
*/
exports.logger = function(name) {
var dateFileLog = log4js.getLogger(name);
dateFileLog.setLevel(log4js.levels.INFO);
return dateFileLog;
} /**
* 用于express中间件,调用该方法前必须确保已经configure过
* @returns {Function|*}
*/
exports.useLog = function() {
return log4js.connectLogger(log4js.getLogger("app"), {level: log4js.levels.INFO});
}
主要是修改了configure方法。
log4js-master.json的内容为:
{
"appenders": [{
"type": "clustered",
"appenders": [
{
"type": "console"
},
{
"type": "dateFile",
"filename": "logs/booklist.log",
"pattern": "-yyyy-MM-dd",
"alwaysIncludePattern": true,
"pollInterval": 1,
"category": "dateFileLog"
}
]
}]
}
log4js-worker.js的内容为:
{
"appenders": [{
"type": "clustered"
}]
}
假设主进程的内容在文件master.js,工作进程在worker.js。master.js中的配置内容为:
var log4js = require("./lib/log");
log4js.configure("master");
worker.js的配置内容为:
var express = require("express");
// 这个是我们上面自定义的模块
var log4js = require("./log"); var app = express();
app.configure("worker"); app.use(log4js.useLog()); ...
如此就完成了。
需要在某个地方记录日志的时候,我们可以如此
var log = require("./log").logger("index"); // logger中的参数随便起
...
log.info("...");
log.error("...")
5、写在后面
log4js还有挺多好玩的内容,比如smtp。这是个很有用的功能,比如当项目发生某个错误时,你希望程序能发邮件通知你,该功能就能派出用场了。
另外,我开源了一个项目booklist。该项目主要在于探讨nodejs建立应用所需要或者注意的地方,非常期待各位指导与探讨,谢谢!
参考
https://github.com/nomiddlename/log4js-node
https://github.com/gcfeng/booklist
nodejs之日志管理的更多相关文章
- Atitit php java python nodejs错误日志功能的比较
Atitit php java python nodejs错误日志功能的比较 1.1. Php方案 自带 1 1.2. Java解决方案 SLF4J 1 1.3. Python解决方案 自带lo ...
- Nodejs日志管理包
Nodejs日志管理工具包:log4js 和 winston 1.log4js的使用 1)package.json中加入依赖 "log4js":"~0.6.21" ...
- node 日志管理log4js
node 日志管理log4js 一.默认的控制台输出 我们使用express框架时,开发模式用node或者supervisor启动nodejs应用时,控制台都是显示如下的日志. GET /css/bo ...
- 第13章 Linux日志管理
1. 日志管理 (1)简介 在CentOS 6.x中日志服务己经由rsyslogd取代了原先的syslogd服务.rsyslogd日志服务更加先进,功能更多.但是不论该服务的使用,还是日志文件的格式其 ...
- ABP(现代ASP.NET样板开发框架)系列之8、ABP日志管理
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之8.ABP日志管理 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)” ...
- 【Java EE 学习 76 下】【数据采集系统第八天】【通过AOP实现日志管理】【日志管理功能分析和初步实现】
一.日志管理相关分析 1.日志管理是一种典型的系统级别的应用,非常适合使用spring AOP实现. 2.使用日志管理的目的:对系统修改的动作进行记录,比如对权限.角色.用户的写操作.修改操作.删除操 ...
- ElasticSearch+NLog+Elmah实现Asp.Net分布式日志管理
本文将介绍使用NLOG.Elmah结合ElasticSearch实现分布式日志管理. 一.ElasticSearch简介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布 ...
- Apache 日志管理,获取客户端端口号
日志管理分类 日志文件是用户管理和监控 Apache 安全的非常好的第一手资料,它清晰地记录了客户端访问 Apache 服务器资源的每一条记录,以及在访问中出现的错误信息,可以这样说,Apache 可 ...
- linux 学习 14 日志管理
第十四讲 日志管理 14.1 日志管理-简介 .日志服务 在CentOS .x中日志服务已经由rsyslogd取代了原先的syslogd服务.rsyslogd日志服务更加先进,功能更多.但是不论该服 ...
随机推荐
- EnumWindows 使用
转载自csdn:http://blog.csdn.net/hairi/article/details/548064 EnumWindows 用来列举屏幕上所有顶层窗口. MSDN原话: The E ...
- Android本地JUnit Text
Android本地JUnit Text 步骤 创建一个和source文件,里面添加和src目录相同的包. 在AndroidManifest.xml文件manifest根节点添加如下文件 <ins ...
- ORACLE里的自增字段设置
大家都知道吧,这很坑,尤其是用惯了mysql里的自增字段设置,结果oracle里面没有的.oh,no 我用的是12c版本的,它有一个新特性,可以这样设置自增序列,在创建表是,把id设置为自增序列 cr ...
- 查看Safari和钥匙串中的密码
Safari Safari的同步书签功能很棒,还可以看到其他设备没关掉的网页.为了省时间,一些经常进的网站,比如博客,邮箱等,我都会选择让Safari保存密码,还使用iCloud同步!因为一直很放心苹 ...
- 校省选赛第一场A题Cinema题解
今天是学校省选的第一场比赛,0战绩收工,死死啃着A题来做,偏偏一直WA在TES1. 赛后,才发现,原来要freopen("input.txt","r",stdi ...
- angularjs应用骨架(2)
时隔一个星期,接着上一篇的angularjs应用骨架继续聊聊angularjs其他的其他的内容. 区分UI和控制器的职责 在应用控制器中有三种职责: 1.为应用中模型设置初始状态 2.通过$scope ...
- linux安装git方法(转)
转自:http://jingyan.baidu.com/article/e9fb46e16698687521f766ec.html 以下内容亲测,确实可行. 由于我的机器是linux6.7,所以省略了 ...
- 更改css element.style
样式后面加 !important就可以更改element.style的优先级了
- 如何在Webstorm中添加js库 (青瓷H5游戏引擎)
js等动态语言编码最大的缺点就是没有智能补全代码,webstorm做到了. qici_engine作为开发使用的库,如果能智能解析成提示再好不过了,经测试80%左右都有提示,已经很好了. 其他js库同 ...
- 《JavaScript高级程序设计 第3版》-学习笔记-2
P31-P82页 1.相等不相等与全等不全等 相等不相等:先转换后比较.对于只有一个对象,调用valueOf方法得到基本类型值再按基本类型转换:如果两个都是对象,则比较他们是否是同一个对象(引用或指针 ...