Your app is shipped and running, and right now you cannot see inside it. A user hits an error, a nightly job dies, a page crawls, and you have no idea why. Scattered print statements are not a trail, they are noise you cannot search when it counts. This chapter gets you logs you can read back later and actually trust.
14.1.1Log the events, never the secrets
A log is the app narrating what it just did. Log the moments that matter: a request handled, an error caught, a payment taken. Give each one enough context to answer "what happened" later, which user, which record, what failed.
The harder discipline is what never goes in. Never write sensitive data to a log: passwords, access tokens, API keys, full card numbers, anyone's private information. Logs get copied, forwarded to other services, and read by people who should never see any of it. The OWASP logging guidance spells out the full list; the rule of thumb is log that a login happened and whose, never the password typed.
Watch out: the fastest way to leak secrets is logging a whole request or response object. Tokens and personal data ride along inside it. Log named fields, never the raw blob.
14.1.2Levels and fields make logs searchable
Give every line a log level so you can filter by how much it matters:
debug: detail you only want while buildinginfo: a normal event worth recordingwarn: something off but handlederror: something broke
In production you keep info and up, and stay quiet below it.
Then give every line the same handful of fields, so any one of them can pull the whole story back out. A correlation id is the important one: a value generated when a request arrives and stamped on every line, error and trace that request produces. Carry the user id and the running version beside it and you can filter by any of the three.
One id, and everything that happened in that moment comes back together, here and in every other tool you point it at.
Then use structured logging: emit each log as data, a level plus named fields, instead of gluing a sentence together. A sentence you can only skim by eye. Structured lines you can search, filter, and count across millions of them.
14.1.3Log who did the dangerous things
One class of event you log even when nothing is broken: the privileged and the irreversible. Who logged in and from where, who failed to, who changed a role, who exported or deleted data, who moved money. That audit trail is how you notice a break-in yourself, instead of hearing about it from a stranger weeks later.
Two of those deserve to reach you, through the alerting the rest of this part sets up: a spike in failed logins, and any admin action at all. The rule above still holds on every one of these lines, an id and an event name, never the token or the password that came with it.
14.1.4Logs feed observability
Clean, structured logs are the raw material for observability: asking any question of your running system and getting an answer from what it already emits. Why is this slow? How often does this fail? What did this one user hit?
Random print strings answer none of that. Structured events you can search, count, and alert on, and that is the base every metric, alert, and timeline in the rest of this part sits on.
Set that foundation now, one structured logger your whole app writes through:
Do this now: paste the prompt, replace your print statements with one structured logger, and write your next log line with a level and named fields, no secrets in it.