Make console.log log current line



  • Ok JavaScript ninjas, I have this utility which basically is a wrapper around console.log:

    It works, but of course, all lines in the console are Logger.js:23

    So, how can I make the call to console.log show the correct file and line number?

    Note 1

    I know there are libraries that do this, but I want to understand what I am doing wrong.


  • sockdevs

    yeah.... that's gotten much less fun thanks to arguments.caller being removed....

    but you can do this:

    function a(){
        var err = new Error();
        var caller_line = err.stack.split("\n")[2];
        var index = caller_line.indexOf("at ");
        var clean = caller_line.slice(index+2, caller_line.length);
        console.log(clean);
    }
    function b(){
        a();
    }
    b();
    

    tested on nodejs 4.0 and Chrome fourty mumble mumble mumble



  • Your code's buggy.

    Well maybe not in Node or whatever, it's broken in browsers.

    You can't assume that a "console" object exists.


  • I survived the hour long Uno hand

    We ran into that issue just a few weeks ago -- someone accidentally left a console.log in, and IE wouldn't render the page.



  • I've seen that a million times. Lazy JS developers developing based on "what Chrome does" instead of reading the specs.

    Your shit looks to be specific to Chrome anyway, so maybe it doesn't matter. But. Any chance to educate people on "console is not guaranteed to exist, guyz!" and I'll take it.



  • @blakeyrat said:

    Your shit looks to be specific to Chrome anyway, so maybe it doesn't matter.

    Well, it's a Chrome application, so yes, it's specific to Chrome. Also, the reason I always wrap console is exactly because of stupid IE.


  • sockdevs

    @blakeyrat said:

    Your code's buggy.

    fine....

    //polyfill console.log
    (function(global) {
      'use strict';
      global.console = global.console || {};
      var con = global.console;
      var prop, method;
      var empty = {};
      var dummy = function() {};
      var properties = 'memory'.split(',');
      var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' +
         'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' +
         'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',');
      while (prop = properties.pop()) if (!con[prop]) con[prop] = empty;
      while (method = methods.pop()) if (typeof con[method] !== 'function') con[method] = dummy;
    })(typeof window === 'undefined' ? this : window);
    
    //actually do the thing
    function a(){
        //this is probably wrong for some browser. only rely on it for debugging at the best.
        var err = new Error();
        var caller_line = err.stack.split("\n")[2];
        var index = caller_line.indexOf("at ");
        var clean = caller_line.slice(index+2, caller_line.length);
        console.log(clean);
    }
    function b(){
        a();
    }
    b();
    


  • @Eldelshell said:

    Also, the reason I always wrap console is

    But but... in the code you linked us to, you didn-- oh never mind, fuck it.



  • @accalia said:

    function a(){
    //this is probably wrong for some browser. only rely on it for debugging at the best.
    var err = new Error();
    var caller_line = err.stack.split("\n")[2];
    var index = caller_line.indexOf("at ");
    var clean = caller_line.slice(index+2, caller_line.length);
    console.log(clean);
    }

    That doesn't work. I get this:

    Object.__log (http://localhost:8000/js/utils/Logger.js:23:13)


  • sockdevs

    hmm.... play with the index on the err.stack.split line.

    try 4 as the value maybe?



  • Yeah, debugged the Error object and the line is there, but this doesn't fix the real issue I wanted to fix:


  • sockdevs

    oh. that. yeah that you can't fix that.



  • Ooo, I was confused too.

    Yeah, you don't control that at all. The only way to get the line number to appear correctly there is to not centralize your logging.



  • @accalia said:

    oh. that. yeah that you can't fix that.

    @blakeyrat said:

    Yeah, you don't control that at all. The only way to get the line number to appear correctly there is to not centralize your logging.

    Your JavaScript abilities are not that of a true Ninja. Of course it can be done:



  • Seems like the magic happens here:


  • sockdevs

    hmm........ thats..... interesting.....



  • Hax



  • @blakeyrat said:

    You can't assume that a "console" object exists.

    alert() is much more portable :trollface:



  • It's only supported in every major browser.


  • Discourse touched me in a no-no place

    @ben_lubar said:

    It's only supported in every major browser.

    If you ignore the big red box at the very top of the page that says "This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future."



  • The trick is that when it works it's actually calling console[methodName]. You can make it work too, as it is effectively:

    define('magic/console', function() {
      function noop() {}
      var c = typeof console !== 'undefined' ? console :  {};
      return {
        trace: c.trace && c.trace.bind(c) || noop,
        log: c.log && c.log.bind(c) || noop,
        debug: c.debug && c.debug.bind(c) || noop,
        info: c.info && c.info.bind(c) || noop,
        warn: c.warn && c.warn.bind(c) ||  noop,
        error: c.error && c.error.bind(c) || noop
      };
    });
    

    That's what they are doing here:

    and here

    So they proxy the console's own methods onto the Logger object, which is how you get the nice correct line numbers (because the browser is doing it for you).

    You can make the whole binding part even simpler if you just want access to the console if it exists. Just return the real console object:

    if (console && console.log && other.tests.here) return console;

Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.