Help us improve
Share bugs, ideas, or general feedback.
Implements structured logging with levels, request context, PII sanitization using Winston in Node.js. Covers Python structlog, Go zap, ELK/CloudWatch integration for log bloat, PII exposure, missing context.
npx claudepluginhub secondsky/claude-skills --plugin logging-best-practicesHow this skill is triggered — by the user, by Claude, or both
Slash command
/logging-best-practices:logging-best-practicesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Implement secure, structured logging with proper levels and context.
Implements structured JSON logging with levels, correlation IDs, PII redaction, aggregation, and retention for Node.js, Go, Python apps. Migrates from console.log/printf.
Guides log level selection, structured logging, and error tracking integration. Use when implementing logging in application code to keep error tracking actionable.
Provides structured JSON logging patterns with correlation IDs, context propagation, log levels, and required fields for observability and production incident debugging.
Share bugs, ideas, or general feedback.
Implement secure, structured logging with proper levels and context.
| 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 |
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' });
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 });
}
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;
}
See references/advanced-logging.md for: