debug
Lightweight logging library dedicated to debugging. Features flexible log display control using DEBUG environment variable. Specialized for displaying debug information during development, automatically disabled in production. Adopted as internal debugging functionality by many Node.js libraries.
GitHub Overview
debug-js/debug
A tiny JavaScript debugging utility modelled after Node.js core's debugging technique. Works in Node.js and web browsers
Topics
Star History
Library
debug
Overview
debug is a "lightweight debugging-specific logging library for JavaScript/Node.js" developed with flexible log control via environment variables as its key feature. Conceptualized as a "tiny JavaScript debugging utility modeled after Node.js core's debugging technique," it specializes in displaying debug information during development and automatically disables in production environments. Adopted as internal debugging functionality by many Node.js libraries, it significantly improves development experience through detailed log display control using the DEBUG environment variable.
Details
debug 2025 edition maintains its solid position as a lightweight and concise debugging-focused library. Its versatility supporting both Node.js and web browsers unifies debugging experience across full-stack development. Provides features that maximize development efficiency including hierarchical debug category management through namespace functionality, DEBUG environment variable control with wildcard support, and improved log visibility through color output. Adopted as standard internal logging system in major Node.js libraries like Express, Socket.IO, and Request, realizing consistent debugging experience across the ecosystem.
Key Features
- Environment Variable Control: Flexible log display control via DEBUG environment variable
- Namespace Support: Hierarchical log category management with wildcard specification
- Lightweight Design: High-speed operation with minimal overhead
- Color Output: Automatic color-coded display in TTY environments
- Browser Support: Works in both Node.js and web browser environments
- Timing Information: Automatic display of elapsed time between logs
Pros and Cons
Pros
- Intuitive and flexible log control system via environment variables
- Lightweight design minimizes impact on production environments
- Detailed log management in large-scale projects through namespace functionality
- Wide adoption and standardization in Node.js ecosystem
- Unified debugging experience across browser and server-side
- Optimal as internal log functionality for library development
Cons
- Debug-only functionality with no production logging features
- No log level concept, only on/off control
- Lacks advanced log management features like file output and rotation
- Limited support for structured logs and JSON format
- Absence of error handling and exception processing features
- Comprehensive logging libraries needed for large-scale applications
Reference Pages
Usage Examples
Installation and Basic Setup
# Install debug library
npm install debug
# Verify usage in project
node -e "console.log(require('debug'))"
# Check version
npm list debug
# Global installation (for development)
npm install -g debug
Basic Debug Log Output
// Create basic debug instance
const debug = require('debug')('myapp');
// Simple log output
debug('Application started');
debug('Configuration file loaded');
// Output values
const config = { port: 3000, env: 'development' };
debug('Configuration: %O', config);
// String formatting
const userId = 123;
const userName = 'John Doe';
debug('User processing: ID=%d, Name=%s', userId, userName);
// Error information debugging
try {
throw new Error('Test error');
} catch (error) {
debug('Error caught: %O', error);
}
// Execution time measurement
debug('Processing started');
setTimeout(() => {
debug('Processing completed'); // Shows time difference like +5ms
}, 5);
Log Control via Environment Variables
# Display only specific namespace
DEBUG=myapp node app.js
# Specify multiple namespaces
DEBUG=myapp,database node app.js
# Use wildcards
DEBUG=myapp:* node app.js
# Exclude specification
DEBUG=*,-myapp:verbose node app.js
# Display all debug logs
DEBUG=* node app.js
# Disable logging
DEBUG= node app.js
# or
node app.js
# Partial wildcards
DEBUG=myapp:*,database:connection node app.js
Namespace Hierarchy and Module Separation
// Main application (app.js)
const debug = require('debug')('myapp:main');
const dbDebug = require('debug')('myapp:database');
const authDebug = require('debug')('myapp:auth');
debug('Application initialization');
// Database module (db.js)
const debug = require('debug')('myapp:database:connection');
const queryDebug = require('debug')('myapp:database:query');
function connectDB() {
debug('Database connection started');
// Connection process
debug('Connection completed: host=%s, port=%d', 'localhost', 5432);
}
function executeQuery(sql) {
queryDebug('SQL execution: %s', sql);
// Query execution
queryDebug('Result: %d rows retrieved', 42);
}
// Authentication module (auth.js)
const debug = require('debug')('myapp:auth:login');
const sessionDebug = require('debug')('myapp:auth:session');
function login(credentials) {
debug('Login attempt: user=%s', credentials.username);
if (validateCredentials(credentials)) {
sessionDebug('Session created: sessionId=%s', generateSessionId());
debug('Login successful');
} else {
debug('Login failed: Invalid credentials');
}
}
// HTTP request detailed logs
const requestDebug = require('debug')('myapp:http:request');
const responseDebug = require('debug')('myapp:http:response');
app.use((req, res, next) => {
requestDebug('%s %s - %s', req.method, req.url, req.get('User-Agent'));
res.on('finish', () => {
responseDebug('%s %s - %d', req.method, req.url, res.statusCode);
});
next();
});
Conditional Debugging and Performance Optimization
const debug = require('debug')('myapp:performance');
// Check debug enablement
if (debug.enabled) {
// Execute heavy processing only when debug is enabled
const memoryUsage = process.memoryUsage();
debug('Memory usage: %O', memoryUsage);
}
// Performance measurement with high-precision timer
function measurePerformance(operationName, fn) {
if (!debug.enabled) {
return fn(); // Skip measurement when debug is disabled
}
debug('%s started', operationName);
const startTime = process.hrtime.bigint();
const result = fn();
const endTime = process.hrtime.bigint();
const duration = Number(endTime - startTime) / 1000000; // Convert nanoseconds to milliseconds
debug('%s completed: %.2fms', operationName, duration);
return result;
}
// Usage example
const result = measurePerformance('Database query', () => {
// Heavy processing
return fetchDataFromDB();
});
// Dynamic debug control
function setDebugLevel(namespace, enabled) {
const debug = require('debug');
if (enabled) {
// Add to current settings
const current = process.env.DEBUG || '';
const newDebug = current ? `${current},${namespace}` : namespace;
debug.enabled = function(name) {
return new RegExp(newDebug.replace('*', '.*')).test(name);
};
} else {
// Disable specific namespace
debug.enabled = function(name) {
return !new RegExp(namespace.replace('*', '.*')).test(name);
};
}
}
// Runtime debug control example
setDebugLevel('myapp:verbose', false); // Disable verbose logs
setDebugLevel('myapp:error', true); // Enable error logs
Formatters and Custom Output
const debug = require('debug')('myapp');
// printf style formatting
debug('Integer: %d, String: %s, JSON: %O', 42, 'test', { key: 'value' });
// Detailed object display
const complexObject = {
user: { id: 1, name: 'John Doe' },
metadata: { created: new Date(), tags: ['important', 'user'] },
config: { theme: 'dark', language: 'en' }
};
debug('Complex object: %O', complexObject);
// Error object details
try {
JSON.parse('invalid json');
} catch (error) {
debug('JSON parse error: %O', {
message: error.message,
stack: error.stack,
name: error.name
});
}
// Custom formatter function
function formatUser(user) {
return `${user.name}(ID:${user.id})`;
}
const user = { id: 123, name: 'Jane Smith' };
debug('User processing: %s', formatUser(user));
// Array detailed display
const items = [
{ id: 1, name: 'Item 1', price: 1000 },
{ id: 2, name: 'Item 2', price: 2000 }
];
items.forEach((item, index) => {
debug('Item[%d]: %s - $%d', index, item.name, item.price);
});
// Binary data or Buffer debugging
const buffer = Buffer.from('Hello, debug', 'utf8');
debug('Buffer data: %O', {
length: buffer.length,
content: buffer.toString('utf8'),
hex: buffer.toString('hex')
});
Practical Application in Express.js
const express = require('express');
const debug = require('debug')('myapp:server');
const routeDebug = require('debug')('myapp:routes');
const dbDebug = require('debug')('myapp:database');
const app = express();
// Server startup log
debug('Express server initializing...');
// Middleware-level debugging
app.use((req, res, next) => {
routeDebug('Incoming: %s %s', req.method, req.url);
// Log on response completion
res.on('finish', () => {
routeDebug('Response: %s %s - %d (%dms)',
req.method, req.url, res.statusCode, Date.now() - req.startTime);
});
req.startTime = Date.now();
next();
});
// Route-specific debugging
app.get('/users/:id', async (req, res) => {
const userDebug = require('debug')('myapp:routes:users');
userDebug('User fetch request: ID=%s', req.params.id);
try {
dbDebug('User database query execution');
const user = await getUserById(req.params.id);
if (user) {
userDebug('User found: %s', user.name);
res.json(user);
} else {
userDebug('User not found: ID=%s', req.params.id);
res.status(404).json({ error: 'User not found' });
}
} catch (error) {
userDebug('User fetch error: %O', error);
res.status(500).json({ error: 'Internal server error' });
}
});
// Error handling middleware
app.use((error, req, res, next) => {
const errorDebug = require('debug')('myapp:error');
errorDebug('Unhandled error: %O', {
message: error.message,
stack: error.stack,
url: req.url,
method: req.method
});
res.status(500).json({ error: 'Something went wrong!' });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
debug('Server started: http://localhost:%d', PORT);
debug('Environment: %s', process.env.NODE_ENV || 'development');
});
// Graceful shutdown
process.on('SIGTERM', () => {
debug('SIGTERM received - Server shutdown initiated');
server.close(() => {
debug('Server shutdown completed');
process.exit(0);
});
});
Production Environment Support and Security Considerations
// Verify debug disabling in production environment
const debug = require('debug')('myapp');
// Automatic control by NODE_ENV
if (process.env.NODE_ENV === 'production') {
// Explicitly clear DEBUG environment variable in production
delete process.env.DEBUG;
// Or enable only minimal error logs
process.env.DEBUG = 'myapp:error,myapp:critical';
}
// Sensitive information protection
function safeDebug(namespace) {
const debug = require('debug')(namespace);
return function(message, ...args) {
// Filter data that may contain sensitive information
const filteredArgs = args.map(arg => {
if (typeof arg === 'object' && arg !== null) {
const filtered = { ...arg };
// Remove passwords and tokens
['password', 'token', 'secret', 'apiKey', 'privateKey'].forEach(key => {
if (filtered[key]) {
filtered[key] = '***REDACTED***';
}
});
return filtered;
}
return arg;
});
debug(message, ...filteredArgs);
};
}
// Safe debug log usage example
const safeLog = safeDebug('myapp:auth');
const loginData = {
username: '[email protected]',
password: 'secretpassword',
rememberMe: true
};
safeLog('Login attempt: %O', loginData); // password displays as ***REDACTED***
// Log level-style control implementation
const logLevels = {
error: require('debug')('myapp:error'),
warn: require('debug')('myapp:warn'),
info: require('debug')('myapp:info'),
debug: require('debug')('myapp:debug')
};
function log(level, message, ...args) {
if (logLevels[level]) {
logLevels[level](message, ...args);
}
}
// Usage example
log('error', 'Database connection failed: %s', error.message);
log('info', 'User registration completed: %s', user.email);
log('debug', 'Internal state: %O', internalState);