Node.js & Express

Logging & Monitoring

18 min Lesson 25 of 40

Logging & Monitoring

Effective logging and monitoring are essential for maintaining, debugging, and understanding your Node.js applications in production. They help you track errors, analyze performance, detect security issues, and understand user behavior.

Why Logging Matters

Benefits of Proper Logging:
  • Debug production issues without access to the server
  • Track application errors and exceptions
  • Monitor security events and suspicious activities
  • Analyze performance bottlenecks
  • Audit user actions and compliance
  • Understand application behavior and usage patterns
  • Alert on critical events

Setting Up Winston Logger

Winston is the most popular logging library for Node.js:

npm install winston

Basic Winston setup:

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console({
      format: winston.format.combine(
        winston.format.colorize(),
        winston.format.simple()
      )
    }),
    new winston.transports.File({
      filename: 'logs/error.log',
      level: 'error'
    }),
    new winston.transports.File({
      filename: 'logs/combined.log'
    })
  ]
});

logger.info('Server started on port 3000');
logger.warn('API rate limit exceeded', { ip: '192.168.1.1' });
logger.error('Database connection failed', { error: err.message });

Morgan HTTP Request Logging

Morgan is an HTTP request logger middleware for Express:

npm install morgan
const express = require('express');
const morgan = require('morgan');

const app = express();

app.use(morgan('combined')); // Apache combined format

// Write logs to file
const accessLogStream = fs.createWriteStream(
  path.join(__dirname, 'logs', 'access.log'),
  { flags: 'a' }
);

app.use(morgan('combined', { stream: accessLogStream }));

Health Check Endpoints

// Simple health check
app.get('/health', (req, res) => {
  res.status(200).json({ status: 'ok' });
});

// Detailed health check
app.get('/health/detailed', async (req, res) => {
  const health = {
    uptime: process.uptime(),
    timestamp: Date.now(),
    status: 'ok',
    checks: {
      database: mongoose.connection.readyState === 1 ? 'up' : 'down',
      redis: await redisClient.ping() ? 'up' : 'down'
    }
  };

  res.status(200).json(health);
});
Logging Best Practices:
  • Use appropriate log levels
  • Include contextual information (user ID, request ID, etc.)
  • Never log sensitive data (passwords, tokens, credit cards)
  • Use structured logging for better searchability
  • Implement log rotation to prevent disk space issues
  • Set up alerts for critical errors
  • Monitor log volume for anomalies
Practice Exercise:
  1. Set up Winston logger with multiple transports
  2. Implement Morgan HTTP logging integrated with Winston
  3. Create structured logging for business events
  4. Build comprehensive health check endpoints
  5. Implement application metrics tracking