Everyone reaches for console.log() early and often, but the console object holds a handful of other methods that solve specific debugging problems better than a plain log ever could.
The basics, with their actual purpose
console.log('Regular information');
console.info('Also informational — an alias for console.log');
console.warn('Something worth noticing, not necessarily broken');
console.error('Something went wrong');
console.error() and console.warn() write to stderr instead of stdout — which matters in production, where logging tools often route these two streams to different destinations (errors to an alerting system, regular output to a log file, for instance).
Timing how long something takes
console.time('database-query');
await runQuery();
console.timeEnd('database-query');
// database-query: 143.221ms
The label passed to .time() and .timeEnd() must match — this is how you can time multiple overlapping operations at once, each with its own label.
Counting how many times something runs
function handleRequest() {
console.count('requests handled');
}
handleRequest(); // requests handled: 1
handleRequest(); // requests handled: 2
handleRequest(); // requests handled: 3
Useful for a quick check on how often a function actually fires, without manually maintaining a counter variable yourself.
Inspecting objects clearly
const user = { id: 1, name: 'Karim', roles: ['admin', 'editor'] };
console.dir(user, { depth: null, colors: true });
console.dir() uses Node's object inspector directly, which is useful for deeply nested objects where console.log()'s default formatting sometimes truncates or abbreviates.
Displaying tabular data
console.table([
{ name: 'Rahim', score: 88 },
{ name: 'Karim', score: 92 }
]);
This prints an actual formatted table in the terminal, with columns for each object key — far easier to scan than the same array logged as raw JSON, especially for a list of similarly-shaped records.
Writing logs to files instead of the terminal
For situations where you want logs saved rather than just printed, the Console class lets you build a custom logger pointed at output streams:
const fs = require('fs');
const { Console } = require('console');
const logFile = fs.createWriteStream('./app.log');
const errorFile = fs.createWriteStream('./app-error.log');
const fileLogger = new Console(logFile, errorFile);
fileLogger.log('Server started'); // written to app.log
fileLogger.error('Connection lost'); // written to app-error.log
This creates a second, independent logger — separate from the global console — that writes to files instead of the terminal, useful for keeping a persistent record without cluttering standard output during development.