Debugging: to System.out.println() or to not System.out.println() - java

That is my question. More specifically, I'm trying to get used to Eclipse's debugger and I'd like to know if printing to console is still done in some cases or if it's considered a bad practise that should be entirely avoided. Also, what can be considered as good approach(es) to debugging overall?

Use System.err.println() instead.
Why?
System.out.println() is often redirected to a file or another output, while this is pretty much always printed on the console. It's easier for debugging and also the right way to do it.
Edit (warning: subjective):
Since you asked about whether System.out.println should be entirely avoided: I don't believe in anything that you must always avoid, be it using goto's, crashing your computer with a BSOD, or whatever. Sometimes you just need a quick-and-dirty way to get small things done fast, and it just plain isn't worth the 1 hour you'll spend on it to try to do things the "right" way, instead of a 5-minute fix, no matter how good the "good" way is. Use your judgment when deciding if something should be used or not, but never set rules for yourself like "I'll never use goto!". :)
Edit 2 (example):
Let's say you're debugging a crashing driver and you suspect that an if statement that shouldn't be execute is being executed. Instead of spending three hours finding out how to use ZwRaiseHardError to display a message box, just call KeBugCheck inside the if and crash the darned system. Sure, you'll reboot, but unless your reboot takes hours, you just saved yourself that much time.

The best choice would be a logging library (of course, this adds an extra dependency to your project). Check out commons-logging, for instance.
The main advantage is that you can write your debug messages in the DEBUG level and when you deploy your code, you'll just configure the logger to skip those messages (instead of searching for all occurrences of System.out.println in your code).
One other great advantage is that loggers usually can be configured to write anywhere (even send email messages or SMS) also without touching your code.

Minor point: if your program actually outputs something useful to the console via System.out, you may want to instead print the debugging info to System.err
You should generally strive to have as much debugging as possible (ideally using some standard logger like log4j). This both eases debugging when you're actually developing the program AND allows for much easier debugging of already-released code in production. The benefit is that your code remains unchanged and you don't need to ADD debugf prints, yet by default the logging config can turn off the logging until it's actually needed (or at least turn down the level of logs)
As far as general simple "throw printlns at the wall" debugging, it can sometimes be one of the fastest ways to debug, though it should by no means be the only/main one.
Why can it be useful? Among other reasons, because running a Java program in a debugger may be much slower than outside of it; or because your bug manifests in an environment/situation that can't be easily replicated in your Eclipse debugger.

If the debugging print lines are not going to stay in the code after you've fixed your bug, then do whatever is easiest for you. Lambert's advice of using System.err.println() is a good idea since you can differentiate it from other output that your program may produce. If the debugging print lines are going to stay in your code, then I would advise on using a logging framework like log4j. This way you can dial up or down the level of output based on whether you're trying to debug something or just running in production. Be sure to output things at the right level when using log4j. Don't just log everything at INFO.

I use System.out.println for my debugging in case i have a problem or to inform me that methods have started to make sure everything has worked properly but when I publish the program I always remove it because it slows down the program.

Related

Is it possible to have Log4J 2 keep everything in memory and output on demand?

Ok, so the problem I'd like to solve is having tests in CI being overly verbose. Now I could turn down the logging in general, but that would hurt when you actually need to debug one. What I think I'd like to do is accumulate all the logs in memory, and then set the actual level to emit when the suite has errored or succeeded, then emit/append the logs that need to be. Bonus points if I could somehow do this by inspecting the exception stack when it fails. Is this possible?
possible duplicate really it's the same question, but in 6 years we've gotten log4j2 and junit5, so I guess I'm wondering if this has changed.
Nope, that watcher is still it (write your own, in other words), because your request is still bizarre. Time isn't going to change this.
Logging frameworks love to write ASAP, not later. After all, maybe the VM is about to hard-crash and that is the absolute worst time of all to cache some writes - the very log statements that provide insights into the hard crash are now lost to the ether.
Normally, the solution is to use tools that read the log files and process them in some fashion - usually, by chucking most of the lines out as you copy and zip them up for the ages, keeping the full dump (and uncompressed) only for the most recent few logs.
Key principle there being: A separate process (may not even be written in java) that does this later.
Can you configure your CI system to do this? That sounds like the right approach: Log at a pretty verbose level, and have the CI system strip the logs down to a much more strict level after the tests ran if the tests were successful.
For JUnit 4 the library System Rules allows you to suppress output that is written to the console for successful tests. You have to add the rules SystemErrRule and SystemOutRule to your test.
#Rule
public final SystemErrRule muteSystemErr
= new SystemErrRule().muteForSuccessfulTests();
#Rule
public final SystemOutRule muteSystemOut
= new SystemOutRule().muteForSuccessfulTests();
Disclaimer: I'm the author of System Rules.

Java Log Coverage tool

