The logging described here has nothing to do with the internal ADEPT2-logging used for tracking changes in process states or structures (execution history, data history, change history). Merely, this logging is used for implementation issues as error messages and debugging.

Logging

To avoid the messy System.out.println(...) for error messages throughout the code, the Java-Logging is used (see java.util.logging).

Java logging

The logging in Java is based on a logger hierarchy which is reflected in the name of the Loggers. "" is the root logger that gets all log messages. All other loggers have arbitrary names, whereas a hierarchy is defined similar to the java-package mechanism, for instance, hierarchy1.Logger1, hierarchy1.Logger2, hierarchy1.subhierarchy1.Logger1, hierarchy2.Logger1,... Parent loggers also log messages of child loggers.
Despite the similarity, this hierarchy is strictly separated from the package structure as well as the class hierarchy. The name of the method and the full name of the corresponding class are implicitly logged and thus allowing a very flexible and completely detached logger hierarchy.

Providing loggers in ADEPT2

In ADEPT2 every class has its own (protected and final) class field for its logger (if needed). The logger has its own name which equals the name of the class (including package).
When subclassing one should pay attention to always use the most specific logger, that is the logger in the most specific subclass. For this to work, the retrieval of a logger (Logger.getLogger(String)) is done in the constructor of the superclass:
public class Super
{
  private static final String loggerName;
  protected Logger logger;
  public Super(...)
  {
    LoggerTools.getLogger(this);
  }
  ...
}
Logger for (static) class methods are set directly after the declaration of the class variable:
private static Logger logger = Logger.getLogger("staticLogger");
Obviously, this joins the logger with the class hierarchy which is done for easier usage. To further simplify this, the first two prefixes (de.aristaflow.) are omitted for ADEPT2-logger.

Providing log messages in ADEPT2

ADEPT2 allows to have multiple instances of one component with user-defined instance names, for instance, a data manager DM1 and a data manager DM2. If the corresponding data manager class wants to log its specific name, it will be prepended to every log message:
logger.severe(String.format("'%1$s': Database error.", instanceName));

Logging exceptions in ADEPT2

Log messages should contain much context information to allow for easy tracking of the source of a log message. The message itself has to be formatted using String.format(String, Object...). This eases reading of a message in the source code.
Exception handling generally consists of logging a message and continuing or rethrowing an exception. Java logging directly supports logging of exceptions providing the complete stack trace and avoiding messy log messages containing the stack trace:
try
{
  ...
}
catch (SQLException sqle)
{
  logger.log(Level.SEVERE, "Database Connection failed.", sqle);
}

Configuration of the ADEPT2-logging

The logging-output is configured via the boot configuration in Boot.properties. There are two types of logging-output: console logging and file logging. Per system (JVM) only one console is allowed but arbitrary log files. The latter allows for very adjustable logging since every node in the logger hierarchy can have its own log file - including, of course, the log messages of the child loggers. The configuration takes the following form: The log files have the same name as their corresponding logger, succeeded by ".log". Example configuration:
# Boot.properties
# disable console logging
Logging.ConsoleLogger.Level = OFF

# register the file loggers
Logging.Instances.FileLogger = adept2warnings, processmanager
# path to the log directory
Logging.FileLogger.LogDirectory = /var/log/adept2/

# log all log-messages equal to or exceeding log-level WARNING
Logging.adept2warnings.Root = adept2
Logging.adept2warnings.Level = WARNING

# log all log-messages from the process managers, equal to or exceeding log-level INFO
Logging.processmanager.Root = adept2.core.processmanager
Logging.processmanager.Level = INFO