I’ve plowed thru gigabytes of log files these last few days trying to identify a problem we have been having with our app. That made me start thinking of what a log and awesome log output should contain.
I came up with these points, some trivial, some are perhaps not.
Use a logging framework I’ve always used log4Net but what ever works for you.
Use the log levels correctly (I’m using the log4Net levels). This makes it possible to hide output you are not interested in. Debug is for trace messages – intended for a developer or administrators. Info is for positive events that successful – Eg “Created user ‘Anders’” Warning is for negative events that may occur but does not prevent the application from function correctly. Eg “User ‘Anders’ is already logged on.’ Error – Is for negative events which prevented a action from being performed. “Unable to create new user ’Anders’. User already created.” Fatal – When unhandled exception occur and your app will have to roll over and die.
Name that thread
If your application more than one thread (which I hope it does these days) remember to set the Name property when you spawn new threads. It makes it easier to follow a flow if many threads are running in parallel.
Include meaningful data in your output. For example, “User changed favorite color” does tell you what the new or old color is. “User changed favorite color to blue, old was yellow”. Although it might not seem useful now it probably is when the user gets a yellow promotion t-shirt sent home to his house. In this case we know that the user had the color updated correctly and that the problem is downstream.
Differentiate between instances If you have multiple instance of a object. It is crucial to know which one is doing the logging. “User changed favorite color” doesn’t tell you which user object now has a now favorite color. Better is ‘”User ‘Anders’ changed favorite color.”. Include details about the endpoint when logging about communication ”Unable to contact server” doesn’t tell you much if you are talking to 10 different servers. “Unable to create user on remote server ‘192.168.1.1’ is better.
Don’t log sensitive data What’s sensitive data is up to you but passwords are a big no no.
Use common id in the output to create a flow. If several operations are performed as a result of a single user action it can be a good idea to include a common ID when logging the operations. This is very useful if the operations are not executed in sequence by the same thread. In addition, if something goes wrong then it might be a good idea to show this to the user so it can be provided to support for investigation.