Verbosity

The project is creeping up on 7,000 lines of code now and there are a few things that are starting to get away from me. I need to spend some time deciding on a few details before I get too far along. The one that I want to discuss is the verbosity levels and the message logging facility. The libdax library has three functions, dax_debug(), dax_error() and dax_fatal() that are used to log messages. I know it's not very *nix-ish, not using syslog for this. In fact there is nothing stopping any of this from being a wrapper on top of syslog calls. That is probably the way that it will go. It is the way that it started, but I got tired of constantly having to open log files while I trying to debug code, so I changed it to vprintf() statements. My intention is to centralize the message logs so that it could go to the terminal, syslog, a database or a user defined module. The way the code stands right now those decisions can be made later because I don't think that function calls will change.

The dax_error() and dax_fatal() function are identical except that dax_fatal() sends a SIGQUIT signal to the calling process. A good module will arrange to catch that signal and exit gracefully. They are set up to log to STDERR right now. dax_debug() takes one extra argument, verbosity. At any point during the modules execution it can set the verbosity with dax_set_verbosity(). Then when the dax_debug() function is called a decision can be made as to whether to actually log that message or not. There are also a couple of macros defined, DAX_DEBUG() and DAX_DEBUG2() which are just conditionally compiled dax_debug() calls with one or two string arguments respectively. (All of these functions take variable numbers of arguments just like printf()). The OpenDAX core program doesn't link with the library so it has it's own little set of functions (xlog(), xerror() and xfatal()).

It seems that I should spend some time deciding on what types of messages should be included with each verbosity level. Right now the verbosity level can be set anywhere from 0 to 10. I'm not convinced that I need that many levels. I need to start trying to enumerate what each level should be before I decide on a number. Here is a first draft of what I might use...

  • Fatal - Called when the error that has happened will keep the module from running properly and will need to shut it down.
  • Error - Serious problems with the module that will decrease its functionality but shouldn't keep it from running at some diminished capacity.
  • Level 0 - Minor Errors, errors that don't necessarily decrease the module's capacity but may either be indicative of other problems or failures that can be resolved at runtime (port failures, communication errors, etc).
  • Level 1 - Logging of major program milestones
    (startup, shutdown, thread launches etc.)
  • Level 2 - User program errors, or configuration file problems.
  • Level 3 - Configuration information.
  • Level 4 - Obscure program milestones. (function entry/exit, message receptions, etc.)
  • Level 5 - Truly obscure program debugging watch points, this level would purely for development only.
  • Level 6 - Developer debugging messages.

The highest levels would only be allowed when DEBUG is defined. This is generally when the --enable-debug configuration parameter is passed to the autoconf script. The level would be reserved for the DAX_DEBUG() macros that are conditionally compiled. This gives the developer a way to add truly verbose debugging messages in places where it would really be a performance hit to call the dax_debug() function only to have it exiting constantly because the verbosity level wasn't met.

I will probably refine this list over time and I'm sure that I'll find exceptions to the rules and possibly rearrange them but I need to start somewhere. I'd also like to try and keep this as uniform across the modules as I can. I still need to write a coding standards document too and this will be some of the information that it'll contain. I may also rename dax_debug() to dax_log().