Skip to content

Structured Logging System

This document provides an overview of the centralized structured logging system implemented for the PRS Backend project.

Overview

The logging system consists of:

  1. Logger Service: A centralized service for structured logging
  2. Log Formatters: Utilities for consistent log formatting
  3. Log Middleware: Middleware for request and database logging
  4. Log Transport: Configuration for log destinations and rotation

Logger Service

The LoggerService provides a consistent interface for logging throughout the application:

JavaScript
const { logger } = require('../infra/logs');

// Basic logging
logger.info('User logged in', { userId: 123 });
logger.error('Failed to process payment', { orderId: 456 });

// Error logging
try {
  // Some operation
} catch (error) {
  logger.error(error, { context: 'payment-processing' });
}

// Business event logging
logger.logBusinessEvent('Order Placed', { 
  orderId: 123, 
  amount: 99.99, 
  items: 3 
});

// Database operation logging
logger.logDatabase('INSERT', 'User', { 
  userId: 123, 
  fields: ['name', 'email'] 
});

Log Levels

The logger supports the following log levels (in order of increasing severity):

  • TRACE: Detailed information for debugging
  • DEBUG: Debugging information
  • INFO: General information about application operation
  • WARN: Warning conditions
  • ERROR: Error conditions
  • FATAL: Severe error conditions that may cause the application to terminate

Log Categories

Logs are categorized to make filtering and analysis easier:

  • API: API requests and responses
  • DATABASE: Database operations
  • SECURITY: Authentication and authorization
  • PERFORMANCE: Performance metrics
  • BUSINESS: Business events and operations
  • INTEGRATION: External service interactions
  • SYSTEM: System-level events

Log Structure

All logs follow a consistent structure:

JSON
{
  "timestamp": "2023-06-01T12:34:56.789Z",
  "level": "info",
  "message": "User logged in",
  "service": "prs-backend",
  "environment": "development",
  "requestId": "01234567-89ab-cdef-0123-456789abcdef",
  "userId": 123,
  "username": "john.doe",
  "category": "security",
  "additionalData": {
    "ip": "192.168.1.1",
    "userAgent": "Mozilla/5.0..."
  }
}

Common Fields

  • timestamp: ISO 8601 timestamp
  • level: Log level
  • message: Log message
  • service: Service name
  • environment: Environment (development, production, etc.)
  • requestId: Request ID for correlation
  • userId: User ID (if available)
  • username: Username (if available)
  • category: Log category

Request Logging

All HTTP requests and responses are automatically logged with the following information:

Request Logs

JSON
{
  "message": "Incoming request",
  "category": "api",
  "request": {
    "id": "01234567-89ab-cdef-0123-456789abcdef",
    "method": "POST",
    "url": "/api/v1/users",
    "ip": "192.168.1.1",
    "userAgent": "Mozilla/5.0..."
  },
  "user": {
    "id": 123,
    "username": "john.doe",
    "role": "admin"
  }
}

Response Logs

JSON
{
  "message": "Outgoing response",
  "category": "api",
  "request": {
    "id": "01234567-89ab-cdef-0123-456789abcdef",
    "method": "POST",
    "url": "/api/v1/users"
  },
  "response": {
    "statusCode": 201,
    "responseTime": 123.45
  }
}

Database Logging

Database operations are automatically logged with the following information:

JSON
{
  "message": "DB INSERT on User",
  "category": "database",
  "database": {
    "operation": "INSERT",
    "model": "User",
    "query": "INSERT INTO users (name, email) VALUES ($1, $2)",
    "parameters": ["John Doe", "john@example.com"]
  }
}

Slow queries (> 100ms) are logged at the INFO level with additional performance information:

JSON
{
  "message": "Slow DB SELECT on User (150ms)",
  "category": "database",
  "database": {
    "operation": "SELECT",
    "model": "User",
    "duration": 150
  },
  "performance": {
    "slow": true,
    "duration": 150
  }
}

Error Logging

Errors are logged with detailed information:

JSON
{
  "message": "Failed to process payment",
  "category": "business",
  "error": {
    "name": "PaymentError",
    "message": "Payment gateway rejected the transaction",
    "stack": "PaymentError: Payment gateway rejected...",
    "code": "PAYMENT_REJECTED"
  },
  "order": {
    "id": 123,
    "amount": 99.99
  }
}

Log Configuration

The logging system is configured based on the environment:

Production

  • Logs are written to rotating files
  • Log level is set to INFO
  • Files are rotated based on size (50MB) and time (daily)
  • Old logs are compressed and retained for 14 days

Development

  • Logs are written to both console and files
  • Console logs are pretty-printed with colors
  • File logs include all levels (DEBUG and above)
  • Files are rotated based on size (10MB) and time (daily)

Local

  • Logs are written to console only
  • Console logs are pretty-printed with colors
  • Log level is set to DEBUG

Best Practices

  1. Use Appropriate Log Levels: Use the appropriate log level for each message
  2. Include Context: Always include relevant context in logs
  3. Structured Data: Use structured data instead of string concatenation
  4. Sensitive Information: Never log sensitive information (passwords, tokens, etc.)
  5. Correlation IDs: Use request IDs for correlating logs across services
  6. Business Events: Log important business events for auditing
  7. Performance Metrics: Log performance metrics for monitoring

Integration with Error Handling

The logging system integrates with the error handling system:

JavaScript
1
2
3
4
5
6
7
8
9
try {
  // Some operation
} catch (error) {
  // The error will be automatically translated to a standardized format
  logger.error(error, { context: 'payment-processing' });

  // Rethrow for the global error handler
  throw error;
}

Extending the Logging System

To add new log categories or formatters:

  1. Add new categories to LOG_CATEGORIES in loggerService.js
  2. Add new formatters to logFormatter.js
  3. Add new methods to LoggerService class as needed