The browser JavaScript console is a web developers best friend. Using console.log() is essential for debugging your web apps. But there are a few annoyances. Two things that bother me for a while are:
- Reloading the page clears the console. Yes, there are settings for keeping the log, but personally I prefer to keep this turned off.
- Internet Explorer and Edge will only print to the console once the dev tools window has been opened. The console is always empty when opened, so anything you logged before this is lost.
Fortunately JavaScript is a very flexible language. Let’s make the console better!
Design goals:
- Record all calls to the console’s log() , error() , warn() and info() functions.
- Recall the console history by calling our own
console.history() function.
- console.history() shows the console history since the current page load.
- console.history(true) shows everything from the current session.
Here is my solution (also available at my GitHub tutorial repo). I have tried to annotate it to explain what is going on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
/* Console History by RL Vision * https://github.com/rlv-dan */ (function () { if (console && console.log) { // Make sure the console object is available console.historyData = []; // Restore previous session (if there is one) // The sessionStorage object is a convenient choice because the browser automatically clears it for us. var currentSessionStorage = []; if(sessionStorage && sessionStorage.consoleHistory) { currentSessionStorage = JSON.parse(sessionStorage.consoleHistory); } // Keep a reference to the original console functions that we intend to overwrite window.originalConsole = { // Assigning a native function to a var could throw TypeError, thus we need to use bind log: console.log.bind(console), info: console.info.bind(console), warn: console.warn.bind(console), error: console.error.bind(console), } // Function to save console calls in our history data objects var makeHistory = function(type, args) { args= Array.prototype.slice.call(args); console.historyData.push( { "type": type, "output": args, "timestamp": new Date() } ); if(sessionStorage) { currentSessionStorage.push( { "type": type, "output": args, "timestamp": new Date() } ); sessionStorage.consoleHistory = JSON.stringify(currentSessionStorage); } } // Override console functions with out own implementations // These will first record the call arguments and then pass the call on to the real console object console.log = function() { makeHistory("log", arguments); return originalConsole.log.apply(this, arguments); } console.info = function() { makeHistory("info", arguments); return originalConsole.info.apply(this, arguments); } console.warn = function() { makeHistory("warn", arguments); return originalConsole.warn.apply(this, arguments); } console.error = function() { makeHistory("error", arguments); return originalConsole.error.apply(this, arguments); } // Recall history by calling console.history() // Argument entireSession determines if recalling since beginning of current page load or since beginning of the current session console.history = function( entireSession ) { // Select data source var source = console.historyData; if(entireSession && sessionStorage && sessionStorage.consoleHistory) { source = JSON.parse(sessionStorage.consoleHistory); } // Print history for(var n=0; n<source.length; n++) { switch(source[n].type) { case "log": originalConsole.log.apply(null, source[n].output); break; case "info": originalConsole.info.apply(null, source[n].output); break; case "warn": originalConsole.warn.apply(null, source[n].output); break; case "error": originalConsole.error.apply(null, source[n].output); break; } } } } })(); // Initialize using an Immediately-Invoked Function Expression (IIFE) |