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. mysql 导出select语句结果到excel文件等

    一.导出数据外部 1)mysql连接+将查询结果输出到文件.在命令行中执行(windows的cmd命令行,mac的终端) mysql -hxx -uxx -pxx -e "query sta ...

  2. 自己开发一个 vsts agent 的 task

    vsts 中支持自定义Build/Release的过程Task 目标:做一个可以读取 Xamarin.Android 所生成的 APK 的 基本信息的 task ,包括 package(包名) / a ...

  3. 理解ThreadLocal(之二)

    想必很多朋友对ThreadLocal并不陌生,今天我们就来一起探讨下ThreadLocal的使用方法和实现原理.首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码 ...

  4. 解析ThreadLocal

    如果定义了一个单实例的java bean,它有若干属性,但是有一个属性不是线程安全的,比如说HashMap.并且碰巧你并不需要在不同的线程中共享这个属性,也就是说这个属性不存在跨线程的意义.那么不推荐 ...

  5. Spring中的JDK动态代理

    Spring中的JDK动态代理 在JDK1.3以后提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.在Sun刚推出动态代理时,还很难想象它有多大的实际用途,现在动态代理是实现AOP的绝好底层 ...

  6. Django调用JS、CSS、图片等静态文件

    zz 在下面的例子中,我们将media作为静态(CSS\JS\图片文件)文件的目录 方法一. 1.首先在settings.py文件中自定义参数 STATIC_PATH=’./media’ .(意为当前 ...

  7. [No000054] Windows 下Python3.5, NoteBook增强版安装

    接着上周继续,没看的童鞋.请移步: http://www.cnblogs.com/Chary/p/No00004B.html 这里,假设你已经能够看到这个画面了: 接下来,我们继续 给药 : 安装no ...

  8. OllyUni.dll

    OllyUni.dll 周银辉 好像很多人找不到OllyUni.dll ,下载在这里:http://www.phenoelit.org/win/index.html 注:在OllyDBG2.0中用不了 ...

  9. Computer assisted surgery

    Computer assisted surgery (CAS) represents a surgical concept and set of methods, that use computer ...

  10. 栈的理解以及如何计算程序所需栈的大小并在IAR中设置栈

    文章首发于浩瀚先森博客 #栈的理解 一个程序大体上讲都是由变量和函数组合而成,变量有全局变量和局部变量,还有函数间传值的参数以及返回值. Stack是为了程序运行过程中临时保存所需数据而在内存里分配的 ...