We use cookies to enhance your experience on the site
CodeWorlds

Browser Console and Its Functions

Managing Jurassic Park is no easy task. When problems arise in the dinosaur tracking system or we need to quickly diagnose why the lockdown protocol isn't starting correctly, debugging is a critical skill. One of the most important diagnostic tools in JavaScript is the browser console.

In this exercise we'll learn about a tool that will be your best friend when searching for and solving problems — the browser developer console.

Opening the Developer Console

Before we start using the console, we need to know how to open it:

  • Chrome/Edge: <kbd>F12</kbd> or <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>J</kbd> (Windows/Linux) or <kbd>Cmd</kbd>+<kbd>Option</kbd>+<kbd>J</kbd> (Mac)
  • Firefox: <kbd>F12</kbd> or <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>K</kbd> (Windows/Linux) or <kbd>Cmd</kbd>+<kbd>Option</kbd>+<kbd>K</kbd> (Mac)
  • Safari: <kbd>Cmd</kbd>+<kbd>Option</kbd>+<kbd>C</kbd> (you must first enable developer tools in settings)

After opening you'll see several tabs, including "Console". That's where we'll focus.

Basic Console Functions

1. console.log() — Your Best Friend

The most commonly used console function is

console.log()
. It displays values in the console, which is indispensable during debugging:

1// Displaying simple values
2console.log("Dinosaur tracking system started");
3console.log(42); // number
4console.log(true); // boolean value
5
6// Displaying multiple values at once
7const dinosaur = { name: "Rex", type: "T-Rex", status: "contained" };
8console.log("Dinosaur data:", dinosaur, "Update:", new Date());
9
10// String interpolation
11const sector = "B7";
12const threat = "high";
13console.log(`Dinosaur detected in sector ${sector}. Threat level: ${threat}`);

In our Jurassic Park system we can use

console.log()
to track various events:

1function trackDinosaur(id, location) {
2  console.log(`Tracking dinosaur #${id} at location ${location}`);
3
4  // Tracking logic...
5  const status = checkContainment(id);
6
7  if (status !== "contained") {
8    console.log(`ALERT: Dinosaur #${id} is not in its enclosure! Current status: ${status}`);
9  }
10
11  return status;
12}

2. console.error(), console.warn(), console.info()

In addition to the standard

log
, we have special methods for different message levels:

1// Errors — usually displayed in red
2console.error("CRITICAL ERROR: Fence system failure in T-Rex sector!");
3
4// Warnings — usually displayed in yellow
5console.warn("Warning: Motion sensor battery level dropping below 20%");
6
7// Info — often distinguished from regular logs
8console.info("Info: Technical system review scheduled for tomorrow, 8:00");

Using them helps visually distinguish message types in the console, which is especially important when dealing with large volumes of logs.

3. console.table() — Clean Display of Tabular Data

When dealing with arrays of objects,

console.table()
is invaluable:

1// Array of dinosaurs in our park
2const dinosaurs = [
3  { id: 1, name: "Rex", species: "T-Rex", danger: 9, location: "Enclosure A" },
4  { id: 2, name: "Blue", species: "Velociraptor", danger: 8, location: "Enclosure B" },
5  { id: 3, name: "Delta", species: "Velociraptor", danger: 8, location: "Enclosure B" },
6  { id: 4, name: "Echo", species: "Velociraptor", danger: 7, location: "Enclosure B" },
7  { id: 5, name: "Trike", species: "Triceratops", danger: 4, location: "Enclosure C" }
8];
9
10// Displays a beautiful table with the data
11console.table(dinosaurs);
12
13// We can also select specific columns
14console.table(dinosaurs, ["name", "species", "danger"]);

This is especially useful for data analysis, checking API query results, or reviewing configurations.

4. console.group() — Grouping Logs

When we have many related logs, we can group them for clarity:

