Copilot just generated 200 lines of data processing logic. It works, or at least it seems to. But you have no idea what is happening inside. Which functions call which? What does the data look like at each step? Is that intermediate transformation correct? You could read every line carefully, or you could instrument the code with strategic console calls and watch the data flow in real time.
Console mastery is not about console.log('here'). It is about choosing the right console method to answer the specific question you have about unfamiliar code.
Beyond console.log, picking the right method
The four basic methods all write to the console but with different visual treatments. Browsers render warnings in yellow and errors in red, and errors include a stack traceWhat is stack trace?A list of function calls recorded at the moment an error occurs, showing exactly which functions were active and in what order. by default.
// Copilot generated this data pipeline - add logging to understand it
console.log('Processing started', { itemCount: items.length });
console.warn('Skipping 3 items with missing prices');
console.error('Critical: duplicate IDs found in dataset');
console.info('Cache hit - using stored results');| Method | Visual style | Stack trace? | Use when |
|---|---|---|---|
log | Default | No | General output, inspecting values |
info | Blue icon (some browsers) | No | Status messages, progress updates |
warn | Yellow | Optional | Deprecations, risky state, edge cases |
error | Red | Yes | Actual errors, unexpected states |
You can filter the console by severity using the dropdown next to the search box. When AI code generates a wall of logs, filter to "Errors only" to find what actually matters.
console.table, the best way to inspect APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. data
When you console.log() an object, you get a collapsed tree you have to click through. console.table() renders an array of objects as an actual table with sortable columns, much faster to scan.
// ChatGPT generated this fetch call - what does the data look like?
const response = await fetch('/api/users');
const users = await response.json();
// Instead of this:
console.log(users); // Collapsed object you have to click through
// Do this:
console.table(users);
// Renders a table with columns for every property
console.table(users, ['name', 'role', 'lastLogin']);
// Only shows the columns you care aboutThis is particularly powerful when debugging AI-generated data transformations. You can log the data before and after each transformation step to verify the AI's logic:
// Claude generated this pipeline - let's verify each step
const raw = await fetchData();
console.table(raw, ['id', 'status', 'amount']);
const filtered = raw.filter(item => item.status === 'active');
console.table(filtered, ['id', 'status', 'amount']);
const totals = filtered.reduce((acc, item) => {
acc[item.category] = (acc[item.category] || 0) + item.amount;
return acc;
}, {});
console.table(Object.entries(totals));.filter() or .map() chain, always console.table() the result of each step. AI tools frequently get filter conditions backwards, filtering out the items you wanted to keep. A quick table view catches this in seconds.console.group, organizing logs from complex AI code
When a single user action triggers many function calls in AI-generated code, the output becomes a wall of text. console.group() lets you nest related logs under a collapsible header.
// Instrument AI-generated checkout flow to understand it
function processOrder(order) {
console.group(`Processing order #${order.id}`);
console.log('Validating items:', order.items.length);
console.log('Calculating subtotal...');
const subtotal = order.items.reduce((s, i) => s + i.price, 0);
console.log('Subtotal:', subtotal);
console.group('Applying discounts');
console.log('Checking coupon code:', order.coupon);
console.log('Discount applied:', order.discount);
console.groupEnd();
console.log('Final total:', subtotal - order.discount);
console.groupEnd();
}
// Use groupCollapsed for verbose output you rarely need
console.groupCollapsed('API Response Details');
console.log('Status: 200');
console.log('Headers:', response.headers);
console.log('Payload size: 4.2 KB');
console.groupEnd();console.time, measuring AI code performance
console.time() starts a named timer and console.timeEnd() stops it and logs the elapsed time. Use this to check whether AI-generated code is actually fast or just looks fast.
// Is this Copilot-generated sort actually efficient?
console.time('ai-sort');
const sorted = items.sort((a, b) => {
// Copilot generated this comparator
return a.name.localeCompare(b.name) || a.date - b.date;
});
console.timeEnd('ai-sort');
// Logs: "ai-sort: 142.35 ms" - that's slow for 1000 items
// Compare with a simpler approach
console.time('simple-sort');
const sorted2 = items.sort((a, b) => a.date - b.date);
console.timeEnd('simple-sort');
// Logs: "simple-sort: 2.18 ms" - the AI over-engineered it// Time an async operation - works with await too
console.time('api-call');
const response = await fetch('/api/users');
const data = await response.json();
console.timeEnd('api-call');
// Logs: "api-call: 187.12 ms"console.timeLog() lets you log intermediate checkpoints without stopping the timer. Use it when profiling a multi-step AI pipeline: console.timeLog('pipeline', 'step 2 complete').console.trace, finding who calls what
When you are reading AI-generated code and a function is being called but you are not sure where from, console.trace() prints the full call stackWhat is call stack?The internal mechanism that tracks which function is currently executing and which called it - visible in error stack traces and browser DevTools. without throwing an error.
// ChatGPT generated this utility - who's calling it and when?
function formatCurrency(amount) {
console.trace('formatCurrency called');
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(amount);
}
// Output shows every function in the call chain:
// formatCurrency called
// at formatCurrency (utils.js:2)
// at renderLineItem (Cart.jsx:45)
// at Cart (Cart.jsx:12)console.assert, silent sanity checks
console.assert() only outputs anything when the condition is false. This makes it perfect for adding validation to AI code without cluttering the console during normal operation.
// Add sanity checks to AI-generated data transformations
const result = transformData(input);
console.assert(result.length > 0, 'Transform returned empty array', { input });
console.assert(result.every(r => r.id), 'Some results missing ID', { result });
console.assert(result.length === input.length, 'Item count mismatch', {
input: input.length,
output: result.length
});
// Logs nothing if all assertions pass - clean consoleA strategy for instrumenting unfamiliar AI code
When you receive AI-generated code you do not fully understand, follow this pattern:
| Step | What to do | Console method |
|---|---|---|
| 1 | Log function entry points | console.group() at the start of each function |
| 2 | Log input data shapes | console.table() on parameters |
| 3 | Log intermediate transformations | console.table() after each .map() / .filter() |
| 4 | Time expensive operations | console.time() / console.timeEnd() |
| 5 | Verify assumptions | console.assert() on expected conditions |
| 6 | Trace unexpected calls | console.trace() in functions called too often |
Quick reference
| Method | Signature | What it does |
|---|---|---|
log | console.log(...args) | General output |
warn | console.warn(...args) | Yellow warning |
error | console.error(...args) | Red error with trace |
table | console.table(data, columns?) | Renders as sortable table |
group | console.group(label) | Opens collapsible group |
groupCollapsed | console.groupCollapsed(label) | Opens group, collapsed |
groupEnd | console.groupEnd() | Closes current group |
time | console.time(label) | Starts named timer |
timeEnd | console.timeEnd(label) | Stops timer, logs ms |
timeLog | console.timeLog(label, ...args) | Logs intermediate time |
assert | console.assert(cond, ...args) | Logs if condition false |
trace | console.trace(label?) | Prints call stack |
count | console.count(label?) | Counts how many times called |
clear | console.clear() | Clears the console |