I work as a Java Developer and two things that I think are not given the due consideration by many developers(me included) are error handling and logging. What makes it important is that there are no fast rules on the two though we do use thumb rules. In this post I will put forth my thoughts on logging.
Many times we hear people saying “Log everything” and developers to be on the “safe” side, put lots of logging information. While it certainly helps in debugging, there are disadvantages:
1. Logs involve I/O: This is expensive and causes overhead on your system and can slow down your program.
2. Too many logs are counterproductive: The main purpose of having logs is that, once the program goes into production, you cannot “debug” it in case of issues like you did in “development” systems. Hence application logs help you by giving the direction taken by the program execution.
If the logs are too bulky, then looking for this direction can be a nightmare. Needle, haystack anyone..
3. Logs occupy space: Logs are physical files and occupy space. Based on your requirements and strategy, you may want to retain logs for certain period of time. Unnecessarily heavy logs eat up on disk space and can cause issues within a short span of time.
So what is a good logging strategy?
Whatever one may say about excessive logging, it is true that we do need logging so that in case of issues we are able to fix it quickly. We do need to strike a balance between logging and its performance.
If you use an utility like Log4J for logging, you can configure it to log only those statements that you need. Hence your code can have all the logger statements at any granularity, but your log files will be light. If you really need to go fine grain, you just change the configuration.
In this case, the trick really is to decide which statement needs what level of logging. There can only be pointers to these and no hard rules
1. Trace: The lowest level: Log every state of object. Frankly , I am yet to use this in my code till now.
2. Debug: The most used one. Use this to log inputs got/ values returned in a method, or intermediate states after some state changes.
3. Info: Information about a business decision taken. X is this and Y is this so we are doing that
4. Warn: You see some business logic not working as expected but not a cause for alarm. Can be used to highlight corner cases .
5. Error: There has been a business logic failure. The sequence of operations is not maintained. The workflow cannot be carried on without fixing these .. mostly inputs from users.
6. Fatal: System error unable to proceed with the workflow at all. Possibly database connection reset, IO operation failure etc.
Keep in mind the following when logging:
1. When a logger statement is encountered, the statement is written and then the logger checks for the logging level . Say the statement is debug but the level is fatal, the object is created and then discarded. In log4j logging, always use logger.isDebugEnabled(), logger.isInfoEnabled etc
2. Loggers are not immune from NullPointerException !!: Quite a few times had this situation when a logger was causing a failure . So try to log direct values of objects than doing getters .
Will write about my experience in Error handling in a later post