1// Monitoring a specific dinosaur
2function monitorDinosaur(dinosaur) {
3  console.group(`Monitoring: ${dinosaur.name} (${dinosaur.species})`);
4
5  console.log(`Location: ${dinosaur.location}`);
6  console.log(`Danger level: ${dinosaur.danger}/10`);
7
8  const healthStatus = checkHealth(dinosaur.id);
9  console.log(`Health status: ${healthStatus.status}`);
10
11  if (healthStatus.issues.length > 0) {
12    console.warn(`Health issues detected: ${healthStatus.issues.join(', ')}`);
13  }
14
15  const securityStatus = checkSecurity(dinosaur.location);
16  console.log(`Security status: ${securityStatus.status}`);
17
18  if (securityStatus.issues.length > 0) {
19    console.error(`Security issues: ${securityStatus.issues.join(', ')}`);
20  }
21
22  console.groupEnd();
23
24  return { healthStatus, securityStatus };
25}
26
27// Grouping can also be nested
28function monitorAllDinosaurs(dinosaurs) {
29  console.group('Monitoring all dinosaurs');
30
31  dinosaurs.forEach(dino => {
32    monitorDinosaur(dino);
33  });
34
35  console.groupEnd();
36}
37
38monitorAllDinosaurs(dinosaurs);

You can also start a group collapsed using

console.groupCollapsed()
, which is useful with many groups.

5. console.time() and console.timeEnd() — Measuring Execution Time

Sometimes we need to know how long certain operations take:

1// Measuring module load time
2console.time('Loading tracking module');
3
4loadTrackingModule()
5  .then(() => {
6    console.timeEnd('Loading tracking module');
7    // Displays e.g.: "Loading tracking module: 235.41ms"
8  });
9
10// We can have multiple parallel timers
11console.time('System initialization');
12console.time('Data processing');
13
14initSystem()
15  .then(() => {
16    console.timeEnd('System initialization');
17    return processData();
18  })
19  .then(() => {
20    console.timeEnd('Data processing');
21  });

This is extremely useful for identifying bottlenecks in applications and optimizing performance.

6. console.trace() — Call Stack Tracing

When you don't know exactly where a function was called from:

1function monitorFenceStatus(sectorId) {
2  console.trace(`Checking fence status in sector ${sectorId}`);
3  // Rest of code...
4}
5
6function checkAllFences() {
7  const sectors = ['A1', 'B2', 'C3'];
8  sectors.forEach(monitorFenceStatus);
9}
10
11function dailySecurityCheck() {
12  checkAllFences();
13}
14
15dailySecurityCheck();

console.trace()
will display the full call stack, showing the exact execution path, which is invaluable when debugging complex calls.

7. console.assert() — Conditional Debug Messages

Checks a condition and displays an error when the condition is false:

1function feedDinosaur(dinosaur, foodAmount) {
2  // Make sure the food amount is sufficient for the species
3  console.assert(
4    foodAmount >= getMinimumFoodRequirement(dinosaur.species),
5    `Insufficient food for ${dinosaur.name}! ` +
6    `Required minimum: ${getMinimumFoodRequirement(dinosaur.species)}kg, ` +
7    `Provided: ${foodAmount}kg`
8  );
9
10  // Rest of code...
11}
12
13feedDinosaur(dinosaurs[0], 5); // If 5kg is too little, we'll see an error

This is useful for early detection of potential problems without stopping program execution.

8. console.count() — Counting Calls

Counting how many times a function or code block has been called:

1function checkFenceVoltage(sectorId) {
2  console.count(`Voltage check in sector ${sectorId}`);
3  // Rest of code...
4}
5
6// Simulate regular checks
7setInterval(() => checkFenceVoltage('A1'), 5000);
8setInterval(() => checkFenceVoltage('B2'), 8000);

After each call we'll see in the console something like:

1Voltage check in sector A1: 1
2Voltage check in sector A1: 2
3Voltage check in sector B2: 1
4Voltage check in sector A1: 3

We can reset the counter using

console.countReset('name')
.

9. console.dir() — Displaying Object Properties

When we want to see the full structure of an object:

1const parkSystem = {
2  name: "Jurassic Park",
3  sectors: {
4    A: { dinosaurs: [/*...*/], status: "secure" },
5    B: { dinosaurs: [/*...*/], status: "alert" }
6  },
7  security: {
8    fences: { status: "online", voltage: 10000 },
9    cameras: { operational: 45, offline: 3 }
10  }
11};
12
13// Displays an interactive, expandable object structure
14console.dir(parkSystem);

This function is especially useful for complex objects, as it allows browsing nested properties.

10. Console Message Formatting

The console also supports basic formatting with format specifiers:

