tags:

views:

126

answers:

3

In a large application logging is essential, but when many developers work on the code, the logs can become chaotic. One might write:

log.info("Loaded " + rowCount + " recodrs from the database.");

Another might do something like:

log.debug("Records read={}", rowCount);

A third developer might think this is the proper way:

log.trace("Record(s) read: " + NumberFormat.getInstance().format(rowCount)
          + ", values: " + values);

This will result in logs that are hard to read, and much harder to parse.

What guidance can you give developers to produce logs that have a chance to be consistent, and actually be usable by other people? Will a policy about logging do any good? And if so, what should it include? Should there be an API (above the logging framework's own) to enforce this policy?

I'm also curious about how to make the code look alike, but the more important question is about the actual output.

+1  A: 

You can use AOP(AspectJ is the best) to log what is passed into the methods. you could even do pointcut to just methods, so it wont be too much logging. You could write method annotation like @Loggable and set pointcut on it, so every method with those params get logged.

I think aspects are the best way to go here.

example

01
Logging is THE example where Aspect Oriented Programming shines! Define one aspect and you can weave it easily in all your code, and leave it all out when you ship the product.
NomeN
+2  A: 

Standardize the messages, either via API or string formats the developers reference when building the log statements. They shouldn't be typing text like that into the program, even for logging, for exactly the reasons you call out. Naturally, this means you need a policy as well, and reviews to ensure that the policy is respected.

T.J. Crowder
+3  A: 

IMHO logging guidelines on what constitutes a good log statement level are rare even among large frameworks and products, primarily due more important guidelines involving

  • Log verbosity - more verbose statements should appear as debug statements, and calls to log.debug() should be wrapped by with a call to check whether debug is enabled. Developers often need to get the distinction between FATAL, ERROR, INFO, DEBUG and TRACE correct - not all exceptions are fatal, and not all messages are informative.
  • Use of TRACE or equivalent - this should be reserved for execution flow. Ideally, no other log statements are required to indicate control flow.
  • DEBUG vs INFO - DEBUG statements are often meant for developers and support personnel; INFO is often for users and administrators.
  • override toString() - it is helpful for logging the state of complex objects

That said, I follow a few general thumb rules at the lowest level:

  • Log data as is, without formatting. That way, in case of an error, I know what was the data that caused the problem, instead of doubting the logger, the formatter and the application at the same time.
  • Avoid creating too many String objects unless you are running with DEBUG or TRACE switched on. In short, avoid concatenating too many strings. Even if log4j eventually checks if DEBUG is enabled or not, the String objects have been created, and that's why log call wrapping is important. slf4j helps avoids this via the use of parameterized messages.
Vineet Reynolds
Regarding your last point, really recommend you to use slf4j (Simple Log Facade 4 Java) which helps take care of that and also allowing string interpolation in your logging message. Since slf4j is just a facade, you can easily switch logging framework implementation that you use.
DJ
@DJ, agree with your point on slf4j. I wanted to avoid being too presumptuous about the logging framework, since only the second code snippet in the question indicates the use of slf4j.
Vineet Reynolds