Favor Logging Over Console Output

 class​ LaunchChecklist {
 
  List<String> checks = Arrays.asList(​"Cabin Pressure"​,
 "Communication"​,
 "Engine"​);
 
  Status prepareAscend(Commander commander) {
» System.out.println(​"Prepare ascend"​);
 for​ (String check : checks) {
 if​ (commander.isFailing(check)) {
» System.out.println(check + ​" ... FAILURE"​);
» System.err.println(​"Abort take off"​);
 return​ Status.ABORT_TAKE_OFF;
  }
» System.out.println(check + ​" ... OK"​);
  }
» System.out.println(​"Read for take off"​);
 return​ Status.READY_FOR_TAKE_OFF;
  }
 }

When you’re lucky, you can find errors in your code just by looking at it. But oftentimes, this isn’t enough and you have to run the code and investigate the memory to spot a bug. Within the development environment, you’ll usually have a debugging mode you can use to halt the execution and look at the memory. But this doesn’t work anymore when you’ve delivered the program to the production environment. In that case, you need meaningful output.

In the code above, we get an insight into the state of the program through calls to System.out.println() and System.err.println(). Errors go to System.err and all other information to System.out. With that separation, the code already provides all information we could possibly need, doesn’t it?

Well, certainly not. We actually miss out on a lot. We don’t know:

  • at what time a statement is printed
  • the number of the line of code that does the printing
  • the value of the method parameter
  • if all printed statements are equally important

And there’s more. All statements go to the console, so we can’t write a subset of the statements to a file and send the important ones via email to the people who need to know. Last but not least, string concatenation is expensive, and we do it all the time in the code above, even if we are not really interested in them.

The solution to this problem is to use a proper logging framework:

 class​ LaunchChecklist {
 
»private​ ​static​ ​final​ Logger LOGGER =
» LogManager.getLogger(LaunchChecklist.class);
 
  List<String> checks = Arrays.asList(​"Cabin Pressure"​,
 "Communication"​,
 "Engine"​);
 
  Status prepareAscend(Commander commander) {
» LOGGER.info(​"{}: Prepare ascend"​, commander);
» LOGGER.debug(​"{} Checks: {}"​, checks.size(), checks);
 for​ (String check : checks) {
 if​ (commander.isFailing(check)) {
» LOGGER.warn(​"{}: {} ... FAILURE"​, commander, check);
» LOGGER.error(​"{}: Abort take off!"​, commander);
 return​ Status.ABORT_TAKE_OFF;
  }
» LOGGER.info(​"{}: {} ... OK"​, commander, check);
  }
» LOGGER.info(​"{}: Read for take off!"​, commander);
 return​ Status.READY_FOR_TAKE_OFF;
  }
 }

There are many logging frameworks for Java and a lot of opinionated discussion about them. From what we know, Log4j[68] is one of the most widely used, and that’s why we use it here. With Log4j, you can use an internal Logger that writes class-specific messages based on a program-wide configuration.

A logger automatically writes a lot more information, which makes it easier to trace down bugs. It will log the time when it executes a statement and also the line of code. It’s also fairly easy to write all context information through parameters for the statement.

We can configure the logging framework so that some log statements are stored in files, some are sent over the network, and some are even printed to the console. What’s more, we can use log levels to mark the severity of a message—for example, debug, info, warn, error, or fatal—by calling the right method. At runtime, we can configure the logger to log only important messages and skip the rest. Not writing out all debug messages can make for a huge performance improvement. To sum up, there’s no real downside to using a logging framework apart from adding another library to the build. That’s why you’re guaranteed to use them in any productive application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.224.226