是否有多传输记录器在向控制台报告时保留原始文件中的调用位置?

Kir*_*tin 12 javascript logging

前言

一个已知的库Winston与许多其他不同的库有相同的问题,这些库用于多传输日志记录.当其中一个传输是console调试器控制台(浏览器或Node.js的任何环境)中报告的消息时,错过了非常强大的信息:启动初始调用的位置(开发人员的文件),而不是显示库内的调用位置.在这种情况下,来自不同文件/地点的多个呼叫都被报告为从同一个地方记录.

解决了尝试

我研究了两种方法.当他们推断出呼叫的地点时,一个是浏览器/节点上的技巧console.log.我发现它的唯一方法是通过源地图.这是一种技术,允许将缩小的js源映射到原始源并在查看完整源时进行调试.但是,这假设存在从真实(缩小)源到原始源的一个转换.如果在源console.log库中替换源代码,则mylogger应该是动态的并且反映mylogger.log被调用的多个位置.我没有找到一种方法来动态执行此操作,因为浏览器只加载一次地图文件.

另一个是用console.log自定义函数调用和内部替换所有其他传输(这可以是相同的Winston).但是,如果我们做如下的简单替换

var originalLog = console.log;
console.__proto__.log = function(message){
    message = [new Date().toISOString(), message].join(' ');
    originalLog.call(console, message);
//here send via other transports
    body.innerHTML = body.innerHTML + message + '<br/>';
};
Run Code Online (Sandbox Code Playgroud)

呼叫的位置originalLog将始终相同,并将在控制台输出中相应地报告.所以我想到拦截调用console.log但保留原始本机函数.但我没有得到呼叫的参数.

function interceptGettingLog(){
    var originalLog = console.log;
    Object.defineProperties(console.__proto__, {
        log: {
            get: function(){
//arguments is always empty here, which is not a big surprise
                originalLog.call(console, 'log accessed ' + JSON.stringify(arguments));
                return originalLog;
            }
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

问题简而言之

在调用时,是否有人知道不同的日志记录方法或浏览器/ Node.js的方法console.log?我们的目标是拥有一个多级多传输记录器,它可以在配置中切换冗长和传输(对于开发和生产来说会有所不同),具有完整的功能console.log并且同时具有整洁的语法,即单个功能在开发人员需要记录某事的地方打电话.谢谢阅读 :)

Kir*_*tin 1

到目前为止,这是我能想到的最好的解决方案。我认为它不干净,因为它强制调用行上的特定语法。但它有效。

function logInfo(){
//do multitransport multilevel logging on your decision
// for example, Winston
    var args = Array.prototype.slice.call(arguments);
    winston.log.apply(winston, args);
    if(levels.contains('console')){
//return a console.log function to call it in the 'right' place
        return console.log.bind.apply(console.log, [console].concat(args));
    }else{
//return a no-operation function to skip output to console
         return function nop(){};
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

...
logInfo('My message:', {foo:true, count: 100})();
...
Run Code Online (Sandbox Code Playgroud)

技巧是返回console.log与传递给主日志记录函数的参数绑定的值,并在调用主日志记录函数的同一位置调用它。这样我们就避免了重复代码:只记录指定的参数一次。主日志记录功能后面的括号()表示是否有输出到控制台。如果配置指示不输出到控制台,我们将返回一个空函数。

PS 我会考虑使用clean来替代console.log. 因此,您可以应用补丁,而无需通过调用修改现有代码console.log。但如果不重载就不可能实现这一点(),这在 ES5 中是不可能的。

使用参数数组调用的功劳bind转到@FelixKling /sf/answers/1505522931/