Debugging & Production Logging
📖 Concept
Effective debugging and structured logging are critical for maintaining Node.js applications. In production, logs are your primary window into application behavior.
Debugging tools:
| Tool | Use Case |
|---|---|
console.log() |
Quick dev debugging (remove before committing!) |
debugger statement |
Breakpoints in Node.js inspector |
node --inspect |
Chrome DevTools debugger |
| VS Code debugger | IDE-integrated debugging |
debug package |
Conditional debug logging (e.g., Express uses it) |
Production logging with Winston: Winston is the most popular logging library for Node.js. It supports multiple log levels, transports (console, file, database), and structured JSON logging.
Log levels (severity):
error: 0 → Application errors, crashes
warn: 1 → Unexpected behavior, deprecations
info: 2 → Important events (server start, user actions)
http: 3 → HTTP request/response logs
debug: 4 → Detailed debugging (disabled in production)
Structured logging best practices:
- Use JSON format — parseable by log aggregation tools (ELK, Datadog)
- Include context — request ID, user ID, timestamp
- Log at appropriate levels — don't log everything at
info - Never log sensitive data — passwords, tokens, credit cards
- Use correlation IDs — trace a request across microservices
🏠 Real-world analogy: Debugging is like being a detective. console.log is asking witnesses (prints). The Node.js debugger is reviewing security camera footage (step-by-step execution). Production logging is like a flight recorder (black box) — capturing everything needed to reconstruct events after they happen.
💻 Code Example
1// Debugging & Production Logging23// === 1. Winston Logger Setup ===4const winston = require("winston");56const logger = winston.createLogger({7 level: process.env.LOG_LEVEL || "info",8 format: winston.format.combine(9 winston.format.timestamp(),10 winston.format.errors({ stack: true }),11 winston.format.json()12 ),13 defaultMeta: { service: "my-api" },14 transports: [15 // Console (colorized for development)16 new winston.transports.Console({17 format:18 process.env.NODE_ENV === "development"19 ? winston.format.combine(winston.format.colorize(), winston.format.simple())20 : winston.format.json(),21 }),22 // File transports (production)23 new winston.transports.File({ filename: "logs/error.log", level: "error", maxsize: 5242880, maxFiles: 5 }),24 new winston.transports.File({ filename: "logs/combined.log", maxsize: 5242880, maxFiles: 5 }),25 ],26});2728// 2. Request logging middleware29function requestLogger(req, res, next) {30 const requestId = req.headers["x-request-id"] || require("crypto").randomUUID();31 req.requestId = requestId;32 res.setHeader("X-Request-Id", requestId);3334 const start = Date.now();3536 res.on("finish", () => {37 const duration = Date.now() - start;38 const logData = {39 requestId,40 method: req.method,41 url: req.originalUrl,42 statusCode: res.statusCode,43 duration: `${duration}ms`,44 ip: req.ip,45 userAgent: req.headers["user-agent"],46 userId: req.user?.id,47 };4849 if (res.statusCode >= 500) {50 logger.error("Request failed", logData);51 } else if (res.statusCode >= 400) {52 logger.warn("Client error", logData);53 } else {54 logger.info("Request completed", logData);55 }56 });5758 next();59}6061// 3. Usage in application code62logger.info("Server starting", { port: 3000, env: process.env.NODE_ENV });63logger.warn("Cache miss", { key: "user:42", source: "redis" });64logger.error("Database query failed", { query: "SELECT...", error: "Connection refused" });6566// ❌ NEVER log sensitive data67// logger.info("User login", { email, password }); // BAD!68// ✅ Log safely69// logger.info("User login", { email, userId: user.id }); // GOOD7071// 4. Node.js Debugger72// Start with: node --inspect src/server.js73// Open: chrome://inspect in Chrome74// Or use VS Code's built-in debugger7576// .vscode/launch.json77const vscodeLaunchConfig = {78 version: "0.2.0",79 configurations: [80 {81 type: "node",82 request: "launch",83 name: "Debug Server",84 program: "${workspaceFolder}/src/server.js",85 env: { NODE_ENV: "development" },86 restart: true,87 },88 {89 type: "node",90 request: "launch",91 name: "Debug Tests",92 program: "${workspaceFolder}/node_modules/.bin/jest",93 args: ["--runInBand", "--no-cache"],94 },95 ],96};9798// 5. Conditional debug logging (debug package)99// const debug = require("debug");100// const dbDebug = debug("app:db");101// const httpDebug = debug("app:http");102// dbDebug("Query executed:", query); // Only shows if DEBUG=app:db103// Start with: DEBUG=app:* node server.js104105// 6. Performance profiling106function measurePerformance() {107 console.time("operation");108 // ... do work109 console.timeEnd("operation"); // "operation: 123ms"110111 // More precise112 const { performance, PerformanceObserver } = require("perf_hooks");113 const start = performance.now();114 // ... do work115 const duration = performance.now() - start;116 logger.debug("Operation completed", { durationMs: duration.toFixed(2) });117}118119module.exports = { logger, requestLogger };
🏋️ Practice Exercise
Exercises:
- Set up Winston with console, file, and error-specific transports
- Create request logging middleware that includes request ID, method, URL, status, and duration
- Add correlation IDs — generate a unique ID per request and include it in all logs
- Configure VS Code debugger for both running the server and running tests
- Profile a slow endpoint using
console.time,perf_hooks, and Node.js--profflag - Set up structured logging that can be parsed by ELK Stack or Datadog
⚠️ Common Mistakes
Using
console.login production — it's synchronous, has no log levels, and can't be routed to files or services; use Winston or PinoLogging sensitive data — passwords, tokens, credit card numbers must NEVER appear in logs; audit your logs regularly
Not including correlation IDs — without request IDs, you can't trace a request through multiple log entries or services
Logging too much in production — excessive logging impacts performance and storage costs; use
infolevel in production,debugin developmentNot setting up log rotation — without rotation, log files grow indefinitely and fill the disk; use Winston's
maxsizeandmaxFilesoptions
💼 Interview Questions
🎤 Mock Interview
Mock interview is powered by AI for Debugging & Production Logging. Login to unlock this feature.