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. 用tpcc测试对比 innodb 和 tokudb

    测试环境 1台IBM Intel(R) Xeon(R) CPU           E5606  @ 2.13GHz,内存12G cd tpcc/tpcc-mysql/src # make cc lo ...

  2. Python简单爬虫入门一

    为大家介绍一个简单的爬虫工具BeautifulSoup BeautifulSoup拥有强大的解析网页及查找元素的功能本次测试环境为python3.4(由于python2.7编码格式问题) 此工具在搜索 ...

  3. qt5.4.0编译错误

    error1: 进程"C:\Qt\Qt5.4.0\Tools\QtCreator\bin\jom.exe"退出,退出代码 2 solution:去工具->选项->构建和 ...

  4. Linux 下.desktop 桌面程序图标文件编写方式

    [Desktop Entry] //每个desktop文件都以这个标签开始,说明这是一个Desktop Entry文件 Version = 1.0 //标明Desktop Entry的版本(可选) N ...

  5. RubyMine优化设置

    RubyMine和IntelliJ默认的JVM -xmx参数太低了,占用的内存满了一GC,程序就假死了,把-xmx改大点就不容易假死了,配合SSD效果更好. [RUBYMINE_DIRECTORY]/ ...

  6. Android源码阅读-Filter过滤器

    Filter 顺便看看,Android中过滤器是怎么实现的? 注释中提到,Filter一般通过继承Filterable实现 具体实现 这是SimpleAdapter出现的一个过滤首字母item的一个过 ...

  7. 【原】HTML5 新增的结构元素——能用并不代表对了

    做移动端有一段时间,今天有同事问了我 article 和 section 标签的使用,模模糊糊的解释了下,他似懂非懂,有点小尴尬.忽然间觉得自己有必要再翻翻书籍,重温下 html5 的新元素.html ...

  8. COGS1008. 贪婪大陆[树状数组 模型转换]

    1008. 贪婪大陆 ★★   输入文件:greedisland.in   输出文件:greedisland.out   简单对比时间限制:1 s   内存限制:128 MB 试题四:贪婪大陆  [题 ...

  9. selenium自动化-java-封断言类2

    封装断言类 package streamax.com; import java.util.ArrayList; import java.util.List; import org.testng.Ass ...

  10. Java并发编程:Lock

    原文出处: 海子 在上一篇文章中我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包 ...