General debugging log practices - java

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 ...

Related

Exception Standard for different logging levels

Which is more suitable out of these two exception object (e) or e.getMessage() for log.info() and log.error() or log.debug().
What should be followed/rule of thumb for different logging levels.
It really depends on the reason of the exception being thrown. I would add here WARN level consideration as well. If this is an unexpected error that should not happen, meaning that this is something wrong with codebase you should definitely log the whole exception object, especially to get the stacktrace that allow developer to find and potentially fix issue faster. Therefore such situation should be logger on ERROR level if this is something wrong with the system, or WARN if this is something wrong with client's data.
INFO level should really not contain exception details, it should keep information easy to read by non-developers(for example testers) and describe the most important parts of the data processing flow.
I think it is up to you to put exception in DEBUG level but I would still recommend not to do it just to keep things clearer OR use e.getMessage() to describe it.
P.S. In general, I would redirect this question to this page since it is a general SE question but since you asked about using particular Java feature I wanted to keep things in the right place.
Don't try to create a fixed rule about including or not including the stacktrace depending on the log level. Instead, when creating a log entry, ask yourself:
Who will read that entry? A user, a system administrator, or a developer?
What information will be useful to that reader for understanding the situation? It's better to add too much information than to omit important parts.
If the entry is to be read by a developer, is the text enough or should I include the stacktrace? Non-developers typically get confused when seeing a stacktrace, but developers very much appreciate it.
This will greatly improve the quality of your logging.
As a very rough rule of thumb, include the stacktrace whenever you log an exception. An exception means that something went wrong, which might involve analysis by a developer, who will be very unhappy if the log entry only reads "NullPointerException" without a hint where it came from.
Of the typical log levels, INFO might be the one not addressing developers (thus not asking for a stacktrace), but generally you don't want to use INFO for exceptions.

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.

Advantage in using Java Logger?

I want to log information to a file and want to know is there any advantage in using the Java Logger class versus my own personal method of logging?
I know using a logger I just add my own FileHandler to the logger. My personal method is just using a FileOutputStream.
Honestly your logger may be as good, it's pretty easy to put in log levels, filtering, etc.
The problem is when you start to put together code from 10 different groups each with their own logging. Some use System.out, some use some custom logger, some use log4j, ...
How do you parse or redirect the output? How do you filter all that output to just show your messages (For instance, filtering options in log4j won't prevent messages being sent straight to System.out).
It's a pretty big bulk change depending on which system you are moving from/to. Better just to use one very common one from the beginning and hope that it's the one everybody else on the project chooses.
The real question is: why would you bother writing your own logger when there are already existing libraries for doing that? Does your logger do something that the others don't? I kind of doubt it.
Standardization is another big issue - see Bill K's answer.
For most scenarios, a standard logging framework is the way to go. They are pretty flexible. But using your own implementation can also be a valid option, specially if we are not speaking of traditional logging (global debugging, problems, warning messages) but about specific informational meesages or accounting.
Among other factors, bear in mind that the standarization of logging allows third party libraries to cooperate. For example, if you have a standard web application using (say) Hibernate, and you have configured a standard Java logging lib, then you can not only log from your own code but also tell Hibernate to log debugging info to your log files (not necessarily the same files). That is very useful - almost a must.
If you code your own logging library with a plain FileOutputStream, you must decide -among other things- if you are going to keep the file opened, or reopen-append-close in each write - and you must take of synchronization and related issues. Nothing terribly complicated, though.
The logger gives to ability to define different levels of importance of the logged messages and the ability to use different sink for the output - the console, a file, etc.
Also it's easy to enable or disable only some type of message when using a logger - for example you don't want to see every debug message in production.
A logging framework allows you specify logging levels (e.g. log only critical messages, log only debug messages etc.). It also allows you to log to multiple destinations (e.g. to a file, to syslog etc.) and you can do this even after your application is fully built by just changing a config file and not changing any code. It can also format your logs easily depending on various parameters.
There are numerous other advantages since proper logging is a rather involved problem and these packages have been written to solve them. I think the important question, why would you not use them?
Well I would always prefer tested thing and approved by community over something which still need a lot of test. Logger allows you many things which will consume you some time to implement and to test the robustness of your solution. A big plus will be the know-how of the next person who will do something with your code, in case it will be your logger, normally it would take more time to learn how its working out, since there is much more examples and documentation for java.util.logger.
Like all others mention, there are more advantages to using a more common logging system over writing your own. To be honest, the Java util logging api is not nearly as extensive and configurable as other libraries you might find out there on the internet.
Bare in mind that rolling your own always has the disadvantage of being less tested and therefore more prone to break or skip some potentially crucial messages.
Personally I prefer using SLF4J since it allows me to plug in adapters for more commonly used logging frameworks and then let's me pick my own actual logging implementation, this solves most of the problems with different library writers preferring different logging frameworks. And if you consider yourself up for the task you could writer an implementation for SLF4J yourself ;)

What information to include at each log level? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Where/what level should logging code go?
Debug Levels
Is there a convention, a standard, or a widely used guide which will help with logging in Java? Specifically, what to include at each level (verbose, debug, ... etc.) rather than the actual mechanism of logging.
There are many guides out there of what to include at each log level, but none of them are specific; they're all vague, and this makes it hard to "follow orders".
Any tips would be appreciated.
It's subject to personal interpretation, but mine is (in order from finest to coursest):
Trace - The finest logging level. Can be used to log very specific information that is only relevant in a true debugging scenario, e.g., log every database access or every HTTP call etc.
Debug - Information to primary help you to debug your program. E.g., log every time a batching routine empties its batch or a new file is created on disk etc.
Info - General application flow, such as "Starting app", "connecting to db", "registering ...". In short, information which should help any observer understand what the application is doing in general.
Warn - Warns of errors that can be recovered. Such as failing to parse a date or using an unsafe routine. Note though that we should still try to obey the fail fast principle and not hide e.g., configuration errors using warning message, even though we a default value might be provided by the application.
Error - Denotes an often unrecoverable error. Such as failing to open a database connection.
Fatal/Critical Used to log an error the application cannot recover from, which might lead to an immediate program termination.
In the end it's up to you to define what suits you best. Personally, I run most production system with logging level of Info, where I'm mostly interested in following the applications main logic, and of course catch all warnings/errors.
Except for code cluttering, there is no such thing as too much logging. All logging which helps you reproduce or understand problems better are good logging. On a performance note, most logging systems (e.g., log4j) allows configuring which level to actually append to the physical log which is a great thing.
For what it's worth, we're using the following log levels:
DEBUG level messages give highly-detailed and/or specific information, only useful for tracking down problems.
INFORMATION messages give general information about what the system is doing. (e.g. processing file X)
WARNING messages warn the user about things which are not ideal, but should not affect the system. (e.g. configuration X missed out, using default value)
ERROR messages inform the user that something has gone wrong, but the system should be able to cope. (e.g. connection lost, but will try again)
CRITICAL messages inform the user when an un-recoverable error occurs. (i.e. I am about to abort the current task or crash)
I think the most important thing with log levels is to figure out a scheme, document it, and stick with it. Although making log level consistent between programs would be nice, as long as you've used common sense in defining your log levels, users will tolerate a certain amount of variance between programs.
Simple log what yuo think is important if you were to come back later and need to read the logs. This of course means that your Object.toStrings now need to be nice and readable and not a dump of crap thats impossible to read. This also means you need to do sensible things like quoting strings etc..

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

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.

Categories

Resources