LoggingDebugWinston5 min read

Logging and debugging your bot

Configure Winston or Pino for Node.js, Python logging module, log levels, structured logging and rotation.


Why structured logging?

console.log doesn't scale. You need log levels, timestamps, file rotation and consistent formatting to diagnose production issues.

Node.js: Winston

bash
npm install winston winston-daily-rotate-file
javascript
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({ format: 'YYYY-MM-DD HH:mm:ss' }),
    winston.format.errors({ stack: true }),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console({
      format: winston.format.combine(
        winston.format.colorize(),
        winston.format.simple()
      )
    }),
    new winston.transports.DailyRotateFile({
      filename: 'logs/bot-%DATE%.log',
      datePattern: 'YYYY-MM-DD',
      maxSize: '20m',
      maxFiles: '14d'
    })
  ]
});

// Usage
logger.info('Bot started', { guilds: client.guilds.cache.size });
logger.warn('Rate limit approaching', { bucket: '/channels/123' });
logger.error('Command error', { command: 'ban', error: err.message });

Node.js: Pino (faster)

bash
npm install pino pino-pretty
javascript
const pino = require('pino');

const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
  transport: {
    target: 'pino-pretty',
    options: { colorize: true, translateTime: 'SYS:standard' }
  }
});

logger.info({ event: 'ready', guilds: 42 }, 'Bot connected');

Python: logging module

python
import logging
from logging.handlers import RotatingFileHandler

def setup_logging():
    logger = logging.getLogger('discord_bot')
    logger.setLevel(logging.INFO)

    # Format
    formatter = logging.Formatter(
        '%(asctime)s | %(levelname)-8s | %(name)s | %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S'
    )

    # Console
    console = logging.StreamHandler()
    console.setFormatter(formatter)
    logger.addHandler(console)

    # File with rotation
    file_handler = RotatingFileHandler(
        'logs/bot.log', maxBytes=10*1024*1024, backupCount=5
    )
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    return logger

logger = setup_logging()
logger.info('Bot started with %d guilds', len(bot.guilds))

View logs in production

bash
# PM2 real-time logs
pm2 logs my-bot --lines 100

# Systemd/journalctl
journalctl -u discord-bot -f
journalctl -u discord-bot --since '1 hour ago'

# Search for specific errors
grep -i 'error' logs/bot-2026-01-15.log

Configure system logrotate

bash
sudo nano /etc/logrotate.d/discord-bot
terminal
/opt/bots/*/logs/*.log {
  daily
  rotate 14
  compress
  delaycompress
  missingok
  notifempty
}

Recommendations

  • Use levels: error > warn > info > debug
  • Never log tokens or sensitive data
  • Configure rotation to prevent filling the disk
  • In production use info level; in development use debug
  • Include relevant context (guild_id, user_id, command) in every log

Was this guide helpful?