console.log(...) | Unstructured, not centralised | Replace with logger.debug(...) or remove |
logger.info(...) | Creates noise | Evaluate: is it warn, error, or debug? |
logger.error('Error') | No context | Add contextual metadata |
catch (err) { logger.error(err) } then re-throws | Duplicate logging | Log at the boundary only |
| Logging PII/secrets | Security risk | Mask or remove |
| Different loggers/alerters in different files | Inconsistency | Use single logger/alerter module |
try/catch that silently swallows | Lost errors | Log or re-throw |
| Fatal error with no alert | Silent failure | Add alert at the error boundary |
| Alert inside a loop or retry | Alert flood | Move alert outside loop, add dedup |
| Alert with no context | Unactionable | Add service, error, scope, log pointer |
| Alert on expected conditions | Alert fatigue | Remove — only alert on unexpected failures |
| Alert but no log | Missing investigation trail | Always log before alerting |
| Frontend calling alerting service directly | Security risk | Route through backend API |
| No trace context propagation on outbound calls | Broken traces | Add middleware for automatic propagation |
| Liveness probe checking all dependencies | Cascading restarts | Liveness: process only; readiness: deps |
| High-cardinality metric labels (user/request ids) | Metric explosion, cost | Ids belong in traces and logs, not labels |
| No correlation ID in log entries | Cannot link logs to traces | Include trace ID in structured log context |
| SLO defined but not measured | False confidence | Instrument the SLI and track the target |