1. qualyzer
  2. main

Wiki

Clone wiki

main / Logging

Logging

Qualyzer relies on two libraries to provide logging facilities: SLF4J and log4j. SLF4J is a logging frontend that provides a common logging API and that accepts many logging libraries as a backend. log4j is one of the oldest, most optimized and most configurable logging libraries for Java and is used as a backend. log4j can be configured through one configuration file or through an API.

This configuration was chosen because Hibernate, one of the frameworks used by Qualyzer, already relies on SLF4J and lets the users (us) select the appropriate backend. By using the same logging library, we avoid loading multiple logging libraries and we can use the same configuration file for both products.

The two libraries and the log4j configuration file are contained by the ca.mcgill.cs.swevo.qualyzer.logging plug-in.

Configuration

The configuration file is located in ca.mcgill.cs.swevo.qualyzer.logging/src/log4j.properties

Two "outputs" are defined in the file: a console output (used for debugging logging statements) and a file output (only used for reporting warnings and errors).

The generated log file is called qualyzer.log and is written to the $HOME directory. If there are no warnings or errors generated during a session, the file is not created. If the file already exists, the logging statements are appended to the file. If the file becomes too big, multiple files are created.

It is possible to define fine-grained logging rules within the configuration file. Currently, there are only two broad rules that are defined and they cover hibernate (org.hibernate) and qualyzer (ca.mcgill.cs.swevo.qualyzer). See the commented configuration lines to control Hibernate: these lines were mentioned in the Hibernate documentation.

Consult the log4j tutorial and the log4j API for more information about the configuration options.

Logging in Qualyzer

General rules:

  1. Don't log exceptions, errors, and warnings that are caused by invalid user actions (e.g., non unique transcript id).
  2. Always append the exception when reporting an error in a catch block.
  3. If you want to include a detailed error message (e.g., the name of the file that could not be deleted), be sure to make the appropriate safety check (e.g., checking if the file is null before getting its name) to avoid causing a new exception.
  4. Logging too many details can leak sensitive information to the log file.
  5. Use Logger.error to report exceptions and Logger.warn to report errors/warnings that were not caused by an exception.
  6. Logging messages should not be translated, but for convenience, the translated message key can be used (see the warning example) to avoid duplicating strings.
  7. The logging file already contains the source file path and the line number so there is no need to precisely indicate the location of the error.

Consult the SLF4J api.

One Logger per class

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QualyzerActivator
{

    private final Logger fLogger = LoggerFactory.getLogger(QualyzerActivator.class);

Note: The fully qualified name of Logger is org.slf4j.Logger, not java.util.logging.Logger or org.apache.log4j.Logger. The parameter for getLogger should be the class that declares the Logger.

Logging Errors

public void deleteParticipant(Participant participant)
{
    ...

    try
    {
        session = manager.openSession();
	t = session.beginTransaction();
        ...	
    }
    catch(HibernateException e)
    {
        HibernateUtil.quietRollback(t);
        String errorMessage = "Error while trying to delete the participant from the database.";
        fLogger.error(errorMessage, e);
        throw new QualyzerException(errorMessage, e);
    }
}

Note: errors appear on the console and in the logging file. Always append the exception if there is one.

Logging Warnings

public Object execute(ExecutionEvent event) throws ExecutionException
{
    ...
    if(projects.size() > 1)
    {
        String warningMessage = "handles.DeleteTranscriptHandler.cannotDeleteFile"
        fLogger.warn(warningMessage);
        MessageDialog.openError(shell, "Unable to Delete",  Messages.getString(warningMessage));
    }
    else
    {
        proceedWithDeletion(page, shell, toDelete);
    }
    ...
}

Note: warning messages should only be logged if they describe an unusual situation, not if they are caused by a user action (e.g., invalid input).

Logging Info Statements

public void start(BundleContext context) throws Exception
{
    ...
    fLogger.info("Qualyzer Started");
}

Note: these logging statements only appear on the console. They are a better alternative to System.out.println and they can be used during debugging/testing.

Updated