Saturday, 1 June 2013

Logger fine-tuning - when to generate logging code

While adding log to my ssh code, I figured out that I can fine-tune logging even further.

I have a few TRACE entries, a lot of DEBUG entries, and the odd INFORMATION/WARNING. Since this code can be reused by several applications, I don't want to fill those apps' logs on a day-to-day basis, only when necessary (e.g., gathering debug info, while investigating an issue).

This can be neatly taken care of with logger names and logger levels. Right now, I'm only fully exploring the logger levels. In order to better explore the logger names, I need get more usage out of this code, to discern what are its patterns and its logical divisions. Of course, I may reach the conclusion this code is, from a functional point of view, too basic to have any division, and I'll just use a "*.ssh" logger, whereas code with more complex functionality could conceivably have a more complex logger tree.

As a principle, I have no problem with TRACE and DEBUG logging statements in production code. However, I also have no problems with removing it, when I see evidence that it's the best course of action. Still, as least as far as DEBUG goes, I can think of not-quite-so-few cases where activating DEBUG on a logger took me from "no clue" to "A-ha!". I'd have a much harder case justifying TRACE, but DEBUG has proved valuable in the past.

So, going back to the fine-tuning I mentioned. I've set up a whole lot of macros as the easiest way to use the logger. And it dawned on me I could use this to create a more selective logging code exclusion, without adding more complexity to the classes themselves.

Suppose I want to build an app with no TRACE logging at all. That's easy, I just change the macros, based on a #define. Now, suppose I want to do the same for DEBUG, but I really, really think that, say, 5% of those statements might be useful in production, should things go south. The answer is also simple, but it took me some more time to get there - create another set of DEBUG macros (yes, this is the not-so-good part), and then create #defines to either remove all the DEBUG code or just remove the DEBUG code that is not considered useful for production.

Why do I think this is a good idea? Because this gives choice to the user without adding any complexity to the default use case. The typical logging usage remains unaffected, and you can ignore all the other options, until the day you need them; if that day comes, it's there for you.

And, as I said in my last post, I believe user choice is a Good Thing(TM).

No comments:

Post a Comment