Structured logging with proper levels, context, PII handling, centralized aggregation. Use for application logging, log management integration, distributed tracing, or encountering log bloat, PII exposure, missing context errors.
View on GitHubsecondsky/claude-skills
logging-best-practices
January 24, 2026
Select agents to install to:
npx add-skill https://github.com/secondsky/claude-skills/blob/main/plugins/logging-best-practices/skills/logging-best-practices/SKILL.md -a claude-code --skill logging-best-practicesInstallation paths:
.claude/skills/logging-best-practices/# Logging Best Practices
Implement secure, structured logging with proper levels and context.
## Log Levels
| Level | Use For | Production |
|-------|---------|------------|
| DEBUG | Detailed debugging | Off |
| INFO | Normal operations | On |
| WARN | Potential issues | On |
| ERROR | Errors with recovery | On |
| FATAL | Critical failures | On |
## Structured Logging (Winston)
```javascript
const winston = require('winston');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
defaultMeta: { service: 'api-service' },
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'error.log', level: 'error' })
]
});
// Usage
logger.info('User logged in', { userId: '123', ip: '192.168.1.1' });
logger.error('Payment failed', { error: err.message, orderId: '456' });
```
## Request Context
```javascript
const { AsyncLocalStorage } = require('async_hooks');
const storage = new AsyncLocalStorage();
app.use((req, res, next) => {
const context = {
requestId: req.headers['x-request-id'] || uuid(),
userId: req.user?.id
};
storage.run(context, next);
});
function log(level, message, meta = {}) {
const context = storage.getStore() || {};
logger.log(level, message, { ...context, ...meta });
}
```
## PII Sanitization
```javascript
const sensitiveFields = ['password', 'ssn', 'creditCard', 'token'];
function sanitize(obj) {
const sanitized = { ...obj };
for (const field of sensitiveFields) {
if (sanitized[field]) sanitized[field] = '[REDACTED]';
}
if (sanitized.email) {
sanitized.email = sanitized.email.replace(/(.{2}).*@/, '$1***@');
}
return sanitized;
}
```
## Best Practices
- Use structured JSON format
- Include correlation IDs across services
- Sanitize all PII before logging
- Use async logging for performance
- Implement log rotation
- Never log at DEBUG in p