1.  使用

有两种方式使用winston,一是通过默认的logger,二是实例化自己的Logger,前者设计的目的是在应用程序中共享logger比较方便。

1.1 使用默认Logger

使用默认的logger很方便,直接通过winston模块获取,logger的任何方法都可以通过默认的logger实例得到。

var winston = require('winston');
winston.log('info','Hello distributed log files!');
winston.info('Hello distributed log files!');
winston.level = 'debug';
winston.log('debug','Now my debug message are written to console!'); 

默认情况logger仅仅只设置了console。可以通过add()和remove()来增加和清除其他处理方式。
winston.add(winston.transports.File,{filename:'somefile.log'});
winston.remove(winston.transports.Console);

或者使用configure()来配置。

winston.configure({
transports:[new (winston.transports.File)({filename:'somefile.log'})]
});

Winston更多处理方式的文档,可以查看Winston Transports文档。

1.2 自定义Logger

如果你想管理loggers对象的生存期,可以自定义logger对象。

 var logger =  new (winston.Logger)({
level:'info',
transports:[
new (winston.transports.Console)(),
new (winston.transports.File)({filename:'somefile.log'})
]
});

它和默认的logger工作方式一样。

logger.log('info','Hello distributed log files!');
logger.info('Hello distributed log files!');
logger.add(winston.transports.File)
 .remove(winston.transports.Console);

同样,使用configure方法也可以重新配置winston.Logger。

var logger =  new (winston.Logger)({
level:'info',
transports:[
new (winston.transports.Console)(),
new (winston.transports.File)({filename:'somefile.log'})
]
});
//替换以前整个transports通过一个新的配置
logger.configure({
level:'verbose',
transports:[
new (require('winston-daily-rotate-file'))(opts)
]
});

2.元数据处理

除了打印字符串信息,winston也能够打印JSON元数据,如下:

winston.log('info','Test Log Message',{anything:'This is metadata'});

不同的日志方式可能导致储存对象会发生变化,有一个比较好的方式去操作元数据:

1.Console:Logger via util.inspect(meta)
2.File:Logger via util.inspect(meta)

3.同种日志类型多种处理方式

通过定义,可以对相同transports的winston.transports.File设置多种不同level处理方式。

var logger = new (winston.Logger)({
transports:[
new (winston.transports.File)({
name : 'info-file',
filename:'filelog-info.log',
level:'info'
}),
new (winston.transports.File)({
name:'error-file',
filename:'filelog-error.log',
level:'error'
})
]
});

如果你想删除其中一种处理方式,可以如下:

logger.remove("info-file");

在这个例子中也可以通过删除Transport本身获得相同的效果:

var infoFile = logger.transports[0];
logger.remove(infoFile);

4.分析

除了对消息和元数据进行处理之外,winston对任何logger也有一个简单的分析机制:

//开始分析test,
//使用Date.now()来标记一个异步操作
winston.profile("test");
setTimeout(function(){
//结束分析test
winston.profile('test');
},1000)
//info: test durationMs=1001

所有分析信息默认设置为'info',在这个配置中消息和元数据都是可选的,没有明显的区别,但是我还是说出这个建议或者问题。

5.字符串插值

log提供和util.format一样的字符串插值方法,允许这样打印信息:

logger.log('info','test message %s', 'my string');
//info: test message my string
logger.log('info','test message %d',123);
//info: test message 123
logger.log('info','test message %j',{number:123},{});
//info: test message {"number":123}
logger.log('info','test message %s, %s','first','second',{number:123});
//info: test message first, second number=123
logger.log('info','test message', 'first', 'second', {number:123});
//info: test message first second number=123
logger.log('info','test message %s,%s','first','second',{number:123},function(){});
//info: test message first,second number=123
logger.log('info','test message', 'first','second',{number:123},function(){});
//info: test message first second number=123

6.查询日志

winston提供查询日志接口,和Logger-like类似,具体可以查看Loggly Search API.

var options = {
from:new Date - 24 * 60 * 60 * 1000,
util:new Date,
limit:10,
start:0,
order:'desc',
fields:['./somefile.log']
};
/*
找出昨天到今天的日志
*/
winston.query(options,function(err,results){
if(err){
throw err;
}
console.log(results);
});

7.日志流

streaming允许从你选择的处理方式流水返回日志。

winston.stream({start: -1}).on('log',function(log){
console.log(log);
});

异常

winston可以在进程中捕获和记录uncaughtException事件。

有两种不同方法能实现这个功能,分别是在默认的logger实例和自定义的实例。

如果你想通过默认的logger来使用这个特征,调用实例的.handleExceptions的方法

//你能增加一个单独的异常日志给.handleException

winston.handleException(new winston.transports.File({
filename:'path/to/exception.log'
}));
//也可以设置.handleException为true当你增加一个处理方式给winston
//可以使用.humanReadableUnhandledException选项或者更多可读的异常 winston.add(winston.transports.File,{
filename:'path/to/all-logs.log',
handleException:true,
humanReadableUnhandledException:true
}); //多个处理方式也能被异常操纵 winston.handleException([transports1,transports2,....]);

 退出和不退出

