扩展console.log而不影响日志行

我想扩展“console.log”函数来添加额外的信息到输出 – 但我不想影响浏览器在控制台窗口中生成的脚本名称/行号信息。 看看如果我创build我自己的实现,我得到无用的跟踪信息,我应该find该代码区域…(他们都链接到日志实现,而不是引起日志消息的实际脚本)

在这里输入图像说明

基本上,我的应用程序是一个非常可插拔的基础设施,任何日志输出可能发生在任何数量的帧。 因此,我希望每条日志消息在日志消息的开头都包含一个特殊的唯一标识符。

我已经尝试用我自己的replaceconsole.log方法,但是chrome抱怨Uncaught TypeError: Illegal invocation

这是我重写它

 var orig = console.log; console.log = function( message ) { orig( (window == top ? '[root]' : '[' + window.name + ']') + ': ' + message ); } 

有任何想法吗?

[编辑]注:解决“非法调用”的问题后,似乎文件名/ linenumber仍然“被污染”的覆盖…

[编辑]它看起来像一般的答案是 – 没有 – 尽pipe一些令人困惑的鹅追逐,所需的function是无法实现在当前版本的浏览器。

是的,可以添加信息而不会搞乱日志调用的起始行号。 这里的其他一些答案接近,但诀窍是让您的自定义日志logging方法返回修改logging器。 下面是一个简单的例子,只是使用上下文变体进行了适度的testing。

 log = function() { var context = "My Descriptive Logger Prefix:"; return Function.prototype.bind.call(console.log, console, context); }(); 

这可以用于:

 log("A log message..."); 

这里是一个jsfiddle: http : //jsfiddle.net/qprro98v/

人们可以很容易地获得创意并传递上下文variables,并从函数定义中移除自动执行的parens。 即日志(“DEBUG:”)(“debugging信息”),日志(“信息:”)(“这是一些信息”),等等。

关于函数的唯一真正导入部分(关于行号)是它返回logging器。

如果你的用例可以处理一些限制,那么一种方法可以使之工作。 这些限制是:

  • 额外的日志内容必须在绑定时计算; 它不能对时间敏感或以任何方式依赖于传入的日志消息。

  • 额外的日志内容只能放在日志消息的开头。

