Recipe Name:
System.err consistent Java Logger logging
Description:
Replace System.err.print.* with consistent Java Logger error logging
Level:
marked_information
Language:
  • java
Tags:
  • framework specific
  • logging
  • Logger
  • quality
Documentation

Logging any issues is considered a best practice. Making a logger available in every class reduces the threshold to use logging.

Printing messages directly to the standard output is considered a bad practice. It's recommended to use a logger instead. Logger can be turned on/off, they provide different levels of logging and can be controlled through a configuration file or environment variables. Advanced loggers enable configuration of log file rotation, log purging and tuning for multi-threading purposes. Centralised logging with multiple error levels enables you to have a clear overview of any issues in the application.

Before
public class Example {
    public void testLoggingRecipe() {
        System.out.print("Printing logs");
        System.out.println("Printing logs");
    }
}
After introducing Logger class
import java.util.logging.Level;
import java.util.logging.Logger;

public class Example {

  Logger logger = Logger.getLogger(Example.class.getName());

    public void testLoggingRecipe() {
 	logger.log(Level.INFO, "Printing logs");
        logger.log(Level.INFO, "Printing logs");
    }
}
After introducing SLF4J logger
public class Example {

    private static final org.slf4j.Logger log =
        org.slf4j.LoggerFactory.getLogger(Example.class);

    public void testLoggingRecipe() {
        logger.log(Level.INFO, "Printing logs");
    }
}
Recipe
id: scw:logging:Logger:System.err_consistent_logging
version: 10
metadata:
  name: System.err consistent Java Logger logging
  shortDescription: Replace System.err.print.* with consistent Java Logger error logging
  level: marked_information
  language: java
  scwCategory: insufficient_logging:generic
  cweCategory: 778
  enabled: true
  descriptionFile: Java/Logging/descriptions/ReplacePrintWithLogger.html
  tags: framework specific;logging;Logger;quality
search:
  methodcall:
    in:
      typeDeclaration:
        without:
          child:
            field:
              name: logger
              type:
                reference:
                  not: java.util.logging.Logger
                checkInheritance: true
    name:
      matches: print.*
    declaration:
      type: java.io.PrintStream
    "on":
      reference:
        name: err
availableFixes:
- name: Use Logger class
  actions:
  - addField:
      field: private static final java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name }}}.class.getName())
      target: parentClass
  - rewrite:
      to: logger.log(java.util.logging.Level.INFO, {{{ arguments }}})
      target: self