警告
我认为 winston 的预期用途是首先记录字符串消息和(如果需要)附加元信息。此外,我不太明白您为什么要记录从 mongo 返回的整个集合,而不是 - 比如说 - 只是_id
s (假设docs
可能很大)。
介绍
我查看了winston
源代码,以下是相关部分:
温斯顿/logger.js
Logger.prototype.log = function (level) {
var self = this,
args = Array.prototype.slice.call(arguments, 1);
...
var callback = typeof args[args.length - 1] === 'function' ? args.pop() : null,
meta = typeof args[args.length - 1] === 'object' ? args.pop() : {},
msg = util.format.apply(null, args);
...
}
基本上,类型的单个参数object
被解释为元。控制台传输层(默认)主要定义在winston/common.js中,下面是 meta 的处理方式:
... if (Object.keys(meta).length > 0) {
output += ' ' + (
options.prettyPrint
? ('\n' + util.inspect(meta, false, null, options.colorize))
: exports.serialize(meta)
);
}
serialize方法迭代(递归)对象的所有键以形成最终字符串(而不是调用.toString
或类似方法)。
建议的解决方案
两种解决方案都强制winston 将单个对象参数解释为元数据,而不是消息字符串。
如果您想支持不同的传输层,则必须对其进行修改。
更改winston源代码
只需 fork 存储库并对源代码进行相关更改。有很多方法可以实现它。一个丑陋的可能是:
meta = args.length === 1 ? {} :
(typeof args[args.length - 1] === 'object' ? args.pop() : {}),
但是.serialize
如果对象是芒果模型,最好在方法中添加特殊情况进行特殊处理,非常幼稚和不正确:
else if ('_doc' in obj && 'save' in obj){
var result = [];
msg += '{'
for(var key in obj['_doc']){
result.push (key + ':' + obj['_doc'][key]);
}
msg += result.join(', ');
msg += '}';
}
(不幸的是,这种方法存在问题,因为 winston 复制了元数据,并且原型链中定义更高的所有方法都丢失了——否则它会像调用一样简单,obj.toJSON
并且肯定会是最优雅和最强大的解决方案)
覆盖winston默认行为
var original = winston.log;
winston.log = function(){
if(arguments.length === 2){
original.call(winston, arguments[0], arguments[1], {});
}
else {
original.apply(winston, arguments);
}
}
说明:arguments[0]
定义级别,因此arguments[1]
是要记录的实际对象。