Knowing what went wrong.
WHAT TO DISTINGUISH
Expected failures: invalid input, not found, not permitted
Unexpected failures: bugs, unavailable dependencies
WHAT TO RETURN FOR EACH
Expected: a specific status and a clear message
Unexpected: a generic message, and an identifier
WHY AN IDENTIFIER
So the user can quote it and you can find the corresponding log entry.
WHAT NEVER TO RETURN
Stack traces File paths Database errors Framework versions
WHY
They assist an attacker and confuse the user.
WHAT TO LOG
Every unexpected error, with full detail Authentication and authorisation failures Significant business events Slow operations
WHAT NOT TO LOG
Passwords and tokens Card details Personal data beyond what is necessary
WHAT TO INCLUDE IN EVERY ENTRY
A timestamp, a severity, a message, and an identifier tying related entries together.
WHY THAT LAST ONE
So one request can be traced across every entry it produced.
WHAT TO SET UP
Alerting on error rate, not only on unavailability.
WHAT TO REVIEW
Logs regularly, not only during incidents.