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.

Logging LibraryNode.jsDebugLightweightEnvironment Variable Control

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

Stars11,300
Watchers139
Forks948
Created:November 29, 2011
Language:JavaScript
License:MIT License

Topics

browserdebugdebuggingjavascriptloggingnodenode-js

Star History

debug-js/debug Star History
Data as of: 7/17/2025, 10:32 AM

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);