1// Styling text with CSS
2console.log(
3  "%cWARNING! %cCritical danger level %cin sector B!",
4  "color: red; font-size: 20px; font-weight: bold;",
5  "color: orange; font-size: 16px;",
6  "color: black; font-weight: bold;"
7);
8
9// Displaying variables in a message
10console.log("Dinosaur %s has danger level %d", "Rex", 9);

Advanced Console Features

1. Filtering Messages

Most browser consoles allow filtering displayed messages. We can filter by:

  • Level (Error, Warning, Info, Log)
  • Text (typing a search phrase)
  • Source (e.g. only from a specific file)

This is extremely useful when dealing with large volumes of logs.

2. Saving to File

Console messages can usually be saved to a file, which is useful for log analysis:

  1. Right-click in the console
  2. Select "Save as..."

3. Clearing the Console

The console can be cleared in several ways:

  • Clicking the crossed-circle icon in the console
  • Pressing <kbd>Ctrl</kbd>+<kbd>L</kbd> (when the console is active)
  • Using code:
    console.clear()

4. Console as a REPL Environment

The browser console also works as a REPL (Read-Eval-Print Loop), meaning we can execute JavaScript code directly in it:

1// Directly in console
2const dinos = [{name: "Rex"}, {name: "Blue"}];
3dinos.filter(d => d.name === "Blue");
4
5// Defining functions
6function alertSecurity(message) {
7  return `[SECURITY ALERT] ${message} - ${new Date().toISOString()}`;
8}
9
10// Using the function
11alertSecurity("Fence breach in sector C2");

This is extremely useful for testing small code snippets or debugging without modifying source code.

Practical Implementation in Our Jurassic Park System

Let's create a practical implementation of a logging system for our Jurassic Park that makes use of various console functions:

