Logging & Observability Standards
Purpose
Logs are the black box recorder of your system. When failures happen at 2 AM in production, logs are your only witness. This skill ensures application state and failures are highly searchable, machine-readable, and traceable across system boundaries WITHOUT leaking sensitive user data.
When to use
- Bootstrapping a new backend microservice or monolithic API
- Refactoring code filled with disorganized
console.log or print statements
- Designing a system that spans multiple services/functions
- Setting up monitoring, alerting, and debugging infrastructure
When NOT to use
- Application performance monitoring (APM) - related but different concern
- Security incident response (use SIEM/security tools)
- User analytics (different use case, different tool)
Inputs required
- Backend service with multiple endpoints/functions
- Logging infrastructure (ELK, DataDog, Grafana Loki, CloudWatch, etc.)
- Understanding of structured logging concepts
Workflow
- Implement Structured Logging: Configure logger to output NDJSON (Newline Delimited JSON) instead of plain text
- Inject Context: Attach a
correlation_id (or trace_id) at HTTP entry point and pass through all downstream calls
- Standardize Levels: ERROR (system broken), WARN (unexpected but recovered), INFO (lifecycle), DEBUG (verbose tracing)
- Sanitize Data: Implement redaction middleware to mask credentials, tokens, and PII before logs hit the stream
- Add Request Context: Log request duration, status code, user context (anonymized), and performance metrics
- Trace Async Flows: Pass correlation ID through event handlers, message queues, and inter-service calls
- Monitor Log Health: Alert on high ERROR rates, unexpected patterns, or missing correlation IDs
Rules
- MUST output JSON in production environments (not plain text)
- MUST include Request ID/Correlation ID in all HTTP requests
- MUST NEVER log raw passwords, session tokens, or financial data
- MUST log full stack traces for ERROR level (for debugging)
- MUST log only message and context for WARN/INFO (not verbose)
- MUST redact/sanitize any PII before log emission
- MUST include timestamps in UTC
- MUST standardize key names across all logs
Anti-patterns
- String Concatenation:
logger.info("User " + userId + " failed to login") (unqueryable)
- Logging Expected Errors as ERROR: Logging validation failure as ERROR (use INFO/WARN)
- Silent Catching: Catching exception without logging the stack trace
- No Context: Logs with no request/correlation ID (impossible to trace)
- Unstructured Logs: Plain text logs without JSON structure
- Missing Timestamps: Logs without UTC timestamps (ordering problems)
- Over-Logging: Logging every line of execution (noise, storage cost)
Failure conditions
- Logs are plain text (not JSON)
- No correlation ID tracking
- PII or credentials in logs
- Missing stack traces on ERROR logs
- No way to correlate logs across services
Validation checklist
Output format
- Log structure: JSON with consistent keys: timestamp, level, message, correlationId, userId (anonymized), duration, error, stack
- Log format: NDJSON (one valid JSON object per line)
- Timestamps: UTC ISO 8601 format
- Levels: ERROR, WARN, INFO, DEBUG
- Middleware: Automatic request ID generation, redaction on output
Security considerations
- All PII (names, emails, phone numbers) MUST be redacted or anonymized
- Tokens, API keys, passwords MUST NEVER appear in logs
- Credit card data MUST NEVER appear in logs
- Database connection strings MUST be redacted
- User IDs may appear but real names MUST NOT
- Logs MUST be encrypted in transit and at rest
Agent execution notes
- Agent MAY: Add structured logging, implement correlation IDs, add redaction middleware, configure log rotation
- Agent MUST NEVER: Log passwords/tokens, use plain text logs, leave PII unredacted, omit stack traces
- Agent MUST ASK: Before adding new log messages that might contain PII, before changing log levels
- Agent MUST VALIDATE: Logs are JSON, correlation IDs flow through system, no PII present
Example
❌ Anti-pattern (String concatenation, no context, no redaction):
// BAD: Unstructured, concatenated
console.log('User ' + req.user.id + ' logged in at ' + new Date());
// BAD: No correlation ID
logger.info('Processing order');
logger.info('Order processed');
// BAD: Leaking PII and secrets
logger.error('Failed to connect: ' + process.env.DB_PASSWORD);
logger.info('User email: ' + user.email + ' password hash: ' + user.passwordHash);
// BAD: Expected error logged as ERROR
try {
const user = await User.findById(userId);
} catch (e) {
logger.error('User not found'); // WRONG level
}
✅ Correct pattern (Structured JSON, correlation IDs, redacted):
// CORRECT: Structured JSON with context
logger.info('User login successful', {
userId: 'user_123', // Anonymized or hashed
correlationId: req.id,
duration: Date.now() - req.startTime,
timestamp: new Date().toISOString()
});
// CORRECT: Correlation ID flows through system
const requestId = req.headers['x-request-id'] || uuid();
req.correlationId = requestId;
// Pass to downstream calls
await orderService.process(order, { correlationId: requestId });
// CORRECT: Redaction middleware
logger.addRedaction([
process.env.DB_PASSWORD,
/\d{4}-\d{4}-\d{4}-\d{4}/, // Credit card pattern
/@\w+\.\w+/, // Email pattern
]);
// CORRECT: Proper error logging with stack trace
try {
const user = await User.findById(userId);
} catch (error) {
logger.warn('User not found', {
userId,
correlationId: req.correlationId,
message: error.message
// Stack trace logged by error handler, not here
});
}
// CORRECT: Full context on errors
logger.error('Database connection failed', {
error: error.message, // Not the password!
code: error.code,
stack: error.stack,
correlationId: req.correlationId,
timestamp: new Date().toISOString(),
severity: 'critical'
});
1---2name: logging-observability-standards3description: When setting up telemetry, debugging distributed systems, or standardizing application output.4license: MIT5---67# Logging & Observability Standards89## Purpose10Logs are the black box recorder of your system. When failures happen at 2 AM in production, logs are your only witness. This skill ensures application state and failures are highly searchable, machine-readable, and traceable across system boundaries WITHOUT leaking sensitive user data.1112## When to use13- Bootstrapping a new backend microservice or monolithic API14- Refactoring code filled with disorganized `console.log` or `print` statements15- Designing a system that spans multiple services/functions16- Setting up monitoring, alerting, and debugging infrastructure1718## When NOT to use19- Application performance monitoring (APM) - related but different concern20- Security incident response (use SIEM/security tools)21- User analytics (different use case, different tool)2223## Inputs required24- Backend service with multiple endpoints/functions25- Logging infrastructure (ELK, DataDog, Grafana Loki, CloudWatch, etc.)26- Understanding of structured logging concepts2728## Workflow291. **Implement Structured Logging**: Configure logger to output NDJSON (Newline Delimited JSON) instead of plain text302. **Inject Context**: Attach a `correlation_id` (or `trace_id`) at HTTP entry point and pass through all downstream calls313. **Standardize Levels**: ERROR (system broken), WARN (unexpected but recovered), INFO (lifecycle), DEBUG (verbose tracing)324. **Sanitize Data**: Implement redaction middleware to mask credentials, tokens, and PII before logs hit the stream335. **Add Request Context**: Log request duration, status code, user context (anonymized), and performance metrics346. **Trace Async Flows**: Pass correlation ID through event handlers, message queues, and inter-service calls357. **Monitor Log Health**: Alert on high ERROR rates, unexpected patterns, or missing correlation IDs3637## Rules38- MUST output JSON in production environments (not plain text)39- MUST include Request ID/Correlation ID in all HTTP requests40- MUST NEVER log raw passwords, session tokens, or financial data41- MUST log full stack traces for ERROR level (for debugging)42- MUST log only message and context for WARN/INFO (not verbose)43- MUST redact/sanitize any PII before log emission44- MUST include timestamps in UTC45- MUST standardize key names across all logs4647## Anti-patterns48- **String Concatenation**: `logger.info("User " + userId + " failed to login")` (unqueryable)49- **Logging Expected Errors as ERROR**: Logging validation failure as ERROR (use INFO/WARN)50- **Silent Catching**: Catching exception without logging the stack trace51- **No Context**: Logs with no request/correlation ID (impossible to trace)52- **Unstructured Logs**: Plain text logs without JSON structure53- **Missing Timestamps**: Logs without UTC timestamps (ordering problems)54- **Over-Logging**: Logging every line of execution (noise, storage cost)5556## Failure conditions57- Logs are plain text (not JSON)58- No correlation ID tracking59- PII or credentials in logs60- Missing stack traces on ERROR logs61- No way to correlate logs across services6263## Validation checklist64- [ ] Logger outputs NDJSON (each line is valid JSON)65- [ ] Correlation ID/Trace ID included in all requests66- [ ] ERROR logs include full stack traces67- [ ] INFO/WARN logs are concise (no excessive detail)68- [ ] All timestamps in UTC69- [ ] No passwords, tokens, or PII in logs70- [ ] Request duration/latency logged71- [ ] Correlation ID passed through async/inter-service calls72- [ ] Redaction middleware configured and working73- [ ] Log levels used correctly (ERROR for failures, INFO for lifecycle)74- [ ] Searchable by correlation ID (verified in log aggregator)75- [ ] Sampling/retention policy defined (cost management)7677## Output format78- **Log structure**: JSON with consistent keys: timestamp, level, message, correlationId, userId (anonymized), duration, error, stack79- **Log format**: NDJSON (one valid JSON object per line)80- **Timestamps**: UTC ISO 8601 format81- **Levels**: ERROR, WARN, INFO, DEBUG82- **Middleware**: Automatic request ID generation, redaction on output8384## Security considerations85- All PII (names, emails, phone numbers) MUST be redacted or anonymized86- Tokens, API keys, passwords MUST NEVER appear in logs87- Credit card data MUST NEVER appear in logs88- Database connection strings MUST be redacted89- User IDs may appear but real names MUST NOT90- Logs MUST be encrypted in transit and at rest9192## Agent execution notes93- Agent MAY: Add structured logging, implement correlation IDs, add redaction middleware, configure log rotation94- Agent MUST NEVER: Log passwords/tokens, use plain text logs, leave PII unredacted, omit stack traces95- Agent MUST ASK: Before adding new log messages that might contain PII, before changing log levels96- Agent MUST VALIDATE: Logs are JSON, correlation IDs flow through system, no PII present9798## Example99100**❌ Anti-pattern (String concatenation, no context, no redaction):**101```javascript102// BAD: Unstructured, concatenated103console.log('User ' + req.user.id + ' logged in at ' + new Date());104105// BAD: No correlation ID106logger.info('Processing order');107logger.info('Order processed');108109// BAD: Leaking PII and secrets110logger.error('Failed to connect: ' + process.env.DB_PASSWORD);111logger.info('User email: ' + user.email + ' password hash: ' + user.passwordHash);112113// BAD: Expected error logged as ERROR114try {115 const user = await User.findById(userId);116} catch (e) {117 logger.error('User not found'); // WRONG level118}119```120121**✅ Correct pattern (Structured JSON, correlation IDs, redacted):**122```javascript123// CORRECT: Structured JSON with context124logger.info('User login successful', {125 userId: 'user_123', // Anonymized or hashed126 correlationId: req.id,127 duration: Date.now() - req.startTime,128 timestamp: new Date().toISOString()129});130131// CORRECT: Correlation ID flows through system132const requestId = req.headers['x-request-id'] || uuid();133req.correlationId = requestId;134135// Pass to downstream calls136await orderService.process(order, { correlationId: requestId });137138// CORRECT: Redaction middleware139logger.addRedaction([140 process.env.DB_PASSWORD,141 /\d{4}-\d{4}-\d{4}-\d{4}/, // Credit card pattern142 /@\w+\.\w+/, // Email pattern143]);144145// CORRECT: Proper error logging with stack trace146try {147 const user = await User.findById(userId);148} catch (error) {149 logger.warn('User not found', {150 userId,151 correlationId: req.correlationId,152 message: error.message153 // Stack trace logged by error handler, not here154 });155}156157// CORRECT: Full context on errors158logger.error('Database connection failed', {159 error: error.message, // Not the password!160 code: error.code,161 stack: error.stack,162 correlationId: req.correlationId,163 timestamp: new Date().toISOString(),164 severity: 'critical'165});166```