Menu
×
   ❮     
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI R GO KOTLIN SASS VUE GEN AI SCIPY CYBERSECURITY DATA SCIENCE INTRO TO PROGRAMMING BASH RUST

Node.js Tutorial

Node HOME Node Intro Node Get Started Node JS Requirements Node.js vs Browser Node Cmd Line Node V8 Engine Node Architecture Node Event Loop

Asynchronous

Node Async Node Promises Node Async/Await Node Errors Handling

Module Basics

Node Modules Node ES Modules Node NPM Node package.json Node NPM Scripts Node Manage Dep Node Publish Packages

Core Modules

HTTP Module HTTPS Module File System (fs) Path Module OS Module URL Module Events Module Stream Module Buffer Module Crypto Module Timers Module DNS Module Assert Module Util Module Readline Module

JS & TS Features

Node ES6+ Node Process Node TypeScript Node Adv. TypeScript Node Lint & Formatting

Building Applications

Node Frameworks Express.js Middleware Concept REST API Design API Authentication Node.js with Frontend

Database Integration

MySQL Get Started MySQL Create Database MySQL Create Table MySQL Insert Into MySQL Select From MySQL Where MySQL Order By MySQL Delete MySQL Drop Table MySQL Update MySQL Limit MySQL Join
MongoDB Get Started MongoDB Create DB MongoDB Collection MongoDB Insert MongoDB Find MongoDB Query MongoDB Sort MongoDB Delete MongoDB Drop Collection MongoDB Update MongoDB Limit MongoDB Join

Advanced Communication

GraphQL Socket.IO WebSockets

Testing & Debugging

Node Adv. Debugging Node Testing Apps Node Test Frameworks Node Test Runner

Node.js Deployment

Node Env Variables Node Dev vs Prod Node CI/CD Node Security Node Deployment

Perfomance & Scaling

Node Logging Node Monitoring Node Performance Child Process Module Cluster Module Worker Threads

Node.js Advanced

Microservices Node WebAssembly HTTP2 Module Perf_hooks Module VM Module TLS/SSL Module Net Module Zlib Module Real-World Examples

Hardware & IoT

RasPi Get Started RasPi GPIO Introduction RasPi Blinking LED RasPi LED & Pushbutton RasPi Flowing LEDs RasPi WebSocket RasPi RGB LED WebSocket RasPi Components

Node.js Reference

Built-in Modules EventEmitter (events) Worker (cluster) Cipher (crypto) Decipher (crypto) DiffieHellman (crypto) ECDH (crypto) Hash (crypto) Hmac (crypto) Sign (crypto) Verify (crypto) Socket (dgram, net, tls) ReadStream (fs, stream) WriteStream (fs, stream) Server (http, https, net, tls) Agent (http, https) Request (http) Response (http) Message (http) Interface (readline)

Resources & Tools

Node.js Compiler Node.js Server Node.js Quiz Node.js Exercises Node.js Syllabus Node.js Study Plan Node.js Certificate

Node.js Logging


Why Logging Matters

Effective logging is essential for several reasons:

  • Debugging: Understand what's happening inside your application
  • Troubleshooting: Diagnose issues in production environments
  • Monitoring: Track application health and performance
  • Auditing: Record important events for compliance and security
  • Analytics: Gather data about application usage and behavior

Basic Logging with Console

Node.js provides built-in console methods for basic logging:

// Basic logging
console.log('Info message');
console.error('Error message');
console.warn('Warning message');
console.debug('Debug message');

// Log objects
const user = { id: 1, name: 'John', roles: ['admin', 'user'] };
console.log('User object:', user);

// Table output for arrays or objects
console.table([
  { name: 'John', age: 30, role: 'admin' },
  { name: 'Jane', age: 25, role: 'user' },
  { name: 'Bob', age: 40, role: 'guest' }
]);

// Timing operations
console.time('operation');
// Perform some operations...
for (let i = 0; i < 1000000; i++) {
  // Do something
}
console.timeEnd('operation'); // Outputs: operation: 4.269ms

// Grouping related logs
console.group('User Processing');
console.log('Loading user data...');
console.log('Validating user...');
console.log('Updating user profile...');
console.groupEnd();

// Stack trace
console.trace('Trace message');

Console Limitations

While the console is convenient, it has significant limitations for production use:

  • No built-in log levels for filtering
  • No log rotation or file management
  • No structured output formats like JSON
  • Limited integration with monitoring systems

Note: Console methods are synchronous when outputting to terminals/files and can impact performance if used frequently in production.


Structured Logging

Structured logging formats log messages as data objects (typically JSON) rather than plain text, making them easier to parse, search, and analyze.

Benefits of Structured Logging

  • Consistent format for machine readability
  • Better searchability and filtering
  • Simplified integration with log aggregation tools
  • Enhanced context with metadata

Example of a Structured Log Entry (JSON)

{
  "timestamp": "2023-11-28T15:24:39.123Z",
  "level": "error",
  "message": "Failed to connect to database",
  "service": "user-service",
  "context": {
    "requestId": "req-123-456",
    "userId": "user-789",
    "databaseHost": "db.example.com"
  },
  "error": {
    "name": "ConnectionError",
    "message": "Connection refused",
    "stack": "..."
  }
}

Popular Node.js Logging Libraries

Winston

Winston is a versatile logging library with support for multiple transports (outputs):

Basic Winston Setup

const winston = require('winston');

// Create a logger
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  defaultMeta: { service: 'user-service' },
  transports: [
    // Write logs to a file
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
  ],
});

// If not in production, also log to the console
if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: winston.format.simple(),
  }));
}

// Usage
logger.log('info', 'Hello distributed log files!');
logger.info('Hello again distributed logs');
logger.error('Something went wrong', { additionalInfo: 'error details' });

Custom Winston Formats

const winston = require('winston');
const { format } = winston;
const { combine, timestamp, label, printf } = format;

// Custom format
const myFormat = printf(({ level, message, label, timestamp }) => {
  return `${timestamp} [${label}] ${level}: ${message}`;
});

const logger = winston.createLogger({
  format: combine(
    label({ label: 'API Service' }),
    timestamp(),
    myFormat
  ),
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

logger.info('Application started');

Pino

Pino is designed to be a low-overhead logger with optimal performance:

Basic Pino Setup

const pino = require('pino');

// Create a logger
const logger = pino({
  level: 'info',
  timestamp: pino.stdTimeFunctions.isoTime,
  base: { pid: process.pid, hostname: require('os').hostname() }
});

// Usage
logger.info('Application started');
logger.info({ user: 'john' }, 'User logged in');
logger.error({ err: new Error('Connection failed') }, 'Database connection error');

Pino with Express

const express = require('express');
const pino = require('pino');
const pinoHttp = require('pino-http');

const app = express();
const logger = pino();
const httpLogger = pinoHttp({ logger });

// Add request logging middleware
app.use(httpLogger);

app.get('/', (req, res) => {
  req.log.info('User accessed homepage');
  res.send('Hello World!');
});

app.get('/error', (req, res) => {
  req.log.error('Something went wrong');
  res.status(500).send('Error!');
});

app.listen(8080, () => {
  logger.info('Server started on port 8080');
});

Bunyan

Bunyan is a structured logging library with a CLI for viewing logs:

Basic Bunyan Setup

const bunyan = require('bunyan');

// Create a logger
const logger = bunyan.createLogger({
  name: 'myapp',
  streams: [
    {
      level: 'info',
      stream: process.stdout
    },
    {
      level: 'error',
      path: 'error.log'
    }
  ],
  serializers: bunyan.stdSerializers
});

// Usage
logger.info('Application started');
logger.info({ user: 'john' }, 'User logged in');
logger.error({ err: new Error('Connection failed') }, 'Database connection error');

Application Logging Best Practices

Log Levels

Use appropriate log levels to categorize the importance and urgency of log messages:

  • error: Runtime errors, exceptions, and failures that require attention
  • warn: Warning conditions that don't stop the application but indicate potential issues
  • info: Informational messages about application events and milestones
  • debug: Detailed diagnostic information useful during development
  • trace: Very detailed debugging information (method entry/exit, variable values)

What to Log

DO LOG:

  • Application startup/shutdown events
  • Authentication and authorization events
  • API requests and responses
  • Database operations and performance metrics
  • Errors and exceptions with context
  • Resource usage and performance metrics
  • Configuration changes

DON'T LOG:

  • Passwords, tokens, API keys, or other credentials
  • Personally identifiable information (PII) without proper safeguards
  • Credit card numbers, social security numbers, or other sensitive data
  • Session IDs or cookies
  • Encryption keys

Contextual Logging

Include relevant context with each log entry to make troubleshooting easier:

const winston = require('winston');

// Create a base logger
const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [new winston.transports.Console()]
});

// Create a child logger with request context
function createRequestLogger(req) {
  return logger.child({
    requestId: req.id,
    method: req.method,
    url: req.url,
    ip: req.ip,
    userId: req.user ? req.user.id : 'anonymous'
  });
}

// Usage in Express middleware
app.use((req, res, next) => {
  req.id = generateRequestId();
  req.logger = createRequestLogger(req);
  req.logger.info('Request received');

  const start = Date.now();

  res.on('finish', () => {
    const duration = Date.now() - start;
    req.logger.info({
      statusCode: res.statusCode,
      duration: duration
    }, 'Request completed');
  });

  next();
});

function generateRequestId() {
  return Date.now().toString(36) + Math.random().toString(36).substring(2);
}

Log Management and Analysis

Log Rotation

Prevent log files from growing too large by implementing log rotation:

