Is there any quick way of getting Chrome to output timestamps in console.log writes (like Firefox does). Or is prepending new Date().getTime() the only option?
In Chrome, there is the option in Console Settings (Either press F1 or select Developer Tools -> Console -> Settings [upper-right corner] ) named "Show timestamps" which is exactly what I needed.
I've just found it. No other dirty hacks needed that destroys placeholders and erases place in the code where the messages was logged from.
Update for Chrome 68+
The "Show timestamps" setting has been moved to the Preferences pane of the "DevTools settings", found in the upper-right corner of the DevTools drawer:
Try this:
console.logCopy = console.log.bind(console);
console.log = function(data)
{
var currentDate = '[' + new Date().toUTCString() + '] ';
this.logCopy(currentDate, data);
};
Or this, in case you want a timestamp:
console.logCopy = console.log.bind(console);
console.log = function(data)
{
var timestamp = '[' + Date.now() + '] ';
this.logCopy(timestamp, data);
};
To log more than one thing and in a nice way (like object tree representation):
console.logCopy = console.log.bind(console);
console.log = function()
{
if (arguments.length)
{
var timestamp = '[' + Date.now() + '] ';
this.logCopy(timestamp, arguments);
}
};
With format string (JSFiddle)
console.logCopy = console.log.bind(console);
console.log = function()
{
// Timestamp to prepend
var timestamp = new Date().toJSON();
if (arguments.length)
{
// True array copy so we can call .splice()
var args = Array.prototype.slice.call(arguments, 0);
// If there is a format string then... it must
// be a string
if (typeof arguments[0] === "string")
{
// Prepend timestamp to the (possibly format) string
args[0] = "%o: " + arguments[0];
// Insert the timestamp where it has to be
args.splice(1, 0, timestamp);
// Log the whole array
this.logCopy.apply(this, args);
}
else
{
// "Normal" log
this.logCopy(timestamp, args);
}
}
};
Outputs with that:
P.S.: Tested in Chrome only.
P.P.S.: Array.prototype.slice is not perfect here for it would be logged as an array of objects rather than a series those of.
I originally added this as a comment, but I wanted to add a screenshot as at least one person could not find the option (or maybe it was not available in their particular version for some reason).
On Chrome 68.0.3440.106 (and now checked in 72.0.3626.121) I had to
open dev tools (F12)
click the three-dot menu in the top right
click settings
select Preferences in the left menu
check show timestamps in the Console section of the settings screen
You can use dev tools profiler.
console.time('Timer name');
//do critical time stuff
console.timeEnd('Timer name');
"Timer name" must be the same. You can use multiple instances of timer with different names.
I convert arguments to Array using Array.prototype.slice so that I can concat with another Array of what I want to add, then pass it into console.log.apply(console, /*here*/);
var log = function () {
return console.log.apply(
console,
['['+new Date().toISOString().slice(11,-5)+']'].concat(
Array.prototype.slice.call(arguments)
)
);
};
log(['foo']); // [18:13:17] ["foo"]
It seems that arguments can be Array.prototype.unshifted too, but I don't know if modifying it like this is a good idea/will have other side effects
var log = function () {
Array.prototype.unshift.call(
arguments,
'['+new Date().toISOString().slice(11,-5)+']'
);
return console.log.apply(console, arguments);
};
log(['foo']); // [18:13:39] ["foo"]
Update as of for Chrome 98:
Settings -> Preferences -> Console -> Show timestamps
From Chrome 68:
"Show timestamps" moved to settings
The Show timestamps checkbox previously in Console Settings Console Settings has moved to Settings.
+new Date and Date.now() are alternate ways to get timestamps
If you are using Google Chrome browser, you can use chrome console api:
console.time: call it at the point in your code where you want to start the timer
console.timeEnd: call it to stop the timer
The elapsed time between these two calls is displayed in the console.
For detail info, please see the doc link: https://developers.google.com/chrome-developer-tools/docs/console
ES6 solution:
const timestamp = () => `[${new Date().toUTCString()}]`
const log = (...args) => console.log(timestamp(), ...args)
where timestamp() returns actually formatted timestamp and log add a timestamp and propagates all own arguments to console.log
Try this also:
this.log = console.log.bind( console, '[' + new Date().toUTCString() + ']' );
This function puts timestamp, filename and line number as same of built-in console.log.
Chrome Version 89.0.4389.90 (19.03.2021)
Press F12.
Find and press gear wheel icon.
Check Show timestamps.
If you want to preserve line number information (each message pointing to its .log() call, not all pointing to our wrapper), you have to use .bind(). You can prepend an extra timestamp argument via console.log.bind(console, <timestamp>) but the problem is you need to re-run this every time to get a function bound with a fresh timestamp.
An awkward way to do that is a function that returns a bound function:
function logf() {
// console.log is native function, has no .bind in some browsers.
// TODO: fallback to wrapping if .bind doesn't exist...
return Function.prototype.bind.call(console.log, console, yourTimeFormat());
}
which then has to be used with a double call:
logf()(object, "message...")
BUT we can make the first call implicit by installing a property with getter function:
var origLog = console.log;
// TODO: fallbacks if no `defineProperty`...
Object.defineProperty(console, "log", {
get: function () {
return Function.prototype.bind.call(origLog, console, yourTimeFormat());
}
});
Now you just call console.log(...) and automagically it prepends a timestamp!
> console.log(12)
71.919s 12 VM232:2
undefined
> console.log(12)
72.866s 12 VM233:2
undefined
You can even achieve this magical behavior with a simple log() instead of console.log() by doing Object.defineProperty(window, "log", ...).
See https://github.com/pimterry/loglevel for a well-done safe console wrapper using .bind(), with compatibility fallbacks.
See https://github.com/eligrey/Xccessors for compatibility fallbacks from defineProperty() to legacy __defineGetter__ API.
If neither property API works, you should fallback to a wrapper function that gets a fresh timestamp every time. (In this case you lose line number info, but timestamps will still show.)
Boilerplate: Time formatting the way I like it:
var timestampMs = ((window.performance && window.performance.now) ?
function() { return window.performance.now(); } :
function() { return new Date().getTime(); });
function formatDuration(ms) { return (ms / 1000).toFixed(3) + "s"; }
var t0 = timestampMs();
function yourTimeFormat() { return formatDuration(timestampMs() - t0); }
I have this in most Node.JS apps. It also works in the browser.
function log() {
const now = new Date();
const currentDate = `[${now.toISOString()}]: `;
const args = Array.from(arguments);
args.unshift(currentDate);
console.log.apply(console, args);
}
extended the very nice solution "with format string" from JSmyth to also support
all the other console.log variations (log,debug,info,warn,error)
including timestamp string flexibility param (e.g. 09:05:11.518 vs. 2018-06-13T09:05:11.518Z)
including fallback in case console or its functions do not exist in browsers
.
var Utl = {
consoleFallback : function() {
if (console == undefined) {
console = {
log : function() {},
debug : function() {},
info : function() {},
warn : function() {},
error : function() {}
};
}
if (console.debug == undefined) { // IE workaround
console.debug = function() {
console.info( 'DEBUG: ', arguments );
}
}
},
/** based on timestamp logging: from: https://stackoverflow.com/a/13278323/1915920 */
consoleWithTimestamps : function( getDateFunc = function(){ return new Date().toJSON() } ) {
console.logCopy = console.log.bind(console)
console.log = function() {
var timestamp = getDateFunc()
if (arguments.length) {
var args = Array.prototype.slice.call(arguments, 0)
if (typeof arguments[0] === "string") {
args[0] = "%o: " + arguments[0]
args.splice(1, 0, timestamp)
this.logCopy.apply(this, args)
} else this.logCopy(timestamp, args)
}
}
console.debugCopy = console.debug.bind(console)
console.debug = function() {
var timestamp = getDateFunc()
if (arguments.length) {
var args = Array.prototype.slice.call(arguments, 0)
if (typeof arguments[0] === "string") {
args[0] = "%o: " + arguments[0]
args.splice(1, 0, timestamp)
this.debugCopy.apply(this, args)
} else this.debugCopy(timestamp, args)
}
}
console.infoCopy = console.info.bind(console)
console.info = function() {
var timestamp = getDateFunc()
if (arguments.length) {
var args = Array.prototype.slice.call(arguments, 0)
if (typeof arguments[0] === "string") {
args[0] = "%o: " + arguments[0]
args.splice(1, 0, timestamp)
this.infoCopy.apply(this, args)
} else this.infoCopy(timestamp, args)
}
}
console.warnCopy = console.warn.bind(console)
console.warn = function() {
var timestamp = getDateFunc()
if (arguments.length) {
var args = Array.prototype.slice.call(arguments, 0)
if (typeof arguments[0] === "string") {
args[0] = "%o: " + arguments[0]
args.splice(1, 0, timestamp)
this.warnCopy.apply(this, args)
} else this.warnCopy(timestamp, args)
}
}
console.errorCopy = console.error.bind(console)
console.error = function() {
var timestamp = getDateFunc()
if (arguments.length) {
var args = Array.prototype.slice.call(arguments, 0)
if (typeof arguments[0] === "string") {
args[0] = "%o: " + arguments[0]
args.splice(1, 0, timestamp)
this.errorCopy.apply(this, args)
} else this.errorCopy(timestamp, args)
}
}
}
} // Utl
Utl.consoleFallback()
//Utl.consoleWithTimestamps() // defaults to e.g. '2018-06-13T09:05:11.518Z'
Utl.consoleWithTimestamps( function(){ return new Date().toJSON().replace( /^.+T(.+)Z.*$/, '$1' ) } ) // e.g. '09:05:11.518'
This adds a "log" function to the local scope (using this) using as many arguments as you want:
this.log = function() {
var args = [];
args.push('[' + new Date().toUTCString() + '] ');
//now add all the other arguments that were passed in:
for (var _i = 0, _len = arguments.length; _i < _len; _i++) {
arg = arguments[_i];
args.push(arg);
}
//pass it all into the "real" log function
window.console.log.apply(window.console, args);
}
So you can use it:
this.log({test: 'log'}, 'monkey', 42);
Outputs something like this:
[Mon, 11 Mar 2013 16:47:49 GMT] Object {test: "log"} monkey 42
A refinement on the answer by JSmyth:
console.logCopy = console.log.bind(console);
console.log = function()
{
if (arguments.length)
{
var timestamp = new Date().toJSON(); // The easiest way I found to get milliseconds in the timestamp
var args = arguments;
args[0] = timestamp + ' > ' + arguments[0];
this.logCopy.apply(this, args);
}
};
This:
shows timestamps with milliseconds
assumes a format string as first parameter to .log
Related
How can we format a value into a string to be consistent with how console.log(value) does it?
I need to append extra details to each value I am printing, without breaking the default formatting provided by console.log. It is easy for simple values, but for such types as Date and Object it is more complicated.
Is there a way I can make it consistent with console.log? In other words, how to format a value to be the same string as we get from console.log(value)?
I'm trying to implement a simple library manakin. Here's its complete source code:
'use strict';
(function () {
var error = console.error, warn = console.warn;
console.error = function () {
var a = arguments;
error.apply(this, Object.keys(a).map(function (key) {
return "\u001b[31m" + a[key] + "\u001b[0m";
}));
};
console.warn = function () {
var a = arguments;
warn.apply(this, Object.keys(a).map(function (key) {
return "\u001b[33m" + a[key] + "\u001b[0m";
}));
};
})();
The problem I am having is that for types Date and Object the output is different:
// without manakin:
console.warn({value: 1});
//=> { value: 1 }
// with manakin:
console.warn({value: 1});
//=> [object Object]
And I want to make it consistent.
SOLVED
In the end I figured out how to make it all work in both both Node.js and in all browsers, see manakin source code (it is small).
It required different implementation for Node.js and for the browsers. Specifically under Node.js it uses util.inspect.
I believe if you modify the code in warn to be:
console.warn = function () {
var a = arguments;
warn.apply(this, Object.keys(a).map(function (key) {
if (a[key] instanceof Date) {
return "\u001b[33m" + a[key].toString() + "\u001b[0m";
}
return "\u001b[33m" + JSON.stringify(a[key]) + "\u001b[0m";
}));
};
you have what you're looking for. I tested it out by just pasting the new code in the console and logging the examples you have, hope that works for you!
Is it possible to extend the console object?
I tried something like:
Console.prototype.log = function(msg){
Console.prototype.log.call(msg);
alert(msg);
}
But this didn't work.
I want to add additional logging to the console object via a framework like log4javascript and still use the standard console object (in cases where log4javascript is not available) in my code.
Thanks in advance!
Try following:
(function() {
var exLog = console.log;
console.log = function(msg) {
exLog.apply(this, arguments);
alert(msg);
}
})()
You Can Also add log Time in This Way :
added Momentjs or use New Date() instead of moment.
var oldConsole = console.log;
console.log = function(){
var timestamp = "[" + moment().format("YYYY-MM-DD HH:mm:ss:SSS") + "] ";
Array.prototype.unshift.call(arguments, timestamp);
oldConsole.apply(this, arguments);
};
It's really the same solution some others have given, but I believe this is the most elegant and least hacky way to accomplish this. The spread syntax (...args) makes sure not a single argument is lost.
var _console={...console}
console.log = function(...args) {
var msg = {...args}[0];
//YOUR_CODE
_console.log(...args);
}
For ECMAScript 2015 and later
You can use the newer Proxy feature from the ECMAScript 2015 standard to "hijack" the global console.log.
Source-Code
'use strict';
class Mocker {
static mockConsoleLog() {
Mocker.oldGlobalConsole = window.console;
window.console = new Proxy(window.console, {
get(target, property) {
if (property === 'log') {
return function(...parameters) {
Mocker.consoleLogReturnValue = parameters.join(' ');
}
}
return target[property];
}
});
}
static unmockConsoleLog() {
window.console = Mocker.oldGlobalConsole;
}
}
Mocker.mockConsoleLog();
console.log('hello'); // nothing happens here
Mocker.unmockConsoleLog();
if (Mocker.consoleLogReturnValue === 'hello') {
console.log('Hello world!'); // Hello world!
alert(Mocker.consoleLogReturnValue);
// anything you want to do with the console log return value here...
}
Online Demo
Repl.it.
Node.js users...
... I do not forget you. You can take this source-code and replace window.console by gloabl.console to properly reference the console object (and of course, get rid of the alert call). In fact, I wrote this code initially and tested it on Node.js.
// console aliases and verbose logger - console doesnt prototype
var c = console;
c.l = c.log,
c.e = c.error,
c.v = c.verbose = function() {
if (!myclass || !myclass.verbose) // verbose switch
return;
var args = Array.prototype.slice.call(arguments); // toArray
args.unshift('Verbose:');
c.l.apply(this, args); // log
};
// you can then do
var myclass = new myClass();
myclass.prototype.verbose = false;
// generally these calls would be inside your class
c.v('1 This will NOT log as verbose == false');
c.l('2 This will log');
myclass.verbose = true;
c.v('3 This will log');
I noted that the above use of Array.prototype.unshift.call by nitesh is a better way to add the 'Verbose:' tag.
You can override the default behavior of the console.log function using the below approach, the below example demonstrates to log the line number using the overridden function.
let line = 0;
const log = console.log;
console.log = (...data) => log(`${++line} ===>`, ...data)
console.log(11, 1, 2)
console.log(11, 1, 'some')
I want to write some log class that can be used like the following code.
// short-hand for logging.
log('log message', [other parameter]);
// full path for writing log.
log.write('log message', [other parameter]);
// print all log
log.print([optional parameter]);
Moreover, it must able to be written as fluent pattern.
log.write('log message').print();
Finally, it should be resetted by using the following code.
log = new log();
Thanks,
Let's implement it as a normal object first, then add some other syntaxes after:
var log = {};
log.write = function() {
// stuff...
return this;
};
log.print = function() {
// stuff...
return this;
};
log.reset = function() {
// stuff
return this;
};
As function is also an object, it can have properties, so you can replace var log = {};, with a function that redirects to log.write instead.
function log() {
return log.write.apply(log, arguments);
}
Finally, for the self-reset syntax, you can detect for a new instance, but instead of creating a new object, you reset the log and hand the same object back!
So now the log function will look like this:
function log() {
if (this instanceof log) {
return log.reset.apply(log, arguments);
}
return log.write.apply(log, arguments);
}
You can look at jsFiddle to see that it works. Warning: lot of alert()s on that page!
var Logger = function(msg,p){
this.msg = typeof msg != 'undefined' ? msg : '';
this.p = typeof p != 'undefined' ? p : '';
}
Logger.prototype = {
write : function(msg,p){
this.msg = typeof msg != 'undefined' ? msg : '';
this.p = typeof p != 'undefined' ? p : '';
},
print : function(p){
this.p = typeof p == 'undefined' ? this.p : p;
if(this.p)
alert(this.msg);
else
console.log(this.msg);
return this;
},
reset : function(){
return new Logger();
}
}
function log(msg,p){
return new Logger(msg,p).print();
}
And then you can use :
log("alert me",true);
log("log me in console!");
log().write("a msg",false).print();
var l = log();
l.write().print().reset();
Doesn't console.log in firebug serve the purpose of logging? Though, one can write their own logger implementation. But the question is when should the logger to be used? Implementation similar like you have proposed could be useful in javascript running in server side like Rhino
But i have written some code, pls try this
<html>
<head>
<script>
var log = function() {
var p_this = this;
this.write = function(p_msg){
p_this.msg = p_msg;
return this.write;
},
this.write.print = function(){
alert(p_this.msg);
}
};
var log1 = new log();
log1.write('test_message').print();
</script>
</head>
<body>
</body>
</html>
This may be helpful. This a conceptual code for the pattern u are looking for. You have to modify this or improve this. You may provide the logic for resetting and all.
You could try this glorious masterpiece:
var log = (function(out){
var msgs = [];
function log(msg){
if (typeof msg == 'string'){
msgs.push(msg);
return log;}
else{
msgs = [];
return log;}}
log.write = function(msg){
log(msg);
return log;};
log.print = function(){
for(var i=0, l=msgs.length; i<l; i++){
out(msgs[i]);}};
return log;})(function(s){console.log(s);});
The real output function is injected at the end. You should test for console.log to exist, and use an alternative otherwise (I do not know what you would prefer).
I tried the following things:
log('First message');
log.write('Second message')('Third message').write('Fourth message');
log.write('Fifth message').print();
log.print(); // Prints all messages again.
log = new log(); // Reset.
log('Lonely!').print(); // Prints only 'Lonely!'.
Beware: log(); or log(undefined); (with undefined undefined) will reset the thing as well, while new log('Foobar'); will add the message 'Foobar'. But this was not in your test cases, so I ignored it.
This is also possible:
(new log()).write('Message');
(new log())('Message');
(new log()).print(); // Prints empty log.
Try to look at JSLog javascript logging framework:
https://github.com/dingyonglaw/JSLog
It supports all browser, and also firebug-lite;
==============
Example Usage:
==============
Logging:
--------
// Register a module logger, p is now logger for 'App.Login'
var p = JSLog.Register('App.Login');
// Log something, and it will display "[App.Login] something" in your console;
p.log('something');
// You can do something as usual:
p.warn('warning!');
p.info('info msg');
Log Level:
----------
The Logger comes with 5 level of logging access: 1-5
which coresponding to: 'error', 'warn', 'info', 'debug', 'log'
// You can set your level like this, to display only info message in console
p.SetLevel(3);
// You can get your current logging level with:
p.GetLevel();
Logging History:
----------------
The logger records your logs and you can Dump it later!
// Dump by Module Name
JSLog.Dump('App.Login');
// Dump all modules in nested view
JSLog.Dump();
// Selective Dump by filtering module name:
JSLog.SetFilter('module-name');
JSLog.Dump(); // Will exclude 'module-name' module
// Clear filter by module name:
JSLog.UnsetFilter('module-name');
// Get assigned filters
JSLog.GetFilter();
According to this post it was in the beta, but it's not in the release?
console.log is only available after you have opened the Developer Tools (F12 to toggle it open and closed).
Funny thing is that after you've opened it, you can close it, then still post to it via console.log calls, and those will be seen when you reopen it.
I'm thinking that is a bug of sorts, and may be fixed, but we shall see.
I'll probably just use something like this:
function trace(s) {
if ('console' in self && 'log' in console) console.log(s)
// the line below you might want to comment out, so it dies silent
// but nice for seeing when the console is available or not.
else alert(s)
}
and even simpler:
function trace(s) {
try { console.log(s) } catch (e) { alert(s) }
}
Even better for fallback is this:
var alertFallback = true;
if (typeof console === "undefined" || typeof console.log === "undefined") {
console = {};
if (alertFallback) {
console.log = function(msg) {
alert(msg);
};
} else {
console.log = function() {};
}
}
This is my take on the various answers. I wanted to actually see the logged messages, even if I did not have the IE console open when they were fired, so I push them into a console.messages array that I create. I also added a function console.dump() to facilitate viewing the whole log. console.clear() will empty the message queue.
This solutions also "handles" the other Console methods (which I believe all originate from the Firebug Console API)
Finally, this solution is in the form of an IIFE, so it does not pollute the global scope. The fallback function argument is defined at the bottom of the code.
I just drop it in my master JS file which is included on every page, and forget about it.
(function (fallback) {
fallback = fallback || function () { };
// function to trap most of the console functions from the FireBug Console API.
var trap = function () {
// create an Array from the arguments Object
var args = Array.prototype.slice.call(arguments);
// console.raw captures the raw args, without converting toString
console.raw.push(args);
var message = args.join(' ');
console.messages.push(message);
fallback(message);
};
// redefine console
if (typeof console === 'undefined') {
console = {
messages: [],
raw: [],
dump: function() { return console.messages.join('\n'); },
log: trap,
debug: trap,
info: trap,
warn: trap,
error: trap,
assert: trap,
clear: function() {
console.messages.length = 0;
console.raw.length = 0 ;
},
dir: trap,
dirxml: trap,
trace: trap,
group: trap,
groupCollapsed: trap,
groupEnd: trap,
time: trap,
timeEnd: trap,
timeStamp: trap,
profile: trap,
profileEnd: trap,
count: trap,
exception: trap,
table: trap
};
}
})(null); // to define a fallback function, replace null with the name of the function (ex: alert)
Some extra info
The line var args = Array.prototype.slice.call(arguments); creates an Array from the arguments Object. This is required because arguments is not really an Array.
trap() is a default handler for any of the API functions. I pass the arguments to message so that you get a log of the arguments that were passed to any API call (not just console.log).
Edit
I added an extra array console.raw that captures the arguments exactly as passed to trap(). I realized that args.join(' ') was converting objects to the string "[object Object]" which may sometimes be undesirable. Thanks bfontaine for the suggestion.
It's worth noting that console.log in IE8 isn't a true Javascript function. It doesn't support the apply or call methods.
Assuming you don't care about a fallback to alert, here's an even more concise way to workaround Internet Explorer's shortcomings:
var console=console||{"log":function(){}};
I really like the approach posted by "orange80". It's elegant because you can set it once and forget it.
The other approaches require you to do something different (call something other than plain console.log() every time), which is just asking for troubleā¦ I know that I'd eventually forget.
I've taken it a step further, by wrapping the code in a utility function that you can call once at the beginning of your javascript, anywhere as long as it's before any logging. (I'm installing this in my company's event data router product. It will help simplify the cross-browser design of its new admin interface.)
/**
* Call once at beginning to ensure your app can safely call console.log() and
* console.dir(), even on browsers that don't support it. You may not get useful
* logging on those browers, but at least you won't generate errors.
*
* #param alertFallback - if 'true', all logs become alerts, if necessary.
* (not usually suitable for production)
*/
function fixConsole(alertFallback)
{
if (typeof console === "undefined")
{
console = {}; // define it if it doesn't exist already
}
if (typeof console.log === "undefined")
{
if (alertFallback) { console.log = function(msg) { alert(msg); }; }
else { console.log = function() {}; }
}
if (typeof console.dir === "undefined")
{
if (alertFallback)
{
// THIS COULD BE IMPROVEDā¦ maybe list all the object properties?
console.dir = function(obj) { alert("DIR: "+obj); };
}
else { console.dir = function() {}; }
}
}
If you get "undefined" to all of your console.log calls, that probably means you still have an old firebuglite loaded (firebug.js). It will override all the valid functions of IE8's console.log even though they do exist. This is what happened to me anyway.
Check for other code overriding the console object.
The best solution for any browser that lack a console is:
// Avoid `console` errors in browsers that lack a console.
(function() {
var method;
var noop = function () {};
var methods = [
'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
'timeStamp', 'trace', 'warn'
];
var length = methods.length;
var console = (window.console = window.console || {});
while (length--) {
method = methods[length];
// Only stub undefined methods.
if (!console[method]) {
console[method] = noop;
}
}
}());
There are so many Answers. My solution for this was:
globalNamespace.globalArray = new Array();
if (typeof console === "undefined" || typeof console.log === "undefined") {
console = {};
console.log = function(message) {globalNamespace.globalArray.push(message)};
}
In short, if console.log doesn't exists (or in this case, isn't opened) then store the log in a global namespace Array. This way, you're not pestered with millions of alerts and you can still view your logs with the developer console opened or closed.
Here is my "IE please don't crash"
typeof console=="undefined"&&(console={});typeof console.log=="undefined"&&(console.log=function(){});
if (window.console && 'function' === typeof window.console.log) {
window.console.log(o);
}
I found this on github:
// usage: log('inside coolFunc', this, arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function f() {
log.history = log.history || [];
log.history.push(arguments);
if (this.console) {
var args = arguments,
newarr;
args.callee = args.callee.caller;
newarr = [].slice.call(args);
if (typeof console.log === 'object') log.apply.call(console.log, console, newarr);
else console.log.apply(console, newarr);
}
};
// make it safe to use console.log always
(function(a) {
function b() {}
for (var c = "assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","), d; !! (d = c.pop());) {
a[d] = a[d] || b;
}
})(function() {
try {
console.log();
return window.console;
} catch(a) {
return (window.console = {});
}
} ());
I'm using Walter's approach from above (see: https://stackoverflow.com/a/14246240/3076102)
I mix in a solution I found here https://stackoverflow.com/a/7967670 to properly show Objects.
This means the trap function becomes:
function trap(){
if(debugging){
// create an Array from the arguments Object
var args = Array.prototype.slice.call(arguments);
// console.raw captures the raw args, without converting toString
console.raw.push(args);
var index;
for (index = 0; index < args.length; ++index) {
//fix for objects
if(typeof args[index] === 'object'){
args[index] = JSON.stringify(args[index],null,'\t').replace(/\n/g,'<br>').replace(/\t/g,' ');
}
}
var message = args.join(' ');
console.messages.push(message);
// instead of a fallback function we use the next few lines to output logs
// at the bottom of the page with jQuery
if($){
if($('#_console_log').length == 0) $('body').append($('<div />').attr('id', '_console_log'));
$('#_console_log').append(message).append($('<br />'));
}
}
}
I hope this is helpful:-)
I like this method (using jquery's doc ready)... it lets you use console even in ie... only catch is that you need to reload the page if you open ie's dev tools after the page loads...
it could be slicker by accounting for all the functions, but I only use log so this is what I do.
//one last double check against stray console.logs
$(document).ready(function (){
try {
console.log('testing for console in itcutils');
} catch (e) {
window.console = new (function (){ this.log = function (val) {
//do nothing
}})();
}
});
Here is a version that will log to the console when the developer tools are open and not when they are closed.
(function(window) {
var console = {};
console.log = function() {
if (window.console && (typeof window.console.log === 'function' || typeof window.console.log === 'object')) {
window.console.log.apply(window, arguments);
}
}
// Rest of your application here
})(window)
Make your own console in html .... ;-)
This can be imprved but you can start with :
if (typeof console == "undefined" || typeof console.log === "undefined") {
var oDiv=document.createElement("div");
var attr = document.createAttribute('id'); attr.value = 'html-console';
oDiv.setAttributeNode(attr);
var style= document.createAttribute('style');
style.value = "overflow: auto; color: red; position: fixed; bottom:0; background-color: black; height: 200px; width: 100%; filter: alpha(opacity=80);";
oDiv.setAttributeNode(style);
var t = document.createElement("h3");
var tcontent = document.createTextNode('console');
t.appendChild(tcontent);
oDiv.appendChild(t);
document.body.appendChild(oDiv);
var htmlConsole = document.getElementById('html-console');
window.console = {
log: function(message) {
var p = document.createElement("p");
var content = document.createTextNode(message.toString());
p.appendChild(content);
htmlConsole.appendChild(p);
}
};
}
It works in IE8. Open IE8's Developer Tools by hitting F12.
>>console.log('test')
LOG: test
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.
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.
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);
}
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?
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);
};
}());
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