Episode 3 — NodeJS MongoDB Backend Architecture / 3.12 — Logging and Monitoring

3.12 — Quick Revision: Logging and Monitoring

Your cheat sheet for log levels, Winston configuration, Morgan formats, error handling patterns, and monitoring tools. Bookmark this page for quick reference.


< Interview Questions | README >


Log Levels (Severity Order)

LevelPriorityWhen to UseExample
error0 (highest)Something brokeDB connection lost
warn1Potential issueSlow query, deprecation
info2Normal eventsUser login, order placed
http3HTTP requestsGET /api/users 200 45ms
debug4Dev debuggingVariable values
silly5 (lowest)Verbose tracingLoop iterations

Setting level = "warn" logs: error + warn (suppresses info, debug, silly)

Recommended Levels by Environment

EnvironmentLevelFormat
DevelopmentdebugColorized console
TestingerrorMinimal/silent
StaginginfoJSON files
Productionwarn or infoJSON files + aggregator

Winston Setup

const winston = require("winston");
require("winston-daily-rotate-file");

const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || "info",
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  defaultMeta: { service: "my-api" },
  transports: [
    new winston.transports.DailyRotateFile({
      filename: "logs/combined-%DATE%.log",
      datePattern: "YYYY-MM-DD",
      maxFiles: "14d",
      zippedArchive: true,
    }),
    new winston.transports.DailyRotateFile({
      filename: "logs/error-%DATE%.log",
      level: "error",
      datePattern: "YYYY-MM-DD",
      maxFiles: "30d",
    }),
  ],
});

if (process.env.NODE_ENV !== "production") {
  logger.add(new winston.transports.Console({
    format: winston.format.combine(
      winston.format.colorize(),
      winston.format.simple()
    ),
  }));
}

Winston Transports

TransportPurposeKey Options
ConsoleTerminal outputformat, level
FileWrite to filefilename, level, maxsize, maxFiles
DailyRotateFileDaily file rotationdatePattern, maxSize, maxFiles, zippedArchive
HttpSend to endpointhost, port, path

Winston Formats

FormatPurposeEnvironment
format.json()Structured JSON outputProduction
format.simple()level: messageBasic/testing
format.colorize()Color-coded levelsDevelopment
format.timestamp()Add timestamp fieldAll
format.errors({ stack: true })Include stack tracesAll
format.printf(fn)Custom format functionCustom
format.combine(...)Chain multiple formatsAll

Morgan Formats

FormatOutput ExampleBest For
devGET /api/users 200 45.123 ms (colorized)Development
combinedFull Apache format with referrer + user-agentProduction
commonApache common (no referrer/agent)Production
shortShorter than combinedGeneral
tinyGET /api/users 200 1234 - 45.123 msSimple

Morgan + Winston Integration

const morgan = require("morgan");
app.use(morgan("combined", {
  stream: { write: (msg) => logger.http(msg.trim()) },
  skip: (req) => req.url === "/health",
}));

Request ID Middleware

const { v4: uuidv4 } = require("uuid");
app.use((req, res, next) => {
  req.id = req.headers["x-request-id"] || uuidv4();
  res.setHeader("x-request-id", req.id);
  next();
});

Error Handling Middleware

app.use((err, req, res, next) => {
  logger.error("Request error", {
    error: err.message,
    stack: err.stack,
    method: req.method,
    url: req.originalUrl,
    requestId: req.id,
    userId: req.user?._id,
  });
  const status = err.statusCode || 500;
  res.status(status).json({
    status: "error",
    message: status === 500 ? "Internal server error" : err.message,
  });
});

Process-Level Error Handlers

process.on("unhandledRejection", (reason) => {
  logger.error("Unhandled Rejection", {
    error: reason instanceof Error ? reason.message : reason,
    stack: reason instanceof Error ? reason.stack : undefined,
  });
});

process.on("uncaughtException", (err) => {
  logger.error("Uncaught Exception", { error: err.message, stack: err.stack });
  process.exit(1);  // MUST exit
});

What to Log vs What NOT to Log

Always Log

EventLevel
Server start/stopinfo
User auth (login/logout/failure)info / warn
API errors (4xx, 5xx)warn / error
Database errorserror
External API calls (time + status)info
Business events (orders, payments)info
Slow queries/responseswarn

Never Log

DataReason
PasswordsSecurity
API keys / tokensSecurity
Credit card numbersPCI compliance
SSN / personal health dataPrivacy laws
Full request bodies with PIIData protection

Monitoring Tools Overview

ToolTypePurpose
SentryError monitoringCapture errors, stack traces, affected users
LogRocketSession replaySee what the user saw (frontend)
ELK StackLog aggregationCentralized search + dashboards
DatadogFull observabilityMetrics, logs, traces, dashboards
CloudWatchAWS loggingAWS-native log management
Prometheus + GrafanaMetricsReal-time metrics and alerting
PapertrailCloud loggingSimple log aggregation

ELK Stack Components

ComponentRole
ElasticsearchStore + index + search logs
LogstashIngest + transform + route logs
KibanaVisual dashboard + search UI
FilebeatLightweight log file shipper

Quick Debugging Checklist

  • Get the user ID or request ID from the error report
  • Search error logs for that ID within the time window
  • Find the request ID from the error log entry
  • Search ALL logs for that request ID to see the full trace
  • Read the stack trace to identify the failure point
  • Check for related errors (DB down? External API failure?)
  • Check recent deployments for the time window
  • Reproduce in staging, fix, deploy, verify

Library Comparison

FeatureWinstonPinoMorgan
TypeGeneral loggerGeneral loggerHTTP logger
SpeedModerateFastestN/A
FormatsMultipleJSONPredefined strings
TransportsBuilt-inSeparate processStream
ExpressManualpino-httpBuilt-in middleware
Best forMost appsHigh-throughputHTTP access logs
Common comboWinston + MorganPino + pino-httpWith Winston/Pino