默认情况下,winston会退出如果记录到一个未捕获异常之后,如果不想退出。设置exitOnError =  false

var logger = new (winston.Logger)({
exitOnError:false
});
//或者这样
logger.exitOnError = false;

当自定义logger实例,你可以给一个处理方式传递exceptionHandlers属性或者在任何处理方式设置handlerExceptions。

例子1:

var logger = new (winston.Logger)({
transports:[
new winston.transports.File({
filename:'path/to/all-logs.log'
})
],
exceptionHandlers:[
new winston.transports.File({
filename:'path/to/exceptions.log'
})
]
});

例子2:

var logger = new (winston.Logger)({
transports:[
new winston.transports.Console({
json:true,
handleException:true
})
],
exitOnError:false
});

exitOnError选项也可以是一个函数,能防止某些错误的类型二退出。

function ignoreEpipe(err){
return err.code !== 'EPIPE';
}
var logger = new (winston.Logger)({
exitOnError:ignoreEpipe
});
//或者像这样:
logger.exitOnError = ignoreEpipe; 

日志等级

这个很简单了

进一步阅读

winston的事件和回调

每一个winston.Logger实例也都是一个EventEmitter实例,一个log事件被触发当写日志成功。

logger.on('logging',function(transport,level,msg,meta){
//msg和meta已经用level记录在[transport]
});
logger.info('CHILL WINSTON',{seriously:true});

值得一提的是,logger还能触发一个“错误”事件,如果你不想操作异常,你可以用来处理或者忽略它

logger.on("error",function(err){
/* do something */
});
//或者忽略它
logger.emitErrs = false;

每个logging方法在最后一个字段也有一个可选的回调函数,它触发当所有的transports已经特殊信息完毕

logger.info('CHILL WINSTON',{seriously:true},function(err.level.msg,meta)){
//msg和meta已经用level记录在[transport]
}

多个winston类目的日志

常常在一个大的,比较复杂的应用中是非常必要使用多个日志实例。每个日志对应不同的特性或者类型,winston有两种方式来处理:

通过winston.loggers或者winston.Container的实例。事实上,winston.loggers也是winston.Container预先定义的实例。

winston.loggers.add('category1',{
console:{
level:'silly',
colorize:true,
label:'category one'
},
file:{
filename:'/path/to/some/file'
}
}); winston.loggers.add('category2',{
couchdb:{
host:'127.0.0.1',
port:5984
}
});

注意:在应用中,你要访问你预配置的logger,你需要require("winston")在你的文件中。

var winston = require("winston");

var category1 = winston.loggers.get('category1');
category1.info('logging from you Ioc Contains-based logger'); 

如果你喜欢Container你可以实例化

var winston = require("winston"),
container = new winston.container(); container.add('category1',{
console:{
level:"silly",
colorize:true
},
file:{
filename:'path/to/some/file'
}
})

过滤和重写

过滤允许修正日志消息的内容,重写允许修改日志元数据,即掩盖日志中不出现的数据。

过滤和重写都是一个函数数组,它被创建一个winston.Logger对象时被提供。

var logger = new winston.Logger({
rewriters:[function(level,msg,meta){}],
filters:[function(level,msg,meta){}]
});

就像其他数组一样,修改日志能运行在winston内部,也没有什么副作用。

var logger = new winston.Logger({
rewriters:[function(level,msg,meta){}],
filters:[function(level,msg,meta){}]
});
logger.filters.push(function(level,msg,meta){
return meta.production ? maskCardNumbers(msg) :msg;
});
logger.info('transaction with card number 1234567890123456 successful');

这个输出的结果可能是:

info:transaction with card number 123456****2345 successful

而重写,你想把creditCard元数据重新实例化:

logger.rewriters.push(function(level,msg,meta){
if(meta.creditCard){
meta.creditCard = maskCardNumbers(meta.creditCard);
}
return meta;
}); logger.info('transaction ok',{creditCard:123456789012345});

输出结果可能是:

info:transaction ok creditCard=123456****2345

增加自定义日志处理方式

增加一个自定义处理方式非常简单,所有需要做的是接受一些选项,设置名字,执行log()方法,和winston暴露的一些transports(处理方式)

var util = require('util'),
winston = require('winston'); var CustomLogger = winston.transports.CustomLogger = function(options){
//logger的名字
this.name = 'customLogger';
//选项设置一个等级
this.level = options.level || "info";
//配置你想要的处理方式
}
// 继承winston.Transports,你能利用基本函数和.handlerExceptions()
util.inherit(CustomLogger,winston.Transports);
CustomLogger.prototype.log = function(level,msg,meta,callback){
callback(null,true);
}

自定义日志格式

指定自定义格式应该为transport设置格式化函数,目前支持格式化的transports是:Console, File和Memory。可选对象作为参数传递给格式化对象。

一般属性有:时间戳、等级、消息、和元数据,取决于transports类型可能会有额外的属性。