1// Logger for the Jurassic Park system
2class JurassicLogger {
3  constructor(moduleName) {
4    this.moduleName = moduleName;
5    this.logCount = 0;
6    this.errorCount = 0;
7    this.warnCount = 0;
8  }
9
10  log(...args) {
11    this.logCount++;
12    console.log(`[${this.moduleName}] `, ...args);
13  }
14
15  error(...args) {
16    this.errorCount++;
17    console.error(`[${this.moduleName}] ERROR:`, ...args);
18  }
19
20  warn(...args) {
21    this.warnCount++;
22    console.warn(`[${this.moduleName}] WARNING:`, ...args);
23  }
24
25  info(...args) {
26    console.info(`[${this.moduleName}] INFO:`, ...args);
27  }
28
29  startGroup(label) {
30    console.group(`[${this.moduleName}] ${label}`);
31  }
32
33  endGroup() {
34    console.groupEnd();
35  }
36
37  startTimer(label) {
38    console.time(`[${this.moduleName}] ${label}`);
39  }
40
41  endTimer(label) {
42    console.timeEnd(`[${this.moduleName}] ${label}`);
43  }
44
45  table(data, columns) {
46    console.log(`[${this.moduleName}] Tabular data:`);
47    console.table(data, columns);
48  }
49
50  getStats() {
51    return {
52      moduleName: this.moduleName,
53      logs: this.logCount,
54      errors: this.errorCount,
55      warnings: this.warnCount
56    };
57  }
58
59  trace(message) {
60    console.log(`[${this.moduleName}] TRACE: ${message}`);
61    console.trace();
62  }
63
64  assert(condition, message) {
65    console.assert(condition, `[${this.moduleName}] Assertion failed: ${message}`);
66  }
67
68  // Special formatting for security alerts
69  securityAlert(message, level = 'warning') {
70    const styles = {
71      warning: "background: #FFA500; color: black; padding: 2px 5px; border-radius: 3px;",
72      critical: "background: #FF0000; color: white; padding: 2px 5px; border-radius: 3px; font-weight: bold;",
73      info: "background: #0066FF; color: white; padding: 2px 5px; border-radius: 3px;"
74    };
75
76    console.log(
77      `%c[${this.moduleName}] SECURITY ALERT %c${message}`,
78      styles[level] || styles.warning,
79      "color: black;"
80    );
81  }
82}
83
84// Example usage
85const securityLogger = new JurassicLogger('ParkSecurity');
86const dinosaurLogger = new JurassicLogger('DinosaurTracker');
87const systemLogger = new JurassicLogger('MainSystem');
88
89// System initialization
90systemLogger.startTimer('System initialization');
91systemLogger.log('Starting Jurassic Park system initialization...');
92
93setTimeout(() => {
94  systemLogger.info('Subsystems started');
95  systemLogger.endTimer('System initialization');
96
97  // Dinosaur information
98  const dinoData = [
99    { id: 'TRX-01', name: 'Rex', species: 'T-Rex', status: 'contained', healthLevel: 92 },
100    { id: 'VEL-01', name: 'Blue', species: 'Velociraptor', status: 'contained', healthLevel: 87 },
101    { id: 'VEL-02', name: 'Delta', species: 'Velociraptor', status: 'sedated', healthLevel: 65 },
102    { id: 'TRI-01', name: 'Sarah', species: 'Triceratops', status: 'contained', healthLevel: 95 }
103  ];
104
105  dinosaurLogger.startGroup('Dinosaur status report');
106  dinosaurLogger.table(dinoData);
107
108  // Check dinosaur health
109  dinoData.forEach(dino => {
110    dinosaurLogger.startGroup(`Dinosaur: ${dino.name}`);
111
112    if (dino.healthLevel < 70) {
113      dinosaurLogger.warn(`Dinosaur ${dino.name} health level is low: ${dino.healthLevel}%`);
114    } else {
115      dinosaurLogger.log(`Health status: ${dino.healthLevel}%`);
116    }
117
118    if (dino.status !== 'contained') {
119      dinosaurLogger.error(`Dinosaur ${dino.name} is not in its enclosure! Status: ${dino.status}`);
120      securityLogger.securityAlert(`Dinosaur ${dino.name} (${dino.species}) status: ${dino.status}`, 'critical');
121    }
122
123    dinosaurLogger.endGroup();
124  });
125
126  dinosaurLogger.endGroup();
127
128  // Check security systems
129  securityLogger.startGroup('Security systems');
130
131  const fenceStatus = { sector: 'B', voltage: 9800, status: 'active' };
132  securityLogger.log(`Fence status in sector ${fenceStatus.sector}: ${fenceStatus.status}`);
133  securityLogger.assert(
134    fenceStatus.voltage >= 10000,
135    `Fence voltage in sector ${fenceStatus.sector} is too low: ${fenceStatus.voltage}V (min. 10000V)`
136  );
137
138  securityLogger.endGroup();
139
140  // Display log stats
141  systemLogger.startGroup('Log statistics');
142  console.table([
143    securityLogger.getStats(),
144    dinosaurLogger.getStats(),
145    systemLogger.getStats()
146  ]);
147  systemLogger.endGroup();
148
149}, 2000);

Production and Development Logging

In real applications it's worth separating development logging from production logging:

1// logger.js
2class Logger {
3  constructor(isProduction = process.env.NODE_ENV === 'production') {
4    this.isProduction = isProduction;
5  }
6
7  log(...args) {
8    if (!this.isProduction) {
9      console.log(...args);
10    }
11  }
12
13  // For critical errors, we log even in production
14  error(...args) {
15    console.error(...args);
16
17    if (this.isProduction) {
18      // In production we can send errors to a monitoring service
19      this.sendToErrorMonitoring(args);
20    }
21  }
22
23  sendToErrorMonitoring(errorData) {
24    // Implementation for sending to Sentry, LogRocket, etc.
25  }
26}
27
28export default new Logger();

Summary

The browser console is a powerful tool that greatly simplifies debugging and monitoring JavaScript applications. In the context of our Jurassic Park, good logging practices can be the difference between a smoothly running park and... well, the scenario from the movies!

Key functions to remember:

  • console.log()
    — basic logging
  • console.error()
    ,
    console.warn()
    ,
    console.info()
    — different message levels
  • console.table()
    — clean data display
  • console.group()
    — organizing related logs
  • console.time()
    and
    console.timeEnd()
    — measuring performance
  • console.trace()
    — diagnosing where a call comes from
  • console.assert()
    — conditional debug messages

Remember to regularly use the console during development — it will help you detect and fix bugs faster, before the dinosaurs find a hole in your code!

Go to CodeWorlds