4

I'm looking for a way to read the most recent command that was logged to the firebug console.

For example, I could have something that does

console.debug('The most current request URI is /sweatsocks');

And then another piece of (pseudo)code could then

if (mostRecentConsoleEntry().endsWith('/sweatsocks')) {
  // do some stuff
}

The context being the debug statement would be in the code under test, and the console checking would be done inside a selenium script. This would let me observe information buried deep in js functions as well as stuff that is built at runtime.

John Sheehan
  • 77,456
  • 30
  • 160
  • 194
adam goucher
  • 1,936
  • 1
  • 11
  • 7
  • "The most current request URI is /sweatsocks" - that's the grossest URI i've ever heard. – nickf Mar 02 '09 at 06:07

5 Answers5

5

You could overwrite the console.log function to add whatever extra functionality you need.

var oldLog = console.log;
var lastLog;
console.log = function () {
    // do whatever you need to do here: store the logs into a different variable, etc
    // eg:
    lastLog = arguments;

    // then call the regular log command
    oldLog.apply(console, arguments);
};

This won't be the most bulletproof solution, since console allows printf style syntax:

console.log("%d + %d = %s", 1, 3, "four");

...but it's probably a start for you.

Timo Tijhof
  • 10,032
  • 6
  • 34
  • 48
nickf
  • 537,072
  • 198
  • 649
  • 721
  • That's what I wished I knew :) +1 – alex Mar 02 '09 at 06:24
  • It don't work in FF3 and Firebug 1.3.3 since console.log is read-only. Also you are not allowed to add properties to the console object. – some Mar 02 '09 at 17:24
  • 1
    The syntax for apply is .apply(thisobject,array), so if it had worked to change the console object, it should have been: console.oldLog.apply(console.oldLog,arguments); but I suggest using a selfexecuting function to store the private variable with instead. – some Mar 02 '09 at 17:26
  • The printf style syntax actually still works fine, why wouldn't it? – Timo Tijhof Oct 30 '12 at 17:54
  • @nickf - Would this (or a more complete implementation of the console object) stop logging of Firefox modules to the console? I get out of memory errors on resource:///modules/sessionstore/SessionStore.jsm and was hoping that I could use Javascript to probe the console periodically for this error, to warn me if when the browser finally crashes (As I don't shut it down often, and am a heavy internet user) that it will not restore with session data from that time (Which is what I am seeing)? – user66001 Nov 12 '12 at 13:39
  • @user66001 no, this wouldn't work for that. The approach above overwrites the `log` method, but I doubt that internal errors and warnings would use the same interface. You could try it though. – nickf Nov 13 '12 at 00:20
  • And what about line numbers? Is it possible to get them? – Ajax Nov 19 '13 at 06:18
2

Don't try and override console.debug, implement a function that does console.debug plus what you need.

var debugCalls = [ ];
function myDebug(errorMessage){
  console.debug(errorMessage); //maintain original functionality
  debugCalls[debugCalls.length]  = errorMessage;
  //the previous argument to myDebug is debugCalls[debugCalls.length]

  //you may also want to call an ajax function to report this error
  mailError(errorMessage);
}
Devin Rhode
  • 23,026
  • 8
  • 58
  • 72
1

Could you rewrite the console.log(), and append all logs to an array? Then fire up the original console.log() and repeat what it's doing to get your debug output on the console?

alex
  • 479,566
  • 201
  • 878
  • 984
0

Here's a more elaborate version I put together:

/**
 * Console log with memory
 *
 * Example:
 *
 *     console.log(1);
 *     console.history[0]; // [1]
 *
 *     console.log(123, 456);
 *     console.history.slice(-1)[0]; // [123, 456]
 *
 *     console.log('third');
 *     // Setting the limit immediately trims the array,
 *     // just like .length (but removes from start instead of end).
 *     console.history.limit = 2;
 *     console.history[0]; // [123, 456], the [1] has been removed
 *
 * @author Timo Tijhof, 2012
 */
console.log = (function () {
    var log  = console.log,
        limit = 10,
        history = [],
        slice = history.slice;

    function update() {
        if (history.length > limit) {
            // Trim the array leaving only the last N entries
            console.history.splice(0, console.history.length - limit);
        }
    }

    if (console.history !== undefined) {
        return log;
    }

    Object.defineProperty(history, 'limit', {
        get: function () { return limit; },
        set: function (val) {
            limit = val;
            update();
        }
    });

    console.history = history;

    return function () {
        history.push(slice.call(arguments));
        update();
        return log.apply(console, arguments);
    };

}());
Timo Tijhof
  • 10,032
  • 6
  • 34
  • 48
  • Update: Added Object.defineProperty logic so that setting console.history.limit trims it immediately instead of after the next log() call (just like internal Array length does) – Timo Tijhof Oct 30 '12 at 18:44
-1

You might wanna implement a queue. Expanding on Devin's answer: (something like this)

var window.log = [];

logger function(msg) {
  var log_length = 10;
  console.log(msg);
  window.log.push(msg);
  if(window.log.length > log_length) {
    window.log.shift()
  }
}

See:
How do you implement a Stack and a Queue in JavaScript?
http://aymanh.com/9-javascript-tips-you-may-not-know#string-concatenation-vs-arrayjoin

Community
  • 1
  • 1
Rimian
  • 36,864
  • 16
  • 117
  • 117