var logger =  new (winston.Logger)({
transports:[
new (winston.transports.Console)({
timestamp:function(){
return Date.now();
}
formatter:function(options){
//返回字符串给logger
return options.timestamp() + ' ' +options.level.toUpperCase() + ''
(options.message ? options.message: "") + (options.meta && Object.keys(options.meta).length ?
'\n\t' + JSON.string(options.meta):"");
}
});
]
});
logger.info('Data to log');

winston写日志(译)的更多相关文章

  1. .NET Core的日志[5]:利用TraceSource写日志

    从微软推出第一个版本的.NET Framework的时候,就在“System.Diagnostics”命名空间中提供了Debug和Trace两个类帮助我们完成针对调试和跟踪信息的日志记录.在.NET ...

  2. [转]ASP.NET Core 开发-Logging 使用NLog 写日志文件

    本文转自:http://www.cnblogs.com/Leo_wl/p/5561812.html ASP.NET Core 开发-Logging 使用NLog 写日志文件. NLog 可以适用于 . ...

  3. Spring 使用 SLF4J代替 Commons Logging 写日志 异常

    项目的日志更换成slf4j和logback后,发现项目无法启动.错误提示 Caused by: java.lang.NoClassDefFoundError: Lorg/apache/commons/ ...

  4. 程序员的修养 -- 如何写日志(logging)

      在程序中写日志是一件非常重要,但是很容易被开发人员忽视的地方.写好程序的日志可以帮助我们大大减轻后期维护压力. 在实际的工作中,开发人员往往迫于的巨大时间压力,而写日志又是一个非常繁琐的事情,往往 ...

  5. ASP.NET Core 开发-Logging 使用NLog 写日志文件

    ASP.NET Core 开发-Logging 使用NLog 写日志文件. NLog 可以适用于 .NET Core 和 ASP.NET Core . ASP.NET Core已经内置了日志支持,可以 ...

  6. 2.2 代码块--delphi 写日志模块

    //2.2 代码块--写日志 //调用例句如:LogMsg('FTP上传线程终止',False,true); procedure LogMsg(AMsg: string; const blnIsErr ...

  7. php大力力 [041节] 今天没有写日志哈

    php大力力 [041节]  今天没有写日志哈  如何下拉,左边的side颜色  能顺延下去?? 今天做了一个表格显示

  8. 转:NLog 自定义日志内容,写日志到数据库;修改Nlog.config不起作用的原因

    转:http://www.cnblogs.com/tider1999/p/4308440.html NLog的安装请百度,我安装的是3.2.NLog可以向文件,数据库,邮件等写日志,想了解请百度,这里 ...

  9. How To Write In Sharepoint Log File 怎么对自定义的MOSS代码写日志

    How To Write In Sharepoint Log File 怎么对自定义的MOSS代码写日志 Add Microsoft.Office.Server dll in your project ...

随机推荐

  1. thrift的lua实现

    最近要进行系统升级,后台的数据是根据城市区分的.担心新系统的稳定性及新数据的准确性,计划部分城市采用新接口.接口的入参里没有城市信息,只有经纬度坐标,需要调用一个thrift接口来根据坐标获取城市信息 ...

  2. eclipse svn分支与合并操作

    以前做项目的时候没有用过svn的分支合并操作,今天用到了,刚开始还真不会啊.最后查了下就是这么的方便.专门记录下来. 原文来自:http://blog.csdn.net/lisq037/article ...

  3. Apache配置

    redhat6.4企业版用的centos的yum源. 下面进行apache的安装与配置. 1.yum在线安装Apache 一般不采用yum在线安装因为如果apache坏掉了,yum安装过程中会有依赖的 ...

  4. web也是区分前端与后端的,session\cookie辨析

    <1>Ajax交互方式 Ext.Ajax.request( { //被用来向服务器发起请求默认的url url : "", //请求时发送后台的参数,既可以是Json对 ...

  5. [转]html超链接打开的窗口大小

    <a href="#" onclick="javascript:window.open('http://www.baidu.com','','height=20,w ...

  6. 关于C语言的问卷调查

    你对自己的未来有什么规划?做了哪些准备? 答:游戏开发,参与一些游戏的测试,通过自身的游戏体验和其他人的游戏体验来总结什么样的游戏会让人眼前一亮,爱不释手. 你认为什么是学习?学习有什么用?现在学习动 ...

  7. HDU 1729 Stone Game【SG函数】

    以下转载至:长春理工大学赵小舟博弈论ppt 题目大意: 1.有n个盒子,每个盒子都有它的容量s 2.在游戏开始时,每个盒子里都有一些石子 3.双方轮流进行游戏,向一个盒子投入n个石子,其中n不能大于当 ...

  8. UNIX系统基本结构

    UNIX系统的基本结构如图所示.整个UNIX系统可分为五层:最底层是裸机,即硬件部分:第二层是UNIX的核心,它直接建立在裸机的上面,实现了操作系统重要的功能,如进程管理.存储管理.设备管理.文件管理 ...

  9. java多线程系类:JUC线程池:04之线程池原理(三)(转)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--"基础篇& ...

  10. Enum简单例子DropdownList

    借鉴:http://www.cnblogs.com/suizhikuo/archive/2013/06/07/3125225.html vs2012 mvc4 最终效果: 1.建立mvc4 Inter ...