UNPKG

@bernierllc/logging

Version:

A comprehensive logging package with Winston integration for audit and system logging

457 lines (338 loc) 13.4 kB
# @bernierllc/logging A comprehensive logging package with Winston integration for audit and system logging. This package provides a clean abstraction layer over Winston, with separate loggers for audit events and system events, ensuring proper separation of concerns and type safety. ## Features - **Dual Logger Architecture**: Separate loggers for audit events and system events - **Type Safety**: Full TypeScript support with comprehensive type definitions - **Winston Integration**: Built on top of Winston for robust logging capabilities - **Environment Awareness**: Automatic configuration based on environment - **Flexible Configuration**: Support for multiple transports and custom configurations - **Convenience Functions**: Easy-to-use logging methods for common scenarios - **Request Tracking**: Built-in support for request IDs and correlation - **File Logging with Rotation**: Production-ready file logging with automatic rotation - **Structured JSON Logging**: All logs are structured JSON for easy parsing and analysis ## Installation ```bash npm install @bernierllc/logging winston ``` ## Quick Start ### Basic Usage ```typescript import { logger, audit } from '@bernierllc/logging'; // System logging logger.info('Application started'); logger.error('Something went wrong', new Error('Database error')); // Audit logging audit({ actorId: 'user123', action: 'DELETE_PROJECT', target: 'project456', ip: '192.168.1.100', metadata: { reason: 'User request' } }); ``` ### Advanced Usage ```typescript import { createAuditLogger, createSystemLogger, logAudit, logSystem } from '@bernierllc/logging'; // Create custom loggers const auditLogger = createAuditLogger({ enableFile: true, filePath: './logs/audit.log', enableConsole: true }); const systemLogger = createSystemLogger({ level: 'debug', enableFile: true, filePath: './logs/system.log' }); // Use custom loggers logAudit(auditLogger, { actorId: 'admin456', action: 'CREATE_USER', target: 'user789' }); logSystem(systemLogger, { level: 'info', message: 'User created successfully', metadata: { userId: 'user789' } }); ``` ## File Logging Configuration ### Production-Ready File Logging The package now includes production-ready file logging with automatic rotation by default: ```typescript import { createSystemLogger } from '@bernierllc/logging'; // Production configuration (default behavior) const productionLogger = createSystemLogger({ enableConsole: false, // Disabled in production enableFile: true, // Enabled in production filePath: './logs/app.log', level: 'info', maxSize: '10m', // Rotate at 10MB maxFiles: '5', // Keep 5 rotated files tailable: true, // Enable tailing zippedArchive: true // Compress old files }); ``` ### Development Configuration ```typescript const developmentLogger = createSystemLogger({ enableConsole: true, // Enabled in development enableFile: true, // Also log to file filePath: './logs/dev.log', level: 'debug', maxSize: '5m', maxFiles: '3', tailable: true, zippedArchive: false // Don't compress in development }); ``` ### Log File Locations By default, logs are written to: - **System logs**: `./logs/app-YYYY-MM-DD.log` (with rotation) - **Audit logs**: `./logs/audit.log` - **Development logs**: `./logs/dev-YYYY-MM-DD.log` (when configured) ### Monitoring Logs To monitor logs in real-time: ```bash # Monitor all system logs tail -f logs/app-*.log # Monitor development logs tail -f logs/dev-*.log # Monitor audit logs tail -f logs/audit.log # Monitor specific date tail -f logs/app-2025-01-15.log ``` ### Log Rotation Configuration The package uses `winston-daily-rotate-file` for automatic log rotation: ```typescript const logger = createSystemLogger({ enableFile: true, filePath: './logs/app.log', maxSize: '10m', // Rotate when file reaches 10MB maxFiles: '5', // Keep 5 rotated files tailable: true, // Enable tailing for real-time monitoring zippedArchive: true, // Compress old log files datePattern: 'YYYY-MM-DD' // Date pattern for rotated files }); ``` **Rotation Options:** - `maxSize`: Maximum size before rotation (e.g., '10m', '100k', '1g') - `maxFiles`: Number of rotated files to keep - `tailable`: Enable real-time monitoring with `tail -f` - `zippedArchive`: Compress old log files to save space - `datePattern`: Date format for rotated file names ## API Reference ### Default Loggers The package provides pre-configured default loggers for immediate use: ```typescript import { defaultAuditLogger, defaultSystemLogger } from '@bernierllc/logging'; ``` ### Convenience Functions #### System Logging ```typescript import { logger } from '@bernierllc/logging'; logger.error(message: string, error?: Error, metadata?: Record<string, unknown>); logger.warn(message: string, metadata?: Record<string, unknown>); logger.info(message: string, metadata?: Record<string, unknown>); logger.debug(message: string, metadata?: Record<string, unknown>); ``` #### Audit Logging ```typescript import { audit } from '@bernierllc/logging'; audit(entry: AuditLogEntry): void; ``` ### Logger Creation #### `createAuditLogger(config?: AuditLoggerConfig): winston.Logger` Creates a Winston logger configured for audit logging. **Configuration Options:** - `level`: Log level (default: 'info') - `enableConsole`: Enable console transport (default: false) - `enableFile`: Enable file transport (default: false) - `filePath`: File path for logging (default: './logs/audit.log') - `databaseUrl`: Database URL for storage (requires additional transport) - `collection`: Database collection name (default: 'audit_logs') - `defaultMeta`: Default metadata for all log entries #### `createSystemLogger(config?: SystemLoggerConfig): winston.Logger` Creates a Winston logger configured for system logging. **Configuration Options:** - `level`: Log level (default: from LOG_LEVEL env var or 'info') - `enableConsole`: Enable console transport (default: true in dev, false in prod) - `enableFile`: Enable file transport (default: false in dev, true in prod) - `filePath`: File path for logging (default: './logs/system.log') - `enableSentry`: Enable Sentry transport (default: false) - `sentryDsn`: Sentry DSN for error tracking - `defaultMeta`: Default metadata for all log entries - `maxSize`: Maximum file size before rotation (default: '10m') - `maxFiles`: Number of rotated files to keep (default: '5') - `tailable`: Enable tailing for real-time monitoring (default: true) - `datePattern`: Date pattern for rotated files (default: 'YYYY-MM-DD') - `zippedArchive`: Compress old log files (default: true) ### Logging Functions #### `logAudit(logger: winston.Logger, entry: AuditLogEntry): void` Logs an audit entry using the specified logger. #### `logSystem(logger: winston.Logger, entry: SystemLogEntry): void` Logs a system entry using the specified logger. #### `logError(logger: winston.Logger, message: string, error?: Error, metadata?: Record<string, unknown>): void` Convenience function for logging errors. #### `logWarn(logger: winston.Logger, message: string, metadata?: Record<string, unknown>): void` Convenience function for logging warnings. #### `logInfo(logger: winston.Logger, message: string, metadata?: Record<string, unknown>): void` Convenience function for logging info messages. #### `logDebug(logger: winston.Logger, message: string, metadata?: Record<string, unknown>): void` Convenience function for logging debug messages. ## Type Definitions ### AuditLogEntry ```typescript type AuditLogEntry = { actorId: string; // Who performed the action action: string; // What action was performed target: string; // What was acted upon ip?: string; // IP address of the actor metadata?: Record<string, unknown>; // Additional context timestamp?: string; // When the action occurred userId?: string; // User ID (alternative to actorId) sessionId?: string; // Session identifier userAgent?: string; // User agent string requestId?: string; // Request correlation ID }; ``` ### SystemLogEntry ```typescript type SystemLogEntry = { level: 'error' | 'warn' | 'info' | 'debug'; message: string; timestamp?: string; metadata?: Record<string, unknown>; error?: Error; context?: string; requestId?: string; userId?: string; }; ``` ## Environment Configuration The package automatically adapts to different environments: ### Development - Audit logs are redirected to console (unless explicitly enabled) - System logs use console transport by default - Debug level logging is enabled - File logging is available but not enabled by default ### Production - Audit logs use file transport by default - System logs use file transport with rotation by default - Console logging is disabled by default - Error tracking can be enabled via Sentry ### Environment Variables - `NODE_ENV`: Determines environment-specific behavior - `LOG_LEVEL`: Sets the default log level for system logging ## Examples ### API Route Logging ```typescript import { logger, audit } from '@bernierllc/logging'; export async function handleUserAction(req, res) { const requestId = req.headers['x-request-id']; const userIp = req.headers['x-forwarded-for']; try { // Log the action audit({ actorId: req.user.id, action: 'UPDATE_PROFILE', target: 'profile', ip: userIp, requestId, metadata: { changes: req.body } }); // Process the request await updateUserProfile(req.user.id, req.body); logger.info('Profile updated successfully', { requestId, userId: req.user.id }); res.json({ success: true }); } catch (error) { logger.error('Profile update failed', error, { requestId, userId: req.user.id }); res.status(500).json({ error: 'Update failed' }); } } ``` ### Service-Specific Loggers ```typescript import { createSystemLogger } from '@bernierllc/logging'; function createServiceLogger(serviceName: string) { return createSystemLogger({ level: 'info', enableFile: true, filePath: `./logs/${serviceName}.log`, defaultMeta: { service: serviceName } }); } const userServiceLogger = createServiceLogger('user-service'); const paymentServiceLogger = createServiceLogger('payment-service'); ``` ## Troubleshooting ### Logs Not Appearing in Files 1. **Check file permissions**: Ensure the application has write permissions to the logs directory 2. **Verify configuration**: Make sure `enableFile: true` is set 3. **Check file path**: Verify the `filePath` is correct and accessible 4. **Environment variables**: Ensure `NODE_ENV` and `LOG_LEVEL` are set ### Log Rotation Not Working 1. **Check maxSize**: Ensure `maxSize` is set to a reasonable value (e.g., '10m') 2. **Verify maxFiles**: Make sure `maxFiles` is set to keep rotated files 3. **File permissions**: Ensure the application can create new files in the logs directory ### Performance Issues 1. **Reduce log level**: Set `level` to 'warn' or 'error' in production 2. **Disable console**: Set `enableConsole: false` in production 3. **Compress archives**: Enable `zippedArchive: true` to save disk space ## Best Practices ### 1. Use Appropriate Logger Types - Use audit logger for security-relevant events (logins, data changes, access attempts) - Use system logger for application events (startup, errors, performance metrics) ### 2. Include Request Correlation - Always include `requestId` in logs for traceability - Use consistent request ID generation across your application ### 3. Structured Metadata - Use structured metadata instead of string concatenation - Include relevant context (user ID, IP, timestamps) ### 4. Environment-Specific Configuration - Configure different transports for different environments - Use environment variables for sensitive configuration ### 5. Error Handling - Always include error objects in error logs - Provide sufficient context for debugging ### 6. File Logging Best Practices - Use log rotation to prevent disk space issues - Monitor log file sizes and rotation frequency - Use compression for archived logs in production - Set appropriate log levels for different environments ## Testing ```bash npm test ``` The package includes comprehensive tests for all functionality, including: - Logger creation and configuration - Log entry formatting and validation - Environment-specific behavior - Type safety validation - File logging and rotation ## Contributing 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Add tests for new functionality 5. Ensure all tests pass 6. Submit a pull request ## License MIT License - see LICENSE file for details. ## Support For issues and questions, please open an issue in the repository. ## Monorepo Workspaces & Dependency Management This package is part of a monorepo using npm workspaces. All dependencies are hoisted to the root. Always run `npm install` from the root directory. ## React 19 and Testing Library Compatibility This package uses React 19.1.0. If you see peer dependency warnings with Testing Library, use: ```bash npm install --legacy-peer-deps ``` This is a temporary workaround until official support is released.