Logging Overview
The AI-Enhanced TypeScript Template includes a comprehensive logging system built on Winston, providing structured, configurable, and professional logging for your TypeScript applications.
What is Winston Logging?
Winston is a versatile logging library for Node.js that provides:
- Multiple transport options (console, file, database, etc.)
- Configurable log levels (error, warn, info, debug)
- Structured logging with metadata support
- Custom formatting for different environments
- Performance optimized for production use
Key Features
🎯 Professional Logging
- Structured log messages with consistent formatting
- Multiple output targets (console with colors, JSON files)
- Configurable log levels for different environments
- Timestamp and metadata support for debugging
🔧 Easy Configuration
- Environment-aware setup with sensible defaults
- File and console outputs with different formats
- Configurable through application config or environment variables
- Hot-reloadable configuration for runtime adjustments
🛠️ Developer Experience
- Utility functions for common logging patterns
- Type-safe interfaces for dependency injection
- Test-friendly design with proper mocking support
- Professional patterns for production-ready logging
Quick Start
1. Import the Logger
typescript
import { logger } from './logger.js';
// Basic usage
logger.info('Application started');
logger.error('Something went wrong', { error: errorObject });
logger.debug('Debug information', { userId: 123, action: 'login' });
2. Use Logger Utilities
typescript
import { loggerUtils } from './logger.js';
// Validation logging
loggerUtils.logValidationSuccess(logger, 'User data validated', userData);
loggerUtils.logValidationFailure(logger, 'Invalid input', errorMessage);
// Section headers for better organization
loggerUtils.logSectionHeader(logger, 'Database Migration');
// Application lifecycle
loggerUtils.logStartup(logger, 'MyApp', '1.0.0');
loggerUtils.logCompletion(logger, 'Process completed successfully');
3. Configure for Your Environment
typescript
import { createLoggerFromConfig } from './logger.js';
// Load from application config
const config = {
level: 'info',
outputFile: 'app.log',
includeTimestamp: true,
useColors: true
};
const logger = createLoggerFromConfig(config);
Log Levels
Winston supports multiple log levels with different priorities:
Level | Priority | Usage | Example |
---|---|---|---|
error | 0 | System errors, exceptions | Database connection failed |
warn | 1 | Warning conditions | Deprecated API usage |
info | 2 | General information | User logged in, server started |
debug | 3 | Detailed debugging | Function entry/exit, variable values |
Level Filtering
typescript
// Only log 'error' and 'warn' messages in production
const productionLogger = createLogger({
level: 'warn',
outputFile: 'production.log',
useColors: false
});
// Log everything in development
const developmentLogger = createLogger({
level: 'debug',
outputFile: null, // Console only
useColors: true
});
Output Formats
Console Output (Development)
2024-01-15 10:30:45 [INFO]: Application started
2024-01-15 10:30:46 [ERROR]: Database connection failed { host: "localhost", port: 5432 }
JSON File Output (Production)
json
{
"timestamp": "2024-01-15T10:30:45.123Z",
"level": "info",
"message": "Application started",
"metadata": {}
}
{
"timestamp": "2024-01-15T10:30:46.456Z",
"level": "error",
"message": "Database connection failed",
"metadata": { "host": "localhost", "port": 5432 }
}
Configuration Options
Logger Configuration
typescript
interface LoggerConfig {
level: 'error' | 'warn' | 'info' | 'debug';
outputFile: string | null;
includeTimestamp: boolean;
useColors: boolean;
}
// Example configurations
const configs = {
development: {
level: 'debug',
outputFile: null,
includeTimestamp: true,
useColors: true
},
production: {
level: 'info',
outputFile: 'app.log',
includeTimestamp: true,
useColors: false
},
test: {
level: 'error',
outputFile: null,
includeTimestamp: false,
useColors: false
}
};
Environment Variables
bash
# Override configuration with environment variables
LOG_LEVEL=debug
LOG_FILE=debug.log
LOG_COLORS=true
LOG_TIMESTAMP=true
Integration with Validation
The logging system integrates seamlessly with the validation system:
typescript
import { validateUserInput } from './validation.js';
import { loggerUtils } from './logger.js';
function processUser(userData: unknown) {
const result = validateUserInput(userData);
if (result.success) {
loggerUtils.logValidationSuccess(
logger,
'User input validated successfully',
{ userId: result.data.name }
);
return result.data;
} else {
loggerUtils.logValidationFailure(
logger,
'User input validation failed',
result.error
);
throw new Error(`Invalid user data: ${result.error}`);
}
}
Professional Logging Patterns
Structured Logging Approach
typescript
// Professional logging with context and metadata
logger.info('User logged in', {
userId: user.id,
timestamp: new Date().toISOString(),
ip: req.ip
});
logger.error('Database error', {
error: { message: error.message, stack: error.stack },
operation: 'user_lookup',
duration: Date.now() - startTime
});
logger.info('Starting server', {
port,
host,
environment: process.env.NODE_ENV
});
Key Benefits
- Structured data with searchable metadata
- Configurable output (console, file, remote services)
- Log level filtering for different environments
- Better performance in production
- Rich context for debugging and monitoring
Best Practices
✅ Do
- Use appropriate log levels - error for errors, info for general information
- Include relevant metadata - user IDs, request IDs, error details
- Use structured logging - objects instead of string concatenation
- Configure for environment - debug in development, info in production
- Log application lifecycle - startup, shutdown, major operations
❌ Don't
- Log sensitive information - passwords, tokens, personal data
- Over-log in production - avoid debug logs in production
- Use basic console output - always use the structured logger
- Log without context - include relevant metadata
- Ignore log rotation - configure file rotation for production
Performance Considerations
Async Logging
typescript
// Winston handles async logging automatically
logger.info('This is logged asynchronously');
// For critical logs that must be written before continuing
await new Promise(resolve => logger.info('Critical log', resolve));
Log Sampling
typescript
// Sample logs in high-traffic scenarios
let logCounter = 0;
function conditionalLog(message: string, metadata?: object) {
logCounter++;
if (logCounter % 100 === 0) { // Log every 100th occurrence
logger.info(message, metadata);
}
}