Search code examples
javascripttypescript

Wrapping a wrapper of console log with correct file/line number?


So I found a way to wrap console.log so that when called through the wrapper it preserves the file/line number from where it was called.

But I'd like to know how I could wrap it once more (perhaps several times if the actual logging happened to be in a very deep level).

class Debugger {
  _log() {
    return Function.prototype.bind.call(console.log, console);
  }

  log = this._log();

  specialLog(msg: string) {
    this.log('special: ' + msg);
  }
}

const debug = new Debugger();
debug.log('hi'); // works perfect: correct file/line number
debug.specialLog('hi'); // line number -> where this.log() is called.

From this sample code, how should I modify specialLog so that it works as log?
I've tried several combinations with .bind, .apply, .call trying to pass the console context through, but no success.

update:

specialLog(msg: string) {
  return this.log.bind(console, 'special ' + msg);
}

debug.specialLog('hi')(); // correct, but notice the extra '()'

This is the closest I could get, but is there a way to do it without having to execute it after call?

update 2: jsfiddle
https://jsfiddle.net/mqa1duvr/

update 3: reason I need it to go through another wrapper:
The actual debugger looks something like this:

class Debugger {
  debug(...)
  trace(...)
  // and inside each these debug..trace..warn etc..
  // there are set colors, timestamps, send log to server etc..
  // then, finally after all the filters, there's the "final" log.
  _log(...)
}

If I can make it go through several functions deep while having the caller's context, then I could keep the functions small.


Solution

  • You can set default arguments (the string "special: ") using bind. So this should work:

    specialLog =  Function.prototype.bind.call(console.log, console, "Special: ");
    //                                                             ^^^^^^^^^^^^^^
    

    Explanation:

    When specialLog get called, the first argument passed to console.log will always be "Special: ", so if you call it like:

    specialLog("Hello, world!");
    

    it will be as if you call console.log like:

    console.log("Special: ", "Hello, world!");
    

    which prints the string: "Special: Hello, world!", your desired result.

    user7552 (op) edit:
    for my case, it would be:

    specialLog =  Function.prototype.bind.call(this.log, console, "Special:");
    

    using this.log (reference inside the debugger class), instead of console.log.