# @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. 