I'm basing my response on the excellent response of Robert Kozak, even though I don't quite use my logging the same way
I use five types of log statements:
- DEBUG
- INFO
- WARNING
- ERROR
- FATAL
DEBUG statements are statements which are useful when you are still writing an application, and when you need a complete understanding of what/where your execution flow is. You can use DEBUG statements to measure the queue in front of a lock, or check usernames of users logging in, or even the parameters for a certain SQL call that's been troubling.
DEBUG is for statements which are not generally needed to be known.
INFO should be used whenever there is information which will be very useful if something goes wrong, but does not indicate that anything has gone wrong. If you use too many INFO statements, your logs will become bloated and unuseful, so be careful.
Use INFO for any critical information which you will need on error, and it is no where near where the error will be throw.
Use WARN level if you have detected a recoverable, but still unexpected (at least a little expected, because you caught it). It indicates that your application MAY be in an unworkable state, but that you believe you can recover/continue on the current execution path.
ERROR warnings are for whenever you catch an unexpected exception. If you are recovering/retrying the current method, I'd suggest using WARN. If you are canceling/bailing out, use the ERROR. Even if your program can continue, ERROR means that you were attempting to do something and were rejected, and are therefore moving on to other things.
FATAL is for use when you catch something at a level far beneath where it was thrown, and you essentially have no idea what's going on. It means you are not even attempting to continue execution, you are simply going to log every possible bit of information at your disposal and then try to exit gracefully.
FATAL errors are infrequently used because generally if you catch an error, you have enough information to try and continue execution. But in the scenarios where corruption might occur if you try and continue, log a FATAL error, and then run away.
As for where you're logging to. I usually like to log to a 'shared' folder on my app servers (be careful about permissioning so that they are not public) so that the logs are very easily accessible and they are always my first step for debugging.
If possible, set it up so that any errors that are WARNING, ERROR, or FATAL are sent out by email so that you'll have 'advanced' warning.
Cheers
slf4j wrappers
Most of Scala's logging libraries have been some wrappers around a Java logging framework (slf4j, log4j etc), but as of March 2015, the surviving log libraries are all slf4j. These log libraries provide some sort of log
object to which you can call info(...)
, debug(...)
, etc. I'm not a big fan of slf4j, but it now seems to be the predominant logging framework. Here's the description of SLF4J:
The Simple Logging Facade for Java or (SLF4J) serves as a simple facade or abstraction for various logging frameworks, e.g. java.util.logging, log4j and logback, allowing the end user to plug in the desired logging framework at deployment time.
The ability to change underlying log library at deployment time brings in unique characteristic to the entire slf4j family of loggers, which you need to be aware of:
- classpath as configuration approach. The way slf4j knows which underlying logging library you are using is by loading a class by some name. I've had issues in which slf4j not recognizing my logger when classloader was customized.
- Because the simple facade tries to be the common denominator, it's limited only to actual log calls. In other words, the configuration cannot be done via the code.
In a large project, it could actually be convenient to be able to control the logging behavior of transitive dependencies if everyone used slf4j.
Scala Logging
Scala Logging is written by Heiko Seeberger as a successor to his slf4s. It uses macro to expand calls into if expression to avoid potentially expensive log call.
Scala Logging is a convenient and performant logging library wrapping logging libraries like SLF4J and potentially others.
Historical loggers
- Logula, a Log4J wrapper written by Coda Hale. Used to like this one, but now it's abandoned.
- configgy, a java.util.logging wrapper that used to be popular in the earlier days of Scala. Now abandoned.
Best Answer
I consider fatal errors to be when your application can't do any more useful work. Non-fatal errors are when there's a problem but your application can still continue to function, even at a reduced level of functionality or performance.
Examples of fatal errors include:
Non-fatal errors would include: