8.4 KiB
8.4 KiB
📝 Centralized Logging System
This guide covers the centralized, high-performance logging system implemented using Pino - the fastest JSON logger for Node.js applications.
🎯 Architecture Overview
Single Logger System
- ✅ Backend (BFF):
nestjs-pinowith Pino - ✅ Frontend: Custom structured logger compatible with backend
- ✅ Shared: Common interfaces and configurations
- ❌ No more mixed logging systems
Benefits of Centralization
- 🚀 Performance: Pino is 5x faster than winston
- 🔒 Security: Automatic sensitive data sanitization
- 📊 Structured: JSON logging for better parsing
- 🌐 Correlation: Request tracking across services
- 📈 Monitoring: Easy integration with log aggregation'
- this implemetnatin requires more type safety faeteur
🏗️ Implementation
Backend (BFF) - NestJS + Pino
// ✅ CORRECT: Use nestjs-pino Logger
import { Logger } from "nestjs-pino";
@Injectable()
export class UserService {
constructor(@Inject(Logger) private readonly logger: Logger) {}
async findUser(id: string) {
this.logger.info(`Finding user ${id}`);
// ... implementation
}
}
Frontend - Structured Logger
// ✅ CORRECT: Use shared logger interface
import { logger } from "@/lib/logger";
export function handleApiCall() {
logger.logApiCall("/api/users", "GET", 200, 150);
logger.logUserAction("user123", "login");
}
🚫 What NOT to Do
❌ Don't Use Multiple Logging Systems
// ❌ WRONG: Mixing logging systems
import { Logger } from "@nestjs/common"; // Don't use this - REMOVED
import { Logger } from "nestjs-pino"; // ✅ Use this - CENTRALIZED
// ❌ WRONG: Console logging in production
console.log("User logged in"); // Don't use console.log
logger.info("User logged in"); // Use structured logger
✅ Current Status: FULLY CENTRALIZED
- All BFF services now use
nestjs-pinoLogger - No more
@nestjs/commonLogger imports - No more
new Logger()instantiations - Single logging system throughout the entire backend
❌ Don't Use Console Methods
// ❌ WRONG: Direct console usage
console.log("Debug info");
console.error("Error occurred");
console.warn("Warning message");
// ✅ CORRECT: Structured logging
logger.debug("Debug info");
logger.error("Error occurred");
logger.warn("Warning message");
🔧 Configuration
Environment Variables
# Logging configuration
LOG_LEVEL=info # error, warn, info, debug, trace
APP_NAME=customer-portal-bff # Service identifier
NODE_ENV=development # Environment context
Log Levels
| Level | Numeric | Description |
|---|---|---|
error |
0 | Errors that need immediate attention |
warn |
1 | Warnings that should be monitored |
info |
2 | General information about operations |
debug |
3 | Detailed debugging information |
trace |
4 | Very detailed tracing information |
📝 Usage Examples
Basic Logging
// Simple messages
logger.info("User authentication successful");
logger.warn("Rate limit approaching");
logger.error("Database connection failed");
// With structured data
logger.info("Invoice created", {
invoiceId: "INV-001",
amount: 99.99,
userId: "user123",
});
API Call Logging
// Automatic API call logging
logger.logApiCall("/api/invoices", "POST", 201, 250, {
userId: "user123",
invoiceId: "INV-001",
});
User Action Logging
// User activity tracking
logger.logUserAction("user123", "password_change", {
ipAddress: "192.168.1.1",
userAgent: "Mozilla/5.0...",
});
Error Logging
// Comprehensive error logging
try {
// ... operation
} catch (error) {
logger.logError(error, "user_creation", {
userId: "user123",
email: "user@example.com",
});
}
🔍 Request Correlation
Automatic Correlation IDs
// Every request gets a unique correlation ID
// Headers: x-correlation-id: 1703123456789-abc123def
logger.info("Processing request", {
correlationId: req.headers["x-correlation-id"],
endpoint: req.url,
method: req.method,
});
Manual Correlation
// Set correlation context
logger.setCorrelationId("req-123");
logger.setUserId("user-456");
logger.setRequestId("req-789");
// All subsequent logs include this context
logger.info("User action completed");
📊 Production Logging
File Logging
// Automatic log rotation
// - Combined logs: logs/customer-portal-bff-combined.log
// - Error logs: logs/customer-portal-bff-error.log
// - Console output: stdout (for container logs)
Log Aggregation
// Structured JSON output for easy parsing
{
"timestamp": "2025-01-22T10:30:00.000Z",
"level": "info",
"service": "customer-portal-bff",
"environment": "production",
"message": "User authentication successful",
"correlationId": "req-123",
"userId": "user-456",
"data": {
"ipAddress": "192.168.1.1",
"userAgent": "Mozilla/5.0..."
}
}
🚀 Performance Benefits
Benchmarks (Pino vs Winston)
| Operation | Pino | Winston | Improvement |
|---|---|---|---|
| JSON serialization | 1x | 5x | 5x faster |
| Object serialization | 1x | 3x | 3x faster |
| String interpolation | 1x | 2x | 2x faster |
| Overall performance | 1x | 5x | 5x faster |
Memory Usage
- Pino: Minimal memory footprint
- Winston: Higher memory usage due to object retention
- Console: No memory overhead but unstructured
🔒 Security Features
Automatic Data Sanitization
// Sensitive data is automatically redacted
logger.info("User login", {
email: "user@example.com",
password: "[REDACTED]", // Automatically sanitized
token: "[REDACTED]", // Automatically sanitized
ipAddress: "192.168.1.1", // Safe to log
});
Sanitized Headers
// Request headers are automatically cleaned
{
"authorization": "[REDACTED]",
"cookie": "[REDACTED]",
"x-api-key": "[REDACTED]",
"user-agent": "Mozilla/5.0...", // Safe to log
"accept": "application/json" // Safe to log
}
🔄 Migration Guide
From @nestjs/common Logger
// ❌ OLD: @nestjs/common Logger
import { Logger } from "@nestjs/common";
private readonly logger = new Logger(ServiceName.name);
// ✅ NEW: nestjs-pino Logger
import { Logger } from "nestjs-pino";
constructor(@Inject(Logger) private readonly logger: Logger) {}
From Console Logging
// ❌ OLD: Console methods
console.log("Debug info");
console.error("Error occurred");
// ✅ NEW: Structured logger
logger.debug("Debug info");
logger.error("Error occurred");
From Winston
// ❌ OLD: Winston logger
import * as winston from 'winston';
const logger = winston.createLogger({...});
// ✅ NEW: Pino logger
import { Logger } from "nestjs-pino";
constructor(@Inject(Logger) private readonly logger: Logger) {}
📋 Best Practices
✅ Do's
- Use structured logging with context
- Include correlation IDs in all logs
- Log at appropriate levels
- Sanitize sensitive data
- Use consistent message formats
❌ Don'ts
- Don't mix logging systems
- Don't use console methods in production
- Don't log sensitive information
- Don't log large objects unnecessarily
- Don't use string interpolation for logging
🛠️ Troubleshooting
Common Issues
- Multiple Logger Instances: Ensure single logger per service
- Missing Correlation IDs: Check middleware configuration
- Performance Issues: Verify log level settings
- Missing Logs: Check file permissions and disk space
Debug Mode
# Enable debug logging
LOG_LEVEL=debug pnpm dev
# Check logger configuration
LOG_LEVEL=trace pnpm dev