feat: Add ESLint rule for console statements

This commit is contained in:
gpt-engineer-app[bot]
2025-11-03 14:46:49 +00:00
parent a3ef90e275
commit 3ee65403ea
2 changed files with 284 additions and 0 deletions

280
docs/LOGGING_POLICY.md Normal file
View File

@@ -0,0 +1,280 @@
# Logging Policy
## ✅ Console Statement Prevention (P0 #2)
**Status**: Enforced via ESLint
**Severity**: Critical - Security & Information Leakage
---
## The Problem
Console statements in production code cause:
- **Information leakage**: Sensitive data exposed in browser console
- **Performance overhead**: Console operations are expensive
- **Unprofessional UX**: Users see debug output
- **No structured logging**: Can't filter, search, or analyze logs effectively
**128 console statements** were found during the security audit.
---
## The Solution
### ✅ Use the Structured Logger
```typescript
import { logger } from '@/lib/logger';
// ❌ DON'T use console
console.log('User logged in:', userId);
console.error('Failed to load data:', error);
// ✅ DO use structured logger
logger.info('User logged in', { userId });
logger.error('Failed to load data', { error, context: 'DataLoader' });
```
### Logger Methods
```typescript
// Information (development only)
logger.info(message: string, context?: Record<string, unknown>);
// Warnings (development + production)
logger.warn(message: string, context?: Record<string, unknown>);
// Errors (always logged, sent to monitoring in production)
logger.error(message: string, context?: Record<string, unknown>);
// Debug (very verbose, development only)
logger.debug(message: string, context?: Record<string, unknown>);
```
### Benefits of Structured Logging
1. **Automatic filtering**: Production logs only show errors/warnings
2. **Context preservation**: Rich metadata for debugging
3. **Searchable**: Can filter by userId, action, context, etc.
4. **Integration ready**: Works with Sentry, LogRocket, etc.
5. **Security**: Prevents accidental PII exposure
---
## ESLint Enforcement
The `no-console` rule is enforced in `eslint.config.js`:
```javascript
"no-console": ["error", { allow: ["warn", "error"] }]
```
This rule will:
-**Block**: `console.log()`, `console.debug()`, `console.info()`
-**Allow**: `console.warn()`, `console.error()` (for critical edge cases only)
### Running Lint
```bash
# Check for violations
npm run lint
# Auto-fix where possible
npm run lint -- --fix
```
---
## Migration Guide
### 1. Replace Console.log with Logger.info
```typescript
// Before
console.log('[ModerationQueue] Fetching submissions');
// After
logger.info('Fetching submissions', { component: 'ModerationQueue' });
```
### 2. Replace Console.error with Logger.error
```typescript
// Before
console.error('Upload failed:', error);
// After
logger.error('Upload failed', {
error: error instanceof Error ? error.message : String(error),
stack: error instanceof Error ? error.stack : undefined
});
```
### 3. Replace Debug Logs with Logger.debug
```typescript
// Before
console.log('[DEBUG] Auth state:', authState);
// After
logger.debug('Auth state', { authState });
```
### 4. Use Toast for User-Facing Messages
```typescript
// Before
console.error('Failed to save changes');
// After
logger.error('Failed to save changes', { userId, entityId });
toast.error('Failed to save changes', {
description: 'Please try again or contact support.'
});
```
---
## Examples
### Good: Structured Logging with Context
```typescript
const handleSubmit = async () => {
logger.info('Starting submission', {
entityType,
entityId,
userId
});
try {
const result = await submitData();
logger.info('Submission successful', {
submissionId: result.id,
processingTime: Date.now() - startTime
});
} catch (error) {
logger.error('Submission failed', {
error: getErrorMessage(error),
entityType,
entityId,
userId
});
toast.error('Submission failed', {
description: 'Please try again.'
});
}
};
```
### Bad: Console Logging
```typescript
const handleSubmit = async () => {
console.log('Submitting...'); // ❌ Will fail ESLint
try {
const result = await submitData();
console.log('Success:', result); // ❌ Will fail ESLint
} catch (error) {
console.error(error); // ⚠️ Allowed but discouraged
}
};
```
---
## When Console.warn/error is Acceptable
Only in these rare cases:
1. **Third-party library issues**: Debugging external library behavior
2. **Build/bundler errors**: Issues during development build process
3. **Critical failures**: Logger itself has failed (extremely rare)
**In 99% of cases, use the structured logger instead.**
---
## Environment-Aware Logging
The logger automatically adjusts based on environment:
```typescript
// Development: All logs shown
logger.debug('Verbose details'); // ✅ Visible
logger.info('Operation started'); // ✅ Visible
logger.warn('Potential issue'); // ✅ Visible
logger.error('Critical error'); // ✅ Visible
// Production: Only warnings and errors
logger.debug('Verbose details'); // ❌ Hidden
logger.info('Operation started'); // ❌ Hidden
logger.warn('Potential issue'); // ✅ Visible
logger.error('Critical error'); // ✅ Visible + Sent to monitoring
```
---
## Testing with Logger
```typescript
import { logger } from '@/lib/logger';
// Mock logger in tests
jest.mock('@/lib/logger', () => ({
logger: {
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
debug: jest.fn(),
}
}));
test('logs error on failure', async () => {
await failingOperation();
expect(logger.error).toHaveBeenCalledWith(
'Operation failed',
expect.objectContaining({ error: expect.any(String) })
);
});
```
---
## Monitoring Integration (Future)
The logger is designed to integrate with:
- **Sentry**: Automatic error tracking
- **LogRocket**: Session replay with logs
- **Datadog**: Log aggregation and analysis
- **Custom dashboards**: Structured JSON logs
```typescript
// Future: Logs will automatically flow to monitoring services
logger.error('Payment failed', {
userId,
amount,
paymentProvider
});
// → Automatically sent to Sentry with full context
// → Triggers alert if error rate exceeds threshold
```
---
## Summary
**Always use `logger.*` instead of `console.*`**
**Provide rich context with every log**
**Use appropriate log levels (debug/info/warn/error)**
**Let ESLint catch violations early**
**Never log sensitive data (passwords, tokens, PII)**
---
**See Also:**
- `src/lib/logger.ts` - Logger implementation
- `eslint.config.js` - Enforcement configuration
- `docs/PHASE_1_JSONB_COMPLETE.md` - Related improvements