Winston with rotating file transport

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

const transport = new winston.transports.DailyRotateFile({
  filename: 'application-%DATE%.log',
  datePattern: 'YYYY-MM-DD',
  zippedArchive: true,
  maxSize: '20m',
  maxFiles: '14d'
});

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    transport,
    new winston.transports.Console()// Optional console transport
  ]
});

logger.info('Hello rotated logs');

Centralized Logging

For applications running across multiple servers or containers, centralize your logs for easier analysis:

Winston with Elasticsearch transport

const winston = require('winston');
require('winston-elasticsearch');

const esTransportOpts = {
  level: 'info',
  clientOpts: {
    node: 'http://localhost:9200'
  },
  indexPrefix: 'app-logs'
};

const logger = winston.createLogger({
  transports: [
    new winston.transports.Elasticsearch(esTransportOpts),
    new winston.transports.Console()// Optional console transport
  ]
});

logger.info('This log will go to Elasticsearch');

Popular Log Management Systems

  • ELK Stack (Elasticsearch, Logstash, Kibana): Comprehensive logging stack
  • Graylog: Centralized log management with a focus on security
  • Fluentd/Fluent Bit: Log collection and forwarding
  • Loki: Lightweight log aggregation system
  • Commercial options: Datadog, New Relic, Splunk, LogDNA, Loggly

Logging in Production

Performance Considerations

  • Use asynchronous logging to avoid blocking the event loop
  • Buffer logs for better performance
  • Adjust log levels to reduce volume in production
  • Sample high-volume logs rather than logging every occurrence

Security Considerations

  • Sanitize sensitive data before logging
  • Protect log files with appropriate permissions
  • Use encryption when transmitting logs
  • Implement retention policies for log data
  • Verify compliance with relevant regulations (GDPR, HIPAA, etc.)

Data Sanitization Example

const winston = require('winston');

// Custom format to sanitize sensitive data
const sanitizeFormat = winston.format((info) => {
  if (info.user && info.user.password) {
    info.user.password = '[REDACTED]';
  }

  if (info.user && info.user.creditCard) {
    info.user.creditCard = '[REDACTED]';
  }

  if (info.headers && info.headers.authorization) {
    info.headers.authorization = '[REDACTED]';
  }

  return info;
});

const logger = winston.createLogger({
  format: winston.format.combine(
    sanitizeFormat(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.Console()
  ]
});

// This sensitive data will be sanitized in the logs
logger.info({
  message: 'User registered',
  user: {
    name: 'John',
    email: 'john@example.com',
    password: 'secret123',
    creditCard: '4111-1111-1111-1111'
  },
  headers: {
    authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
  }
});

Debugging with Logs

Debug Module

The debug module provides a lightweight way to add conditional debug logging:

const debug = require('debug');

// Create named debuggers
const dbDebug = debug('app:db');
const apiDebug = debug('app:api');
const authDebug = debug('app:auth');

// Usage
dbDebug('Connected to database');
apiDebug('API request received at /users');
authDebug('User authenticated: %o', { id: 123, roles: ['admin'] });

// Enable with environment variable:
// DEBUG=app:* node app.js
// or
// DEBUG=app:db,app:auth node app.js

Correlation IDs

Track requests across multiple services using correlation IDs:

const express = require('express');
const { v4: uuidv4 } = require('uuid');
const winston = require('winston');
const app = express();

// Create a logger
const logger = winston.createLogger({
  transports: [new winston.transports.Console()],
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  )
});

// Correlation ID middleware
app.use((req, res, next) => {
  // Extract correlation ID from the request header or generate a new one
  const correlationId = req.headers['x-correlation-id'] || uuidv4();

  // Add it to the response headers
  res.setHeader('x-correlation-id', correlationId);

  // Add it to the request object
  req.correlationId = correlationId;

  // Create a request-specific logger
  req.logger = logger.child({ correlationId });

  req.logger.info({
    message: 'Request received',
    method: req.method,
    url: req.url
  });

  next();
});

// Routes
app.get('/', (req, res) => {
  req.logger.info('Processing home request');
  res.send('Hello World');
});

app.get('/error', (req, res) => {
  req.logger.error('Error occurred in request');
  res.status(500).send('Error');
});

app.listen(8080, () => {
  logger.info('Server started on port 8080');
});

Summary

  • Effective logging is crucial for debugging, monitoring, and troubleshooting Node.js applications
  • Use structured logging with JSON format for better searchability and analysis
  • Choose appropriate logging libraries like Winston, Pino, or Bunyan based on your needs
  • Apply best practices: use proper log levels, include context, and protect sensitive data
  • Implement log rotation and centralized logging for production environments
  • Consider performance and security implications when designing your logging strategy
  • Use correlation IDs to track requests through distributed systems



×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
sales@w3schools.com

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
help@w3schools.com

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2025 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.