有了这些限制,以下可能适用于您:

 var context = "ALIASED LOG:" var logalias; if (console.log.bind === 'undefined') { // IE < 10 logalias = Function.prototype.bind.call(console.log, console, context); } else { logalias = console.log.bind(console, context); } logalias('Hello, world!'); 

http://jsfiddle.net/Wk2mf/

至less在铬中是可行的。 这是最相关的。 这可能会有所不同,这取决于设置,我如何得到分裂是只logging整个堆栈,并find我需要的信息。

  var stack = new Error().stack; var file = stack.split("\n")[2].split("/")[4].split("?")[0] var line = stack.split("\n")[2].split(":")[5]; 

这是整个事情,保留本地对象日志logging。

 var orig = console.log console.log = function(input) { var isChrome = navigator.userAgent.indexOf("Chrome") !== -1; if(isChrome){ var stack = new Error().stack; var file = stack.split("\n")[2].split("/")[4].split("?")[0] var line = stack.split("\n")[2].split(":")[5]; var append = file + ":" + line; } orig.apply(console, [input, append]) } 

您需要使用正确的上下文( console )调用console.log

 orig.call(console, message); 

要完成允许多个参数的函数:

 var orig = console.log; console.log = function() { var msgs = [], prefix = (window== top ? '[root]' : '[' + window.name + ']'); while(arguments.length) { msgs.push(prefix + ': ' + [].shift.call(arguments)); } orig.apply(console, msgs); }; 

演示: http : //jsfiddle.net/je2wR/

请记住,当使用+号将对象与string组合在一起时,将释放控制台中的内置对象/数组浏览器。

我只是回答了这个问题,帮助我回答了原来的“别名”问题:

http://stackoverflow.com/a/12942764/401735);

 my_log_alias = console.log.bind(console) 

显然,这样做的能力已经被devise。 作品。

此后my_log_alias与console.log相同,可以用同样的方法调用; 从函数内调用此函数将报告该函数调用的行号,包括适用的别名或通知函数中的行。

具体来说,Chrome提供的线路号会告诉您线路所在的文件,因此您正在做的事情可能是不必要的; 考虑把它报告为一个在chrome中的bug /function请求,它在console.log中提供这个信息。

一个可接受的解决scheme可以是使自己的日志function,返回一个console.log函数与日志参数绑定。

 log = function() { // Put your extension code here var args = Array.prototype.slice.call(arguments); args.unshift(console); return Function.prototype.bind.apply(console.log, args); } // Note the extra () to call the original console.log log("Foo", {bar: 1})(); 

克里斯托弗·柯里提供了一个很好的解 我已经扩大了一点为我的需要。 这是AMD模块:

 define([], function () { var enableDebug = true; var separator = ">"; function bind(f, thisArg, ctx) { if (f.bind !== 'undefined') { // IE < 10 return Function.prototype.bind.call(f, thisArg, ctx); } else { return f.bind(thisArg, ctx); } } function newConsole(context, parentConsole) { var log; var debug; var warn; var error; if (!parentConsole) { parentConsole = console; } context = context + separator; if (enableDebug) { debug = bind(console.log, console, context + "DEBUG" + separator); } else { debug = function () { // suppress all debug messages }; } log = bind(console.log, console, context); warn = bind(console.warn, console, context); error = bind(console.error, console, context); return { debug: debug, info: log, log: log, warn: warn, error: error, /* access console context information */ context: context, /* create a new console with nested context */ nest: function (subContext) { return newConsole(context + subContext, this); }, parent: parentConsole }; } return newConsole(""); }); 

默认情况下,这将输出> {message} 。 你也可以为你的日志添加嵌套上下文,例如console.nest("my").log("test")会输出>my> test

我还添加了一个debugfunction,可以用>DEBUG>缩进信息

希望有人会觉得有用。

我已经看了几次,总是发现这是不可能的。

我的解决方法如果你感兴趣的是将控制台分配给另一个variables,然后把我所有的日志消息包裹在一个函数,让我修改/样式/消息。

它看起来不错,CoffeeScript,不知道它与纯JS的实用性。

我只是习惯于用x来加前缀。

 logger.debug x 'Foo' log x 'Bar' log x('FooBar %o'), obj 

不幸的是,这是不可能的,将来我们可以用ECMAScript 6中的代理对象来实现。

我的用例是自动为控制台消息加上有用的信息,比如传递参数和执行方法。 目前最接近的是使用Function.prototype.apply

一个简单的方法就是像这样编写你的debugging语句:

 console.info.apply(console, ['=== LazyLoad.css(', arguments ,'): css files are skipped, gives us a clean slate to style within theme\'s CSS.']); 

一个复杂的方法是按照下面的方式使用帮助函数,我个人现在更喜欢简单的方法。

扩展“console.debug”功能的方法

 /* Debug prefixing function * =========================== * * A helper used to provide useful prefixing information * when calling `console.log`, `console.debug`, `console.error`. * But the catch is that to utilize one must leverage the * `.apply` function as shown in the below examples. * * ``` * console.debug.apply(console, _fDebugPrefix(arguments) * .concat('your message')); * * // or if you need to pass non strings * console.debug.apply(console, _fDebugPrefix(arguments) * .concat('json response was:', oJson)); * * * // if you need to use strict mode ("use strict") one can't * // extract the function name but following approach works very * // well; updating the name is just a matter of search and replace * var aDebugPrefix = ['fYourFunctionName(' * ,Array.prototype.slice.call(arguments, 0), * ,')']; * console.debug.apply(console, * aDebugPrefix.concat(['json response was:', oJson])); * ``` */ function _fDebugPrefix(oArguments) { try { return [oArguments.callee.name + '(' ,Array.prototype.slice.call(oArguments, 0) , ')']; } catch(err) { // are we in "use strict" mode ? return ['<callee.name unsupported in "use strict">(' ,Array.prototype.slice.call(oArguments, 0) , ')']; } } 

我遇到了这个问题,关于扩展console.log(),以便应用程序可以扩展,控制和花哨的东西,除了logging的东西到控制台。 丢失行号信息无异于失败​​。 在解决这个问题之后,我提出了一个冗长的解决方法,但至less它仍然是一个“单线程”使用。

首先,定义一个全局类来使用或添加一些方法到你现有的主要“应用”类:

 /** * Log message to our in-app and possibly on-screen console, return args. * @param {!string} aMsgLevel - one of "log", "debug", "info", "warn", or "error" * @param {any} aArgs - the arguments to log (not used directly, just documentation helper) * @returns args so it can be nested within a console.log.apply(console,app.log()) statement. */ MyGlobalClassWithLogMethods.prototype.debugLog = function(aMsgLevel, aArgs) { var s = ''; var args = []; for (var i=1; i<arguments.length; i++) { args.push(arguments[i]); if (arguments[i]) s += arguments[i].toString()+' '; } if (typeof this.mLog === 'undefined') this.mLog = []; this.mLog.push({level: aMsgLevel, msg: s}); return args; }; MyGlobalClassWithLogMethods.prototype.log = function() { var args = ['log'].concat(Array.prototype.slice.call(arguments)); return this.debugLog.apply(this,args); }; MyGlobalClassWithLogMethods.prototype.debug = function() { var args = ['debug'].concat(Array.prototype.slice.call(arguments)); return this.debugLog.apply(this,args); }; MyGlobalClassWithLogMethods.prototype.info = function() { var args = ['info'].concat(Array.prototype.slice.call(arguments)); return this.debugLog.apply(this,args); }; MyGlobalClassWithLogMethods.prototype.warn = function() { var args = ['warn'].concat(Array.prototype.slice.call(arguments)); return this.debugLog.apply(this,args); }; MyGlobalClassWithLogMethods.prototype.error = function() { var args = ['error'].concat(Array.prototype.slice.call(arguments)); return this.debugLog.apply(this,args); }; //not necessary, but it is used in my example code, so defining it MyGlobalClassWithLogMethods.prototype.toString = function() { return "app: " + JSON.stringify(this); }; 

接下来,我们把这些方法使用如下:

 //JS line done as early as possible so rest of app can use logging mechanism window.app = new MyGlobalClassWithLogMethods(); //only way to get "line info" reliably as well as log the msg for actual page display; // ugly, but works. Any number of params accepted, and any kind of var will get // converted to str using .toString() method. console.log.apply(console,app.log('the log msg')); console.debug.apply(console,app.debug('the log msg','(debug)', app)); console.info.apply(console,app.info('the log msg','(info)')); console.warn.apply(console,app.warn('the log msg','(warn)')); console.error.apply(console,app.error('the log msg','(error)')); 

现在控制台获取日志消息及其相应的行信息,以及我们的应用程序包含可以使用的日志消息的数组。 例如,要使用HTML,JQuery和一些CSS来显示你的应用内日志,可以使用下面的简单例子。

首先,HTML:

 <div id="debug_area"> <h4 class="text-center">Debug Log</h4> <ul id="log_list"> <!-- console log/debug/info/warn/error ('msg') lines will go here --> </ul> </div> 

一些CSS:

 .log_level_log { color: black; background-color: white; font-size: x-small; } .log_level_debug { color: #060; background-color: #80FF80; font-size: x-small; } .log_level_info { color: #00F; background-color: #BEF; font-size: x-small; } .log_level_warn { color: #E65C00; background-color: #FB8; font-size: x-small; } .log_level_error { color: #F00; background-color: #FBB; font-size: x-small; } 

和一些JQuery:

 var theLog = app.mLog || []; if (theLog.length>0) { var theLogList = $('#log_list'); theLogList.empty(); for (var i=0; i<theLog.length; i++) { theLogList.prepend($('<li class="log_level_'+theLog[i].level+'"></li>').text(theLog[i].msg)); } } 

这是一个简单的用法,但是一旦你有了这个机制,你就可以做任何你想象得到的事情,包括在代码中留下日志,但是设置一个门槛,这样只有警告和错误才能通过。 希望这有助于他人的项目。

尝试setTimeout(console.log.bind(console,'foo'));

不久前,Chrome推出了一个function,可以解决您的问题,而无需代码的黑客。 它被称为“黑匣子”,它基本上允许你用他们的工具来标记应该被忽略的文件。

https://gist.github.com/paulirish/c307a5a585ddbcc17242

是的,这个解决scheme是浏览器特定的,但是如果你使用的是Chrome,你需要这个解决scheme。

对于每个日志抛出一个错误的巨大破解解决scheme可以显示正确的线,但它不会是在您的控制台中的可点击的链接。

基于绑定/别名的解决scheme只能使您修改打印的文本。 您将无法将参数转发到第三个函数进行进一步处理。