Are there any tools or strategies for generating a "Log coverage" report on (Java, log4j)? Like code coverage, but ensuring that there aren't large methods, classes, or packages which don't log anything.
When coding web services, me team doesn't write many log statements. When debugging a real time problem with running, production code, we always wish we had. Inevitably we try to reproduce the bug in our test environment with either a debugger attached or additional log statements added, which can be very difficult depending on the structures and inter-operation involved.
Does anyone use this as a code-quality metric?
Code coverage takes special instrumentation because you're trying to find out whether a piece of production code is exercised by any test. What you're asking is a little more vague and could be either much easier ("is any logging done for this large class?") or much harder to the point of impossible ("did we log the method that's going to break in production?").
For the first question, you could whip up a shell script pretty quickly to do the job. Here's a skeleton in Perl, for example. Here, I assume that we're using SLF4J and that seeing the import of "LoggerFactory" is enough evidence to assume there's a logger.
while ($filename = shift) {
open my $in, "<$filename";
my $loc = 0;
my $log = "NO LOGGER";
while (<$in>) {
$loc++;
if (m/import org.slf4j.LoggerFactory/) {
$log = "has logger";
}
}
print "$filename : $loc LOC $log\n";
$total{$log} += $loc;
}
print "\n\nTOTAL LOGGED: $total{'has logger'}\nTOTAL UNLOGGED: $total{'NO LOGGER'}\n";
and I can run this from my shell to run over all the Java files in a little project with
$ find . -name \*.java -exec perl haslog.pm {} \+
This only works for small-sized projects, and it's fairly brittle but it wouldn't be a ton of work to make a more robust version of this.
Lots of logs can be noise and in my experience I always found tracing through logs painful. Having said that if the logs are managed well you can get good diagnostics/reporting. One of the reason for the code not being tested properly is because of having lots of logs in production code. What developers tend to do is add a log statement when they are developing to check the code works, consequently it encourages not writing a test with the right assertion. What you need is lots of little classes that are well tested composed together. The assertion should exactly tell you why the test is failing.
Lets say in your code path you are expecting something to happen which is its main responsibility (e.g Created a DB entry to register user/or someone logging in), when I say its main responsibility I am not talking about a side effect that happens in your code path. If you have an error condition in the main code path the exception should be thrown all the way up the stack were you can log and convert that to a user friendly message. RuntimeExceptions are a good here because you dont want to be catching these exceptions until its all the way up to the view layer. Side effects can be logged as well because they are like info/warnings.

Print source code flow as program is executed

is there a way to print each line of source when the program executes without having to insert System.out.println after each line?
Use a debugger. Debuggers provide a number of useful tools to step through your program. Check your IDE, it probably has one.
First a question: Why would you need that? You might use a debugger if it's just for debugging.
If it is for logging purposes, logging each line would be overkill.
Second a suggestion: you might use AOP to log each method call (assignments etc. could not be intercepted), but that might require a lot of work (incorporate AOP into your build process etc.) and might not be worth the hassle.
Eclipse Test & Performance Tools Platform Project has a way to show you a sequence diagram of the program execution:
http://www.eclipse.org/tptp/home/documents/tutorials/profilingtool/profilingexample_32.html
For printing as text, AOP is nice but complicated, debug statements are easiest but most invasive.
I'm pretty sure Eclipse lets you step through the program line by line, the link is unfortunately down for maintenance but maybe check back on it later: http://help.eclipse.org/indigo/topic/org.eclipse.jdt.doc.user/tasks/task-stepping.htm

General debugging log practices

Due to recent events, i am trying to figure out how much debugging logs i should use for code in general.
What i have been doing is using debugging logs pretty sparingly, and just in cases where i wanted some extra information or what have you. This made sense to me, as it seems like you shouldn't log every little thing your code does, as that could make flood you with so much information that it would be easier to miss something that was actually important (or go crazy from digging through and verifying logs).
On the other hand, i present an example: I just started using logback/slf4j for my java project, and to test that i had the .xlm file set up correctly i added a debugging log statement to the end of a method that initializes gui components. Normally i would have never put a log statement there, because it is pretty obvious if your gui components don't initialize correctly when you run the program. However this time i ran the program, and low and behold the logs showed that the gui components were being initialized twice, even though only one set of them were being displayed. A decent sized bug, but something i likely wouldn't have caught without without those debugging statements.
So my question: Is there any "best practices" out there when it comes to debugging logs? I have seen many best practice questions when it comes to info logs, exceptions, errors, etc, but haven't found much out there in regards to debugging logs.
Thanks :)
Some thoughts:
Don't just log what's happening, but take care to log the available parameters/method arguments etc. It's easy to overlook this.
It's easy to disable debug logging via configuration rather than logging in after the fact.
Don't worry about logging overhead until it really becomes an issue.
You can automate some logging (entry/exit of methods) by using an AOP framework (Spring / AspectJ etc.)
I don't think there are any "best practices" in deciding what / how much to log. It is one of those catch-22 situations. If you need to look at the logs, there is "never" enough information there, but if you don't then "all" logging is just code clutter and an unnecessary runtime overhead. You need to make a separate judgement about where to draw the line for each application.
One point to bear in mind though. If you and your customers are able to hack the code to add temporary debugging statements, then you don't need as much permanent logging code in place. But if you don't have the option of hacking on the (almost) production code to debug things, then you need a certain level of logging code in place, just in case ...

How to identify which lines of code participated in a specific execution of a Java program?

Suppose that I have a Java program within an IDE (Eclipse in this case).
Suppose now that I execute the program and at some point terminate it or it ends naturally.
Is there a convenient way to determine which lines executed at least once and which ones did not (e.g., exception handling or conditions that weren't reached?)
A manual way to collect this information would be to constantly step with the debugging and maintain a set of lines where we have passed at least once. However, is there some tool or profiler that already does that?
Edit: Just for clarification: I need to be able to access this information programmatically and not necessarily from a JUnit test.
eclemma would be a good start: a code coverage tool would allow a coverage session to record the information you are looking for.
(source: eclemma.org)
What you're asking about is called "coverage". There are several tools that measure that, some of which integrate into Eclipse. I've used jcoverage and it works (I believe it has a free trial period, after which you'd have to buy it). I've not used it, but you might also try Coverlipse.
If I understand the question correctly you want more than the standard stacktrace data but you don't want to manually instrument your code with, say, log4j debug statements.
The only thing I can think of is to add some sort of bytecode tracing. Refer to Instrumenting Java bytecode. The article references Cobertura which I haven't used but sounds like what you need...

Categories

Resources