Logging module specs

From Inforail
Jump to: navigation, search

Overview

Post-mortem debugging is useful for cases in which an error occurred after the product was released into the wild. In such circumstances you don't always have the option to visit the end-user and debug the problem on site (it could be too expensive, too time-consuming, they may not have the instruments you need, etc).

The solution is to provide a logging feature to your program, which will dump some useful information to a log - this information will help you understand the state in which the program was before the crash. Once you understand the problem, you can think about a solution.


Objectives

Design a module that provides logging functionality to a program.

Requirements

Your module must be easy to integrate into an existing application written in the same language. Everyone's definition of "easy to integrate" is different, therefore we will rely on the following:

  • The logger will be added to the program you chose to write in one of your earlier assignments
  • Adding the logger is done by creating an object of a class, or by calling a function from a file (naturally, in some languages the approach can be different)


  • The interface of your module must have the following function (you can add other ones if you think they are useful; in fact, you will have to add more functions to implement some of the suggested features):
    • WriteLog - calling this function from any place in your code, with specific parameters, will add a new entry to the log, dumping at least the following information (when relevant):
      • name of the function being executed (ex: "MyFunc")
      • location inside the function (i.e. where in the body of myFunc are we? ex: "BeforeMyOtherFunc" or "AfterCreateFile")
      • values of its input parameters
      • returned result
  • Implement the following minimal subset of features from the Things to think about list
    • System report
    • Verbosity
    • Timestamps




Example (before attaching the logger):

def getBounds(ip, mask, number):
   ipLo=[]
   ipHi=[]  
   ipL=ip.split(".", 4)
   maskL=mask.split(".", 4)  
   for i in range(4):
       ipLo.append((string.atoi(ipL[i])) & (string.atoi(maskL[i])))     
   for i in range(4):
       ipHi.append((string.atoi(ipL[i])) | (255-(string.atoi(maskL[i]))))
   return (ipLo, ipHi)


Example (after attaching the logger):

def getBounds(ip, mask, number):
   WriteLog("GetBounds","1\t\t\t\t" ip, mask, number)
   ipLo=[]
   ipHi=[]  
   ipL=ip.split(".", 4)
   number=number+45
   WriteLog("GetBounds","1a before some function\t\t", number)
   result=CallSomeFunction(number)
   WriteLog("GetBounds","1a after function\t\t", result)
   maskL=mask.split(".", 4)  
   WriteLog("GetBounds","2 after mask split\t\t", maskL)
   for i in range(4):
       ipLo.append((string.atoi(ipL[i])) & (string.atoi(maskL[i])))     
   for i in range(4):
       ipHi.append((string.atoi(ipL[i])) | (255-(string.atoi(maskL[i]))))
   WriteLog("GetBounds","3 before return\t\t", ipLo, ipHi)
   return (ipLo, ipHi)

Example (what's inside the log):

12:45.34 GetBounds 1                       127.0.0.1 255.255.255.0 45
12:45.35 GetBounds 1a before some function 90
12:45.36 GetBounds 1a after some function  True
12:45.44 GetBounds 2 after mask split      255,255,255,0
12:46.00 GetBounds 3 before return         1,254

Things to think about

In an ideal world, these would be the requirements for your logging system. Note that most of the examples are for the Windows platform, you should take into account the specifics of your target platform.

  • Type - the log could go into a file, a database, or a special storage mechanism provided by the OS (ex: Event log)
  • Name - how the log file is named. It is a good idea to have a naming scheme if the filename is not constant, such that your logs can be easily identified
  • Location - where the log files are stored; you can go for typical places, but note that some choices are not a good idea:
    • C: - the root directory is not writable by default on Vista and newer systems
    • \Program Files\ProgramDir - same as the root directory
    • \Desktop - it is already too messy
    • \Documents and settings\username\Company name\Program name - good choice, but tough to remember and difficult to tell people where to look
  • Enable criterion - how to know whether the logging mode has to be enabled or not? There are various ways, ex:
    • the presence of a file with a specific name in a specific location
    • a checkbox in the GUI (but what if the program crashes before the UI is drawn?)
    • a command line argument
    • you can have a debug build for which logging is always enabled (not recommended, because your end users will be running the non-debug version, won't they?)
  • Privacy - if the log contains sensitive information (ex: password, addresses, email addresses, names) you should make sure that information is handled properly. You can mask the passwords with asterisks, or simply warn the users that logs will contain sensitive data.
  • Timestamps - sometimes it is useful to indicate the system time in each line of the log, this will allow you to reveal some details about the performance of your system. For high precision cases, the timestamp must not be limited to "hours, minutes and seconds".
  • Concurrency - if your application is multi-threaded, or if several processes will write to the same log file, you will need to use a synchronization mechanism provided by your OS. You may want to indicate the ID of the process or the thread in each line.
  • Verbosity - sometimes you need a verbose log to understand the cause of a problem; other times a superficial log is sufficient. A good logging mechanism allows you to set different levels of verbosity.
  • Clearing - when should the log file be cleared?
    • after each restart
    • when it reaches a size of N MB
    • after N days
    • after N restart cycles
  • System report - sometimes you need to know some details about the system on which the software is running, in order to be able to simulate the problem on your test systems. Instead of asking the end users these questions, you should obtain the information automatically (avoiding the risk of getting incorrect answers from people). Usually you need to know details such as these:
    • version of the OS (mention service packs, hotfixes, etc)
    • version of your program
    • the system's regional settings
    • the system's time
    • path to your program
  • Feedback - how is the log sent to the developers?
    • automatically, via Internet (by email, or a custom protocol)
    • create an email with an attachment and start the system's default email client
    • open the directory that contains the log and highlight the file (let the user figure out by themselves how to send it over)
    • tell people which folder they should open in order to find the file
Suggestion

WriteLog should take a variable number of input parameters, like printf does.


References