views:

187

answers:

5

Is there a cleaner way for me to write debug level log statements? In some ways one could say that the string literals are basically commenting the code and providing logging in one line and that it is already very clean. But after I add debug level log statements, I find the code much less easier to read up and down. Take this example (I may update to a real example if I get back to my home PC):

int i = 0;
logger.debug("Setting i to 0,"); //Just an example, would show something more complex
i++;

InputStream is = socket.getInputStream();
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());

IOUtils.write(request, dos);
logger.debug("request written to output");

while (!is.read(buffer))
    logger.debug("Reading into buffer");

logger.debug("Data read completely from socket");

CustomObject.doStuff(buffer);
logger.debug("Stuff has been done to buffer");
+1  A: 

If you want very fine grained debug instructions I am not sure you can separate the actual code from the debug code.

If you want it at a higher level, maybe adding your logging using AOP could help make things easier to read, maybe use a proxy object?

But if you have debug instructions as fine grained as in the example you provided, IMHO you could gain more by replacing the loggers with unit tests. Don't write in a log that something happened, test that it did.

dpb
I see... I suppose in my case, where I am using network I/O, I want to record everything that happens since odd things can/do happen that the unit test case won't be able to verify as well. I suppose unit testing something like a crawler/scrapper can be difficult since what I am testing against (the internet) is always changing.
Zombies
If that is the case, I'm afraid that you might have to keep the debug statements in your code
dpb
+1  A: 

You could try using aspects, although these have the limitation that you can only put log statements "around" method calls, i.e. before entering and/or after leaving a specific method.

For more detailed logging, I am afraid there is no other way than hand-coded log messages.

I typically strive to remove the not-so-much-needed debug log statements from the code once I made sure that it works the way it should (for which unit tests are a must).

Péter Török
It is very hard to do much more than "trigger when this happens" logging with AOP (to my understanding). I do not think that is quite enough here.
Thorbjørn Ravn Andersen
@Thorbjørn Ravn Andersen - That's what I was trying to communicate here too... if it is unclear, would you be so kind to point to the unclear bits?
Péter Török
+2  A: 

Ask yourself if I run this in a different machine/country/planet, and things go wrong and all I have is only a log file what information do I need to know what has gone wrong ?

Use debug logs in a for loop, or a while loop sparingly. For example, if you are reading 1000 records from a file, performing an op for each record. You could record before the for loop that "file exists and is readable and is going to read 1000 records" and print status after the process is done. If it is say 1000000 records then you could print something every say 100 or 1000 iterations

In your code except for the logger for setting i to 0 everything else sorta makes sense to me. Also care to use log.isDebugEnabled() if your string in the logger statmeent is hard to compute..

ex:

if(log.isDebugEnabled) {
   logger.debug("Here " + obj.aMethodCallThatTakes5MinsToEvaluateToString());
}

UPDATE 1: SLF4J solves only half the problem.

if(slfLog.isDebugEnabled) {
   slfLog.debug(obj.getObjectThatTakes5Mins());
}

Yes the toString is prevented but if you are logging an actual object which is result of some computation you are not prevented.

Calm Storm
the slf4j {}-construct avoids the log.isDebugEnabled by passing the object and only needing toString() when the actual message needs to be created, not always.
Thorbjørn Ravn Andersen
A: 

You will not be able to do much if you dislike the log statements. The information needs to be there somehow.

What you CAN do, is strongly considering what NEEDS to be there. You are basically writing for the log file reader who per definition does not know about how your program works, so the information needs to be concise and correct. Personally I very frequently add the method name to the log statement.

Also note that slf4j allows you to use the {}-syntax which helps somewhat

 log.debug("main() date={}, args={}", new java.util.Date(), args);

Also note that having unit tests, allow you to move much stuff to there simply because you know that THAT works.

Thorbjørn Ravn Andersen
A: 

Why not simply debug the program with a debugger if things goes wrong? Why do you need to persistently put those log messages there?

Enselic
It is not always possible to attach debugger for various reasons especially in live/production instances and usually that is where things will go wrong :)
Calm Storm
Also, the issue may not be easily reproducable, or at all without understanding what happened. In that case ALL you have is the log.
Thorbjørn Ravn Andersen