console.log包装器保存行号并支持大多数方法?

Pau*_*ber 48 javascript logging

如何编写控制台日志包装器:

  • 保持记录的行号和日志语句的文件名保持不变
  • 提供对所有日志严重性方法(错误,日志,调试......)的访问,并在控制台中将其显示在所记录的位置
  • 确实提供了一些后备(例如,当浏览器不支持错误时调用log方法)
  • 可以在中央位置关闭,所以我可以关闭生产日志
  • 确实处理没有控制台存在的情况,并且不会抛出错误

由于登录Java Script是如此不一致,因此必须有一些解决方案.自己实现它有点乏味,但似乎没有好的库.

我目前发现这个记录器提供了所有功能,但它确实搞乱了行号.http://benalman.com/projects/javascript-debug-console-log/

Tim*_*own 15

有我自己的log4javascript,它有自己的日志记录控制台,但也提供了一个包装器console.log.它符合您的所有标准,除了保持行号完整,如果您console.log()在另一个函数中包含调用等,则无法实现.

var log = log4javascript.getLogger("main");
var appender = new log4javascript.BrowserConsoleAppender();
log.addAppender(appender);
log.debug("Hello world");
Run Code Online (Sandbox Code Playgroud)


Leo*_*eoR 8

我还建议使用log4javascript,并解释如何仍然保留有关打印文件名和行的信息,至少在Chrome中是这样.

我不是在谈论更改Chrome打印的文件名和行,但您可以获取您感兴趣的信息并将其附加到日志语句中.我的解决方案是一个快速的黑客,但我认为通过更多的工作,你可以获得格式良好的日志语句.它可能也会产生严重的性能影响,但由于您不会在生产中激活日志,因此这不应该是一个太大的问题.

这个概念

在Chrome中,您可以创建一个Error对象,该对象提供一个堆栈属性,显示您当前的堆栈位置,在堆栈字符串中的某处找到您的调用脚本的文件和行号.

  > new Error().stack
  "Error
    at eval at <anonymous> (eval at evaluate (unknown source))
    at eval at evaluate (unknown source)
    at FrameMirror.evaluate (native)
    at Object.evaluate (unknown source)
    at Object._evaluateOn (unknown source)
    at Object._evaluateAndWrap (unknown source)
    at Object.evaluateOnCallFrame (unknown source)
    at meinAjaxAufruf (http://localhost:8080/numberajax.js:21:9)
    at HTMLInputElement.onkeyup (http://localhost:8080/numberajax.html:15:188)"
Run Code Online (Sandbox Code Playgroud)

对于log4javascript调用,堆栈跟踪可能如下所示:

"Error
    at Object.append (http://localhost:8080/log4javascript_uncompressed.js:1921:17)
    at Object.doAppend (http://localhost:8080/log4javascript_uncompressed.js:1047:9)
    at Object.callAppenders (http://localhost:8080/log4javascript_uncompressed.js:647:27)
    at Object.log (http://localhost:8080/log4javascript_uncompressed.js:640:10)
    at Object.debug (http://localhost:8080/log4javascript_uncompressed.js:748:9)
    at meinAjaxAufruf (http://localhost:8080/numberajax.js:36:16)
    at HTMLInputElement.onkeyup (http://localhost:8080/numberajax.html:16:188)"
Run Code Online (Sandbox Code Playgroud)

并且调用log4javascript并且我感兴趣的文件和行是

at meinAjaxAufruf (http://localhost:8080/numberajax.js:36:16)
Run Code Online (Sandbox Code Playgroud)

解决方案

我猜你从感兴趣的脚本到实际console调用发生的位置的堆栈深度总是一样的.所以现在你只需找出BrowserConsoleAppenderwindow.console访问的位置并将你感兴趣的行添加到格式化的字符串中.我对log4javascript_uncompressed.js(版本1.4.2第1913行)进行了以下更改:

} else if (window.console && window.console.log) { // Safari and Firebug
        var formattedMesage = getFormattedMessage();

        //---my additions
        var isChrome = navigator.userAgent.indexOf("Chrome") !== -1;
        if(isChrome){
            var stack = new Error().stack;
            var lineAccessingLogger = stack.split("\n")[6];
            formattedMesage += "\n" + lineAccessingLogger;
        }
        //---

        // Log to Firebug using its logging methods or revert to the console.log
        // method in Safari
        if (window.console.debug && Level.DEBUG.isGreaterOrEqual(loggingEvent.level)) {
            window.console.debug(formattedMesage);
        } else if (window.console.info && Level.INFO.equals(loggingEvent.level)) {
        ...
Run Code Online (Sandbox Code Playgroud)

而不是

17:53:22,872 DEBUG - sending /NumberServlet?zahl=1&text=
                                                 log4javascript.js:154
Run Code Online (Sandbox Code Playgroud)

我明白了

17:55:53,008 DEBUG - sending /NumberServlet?zahl=1&text=

    at meinAjaxAufruf (http://localhost:8080/numberajax.js:36:16) log4javascript_uncompressed.js:1930
Run Code Online (Sandbox Code Playgroud)

这肯定不是一个很好的解决方案:),但我得到了我需要的东西.

有了更多的框架知识,我想可以通过一种方式更改PatternLayout,您可以定义如何打印文件名/位置和行号.

编辑而不是我之前的解决方案我对PatternLayout.prototype.format函数进行了一些修改,所以现在我可以使用附加选项%l来定义我想要输出调用文件及其行的位置和方式.我发布了我的更改和用法示例作为Gist.


mpr*_*mpr 7

我们的日志包装器也遇到了这个问题,事实证明使用部分函数应用程序有一个非常简单的解决方法:

if(DEBUG_ENABLED && (typeof console != 'undefined')) {
    this.debug = console.log.bind(console);
}
else {
    this.debug = function(message) {};
}
Run Code Online (Sandbox Code Playgroud)

这样,您的浏览器将检测您要记录的源的正确行号和文件.


drz*_*aus 6

从相关问题(具有正确行号的console.log的正确包装器)进行交叉转换,但使用更新的解决方案来解决多种方法.


我喜欢@fredrik的答案,所以我将另一个答案拆分为Webkit 堆栈跟踪,并将其与@PaulIrish的安全console.log包装器合并."标准化" filename:line为"特殊对象",因此它在FF和Chrome中看起来大致相同.

小提琴测试:http://jsfiddle.net/drzaus/pWe6W/9/

_log = (function (methods, undefined) {

    var Log = Error; // does this do anything?  proper inheritance...?
    Log.prototype.write = function (args, method) {
        /// <summary>
        /// Paulirish-like console.log wrapper.  Includes stack trace via @fredrik SO suggestion (see remarks for sources).
        /// </summary>
        /// <param name="args" type="Array">list of details to log, as provided by `arguments`</param>
        /// <param name="method" type="string">the console method to use:  debug, log, warn, info, error</param>
        /// <remarks>Includes line numbers by calling Error object -- see
        /// * http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
        /// * https://stackoverflow.com/questions/13815640/a-proper-wrapper-for-console-log-with-correct-line-number
        /// * https://stackoverflow.com/a/3806596/1037948
        /// </remarks>

        // via @fredrik SO trace suggestion; wrapping in special construct so it stands out
        var suffix = {
            "@": (this.lineNumber
                    ? this.fileName + ':' + this.lineNumber + ":1" // add arbitrary column value for chrome linking
                    : extractLineNumberFromStack(this.stack)
            )
        };

        args = args.concat([suffix]);
        // via @paulirish console wrapper
        if (console && console[method]) {
            if (console[method].apply) { console[method].apply(console, args); } else { console[method](args); } // nicer display in some browsers
        }
    };
    var extractLineNumberFromStack = function (stack) {
        /// <summary>
        /// Get the line/filename detail from a Webkit stack trace.  See https://stackoverflow.com/a/3806596/1037948
        /// </summary>
        /// <param name="stack" type="String">the stack string</param>

        // correct line number according to how Log().write implemented
        var line = stack.split('\n')[3];
        // fix for various display text
        line = (line.indexOf(' (') >= 0
            ? line.split(' (')[1].substring(0, line.length - 1)
            : line.split('at ')[1]
            );
        return line;
    };

    // method builder
    var logMethod = function(method) {
        return function (params) {
            /// <summary>
            /// Paulirish-like console.log wrapper
            /// </summary>
            /// <param name="params" type="[...]">list your logging parameters</param>

            // only if explicitly true somewhere
            if (typeof DEBUGMODE === typeof undefined || !DEBUGMODE) return;

            // call handler extension which provides stack trace
            Log().write(Array.prototype.slice.call(arguments, 0), method); // turn into proper array & declare method to use
        };//--  fn  logMethod
    };
    var result = logMethod('log'); // base for backwards compatibility, simplicity
    // add some extra juice
    for(var i in methods) result[methods[i]] = logMethod(methods[i]);

    return result; // expose
})(['error', 'debug', 'info', 'warn']);//--- _log
Run Code Online (Sandbox Code Playgroud)