Home Tutorials Training Consulting Books Company Contact us


Get more...

Using Eclipse logging. This tutorial gives an overview how to do logging in an Eclipse application.

1. Eclipse Logging

The Eclipse `ILog class provides a simple set of APIs for logging exceptions, warnings, or other information useful in debugging or servicing a deployed Eclipse product. The intent of the log is to record information that can be used later to diagnose problems in the field. Because this information is not directed at users, you do not need to worry about translating messages or simplifying explanations into a form that users will understand. The idea is that when things go wrong in the field, your users can send you the log file to help you figure out what happened.

Each plug-in has its own log associated with it, but all logged information eventually makes its way into the platform log file (see the getLogFileLocation method on Platform).

 import org.eclipse.core.runtime.ILog;
...
public class MyLogger {
...
private static final Bundle BUNDLE = FrameworkUtil.getBundle(MyLogger.class);


...
public static void test(){
     ILog.get().info("Starting");
     try {
      // do something that may cause an exception
   }
   catch(Exception e){
             ILog.get().error("Generating template failed!", e);

     }
     ILog.get().warn("Creating a warning..");

}

During development, you can browse and manipulate the platform log file using the Error Log view (Window > Show View > General > Error Log). You can also have the log file mirrored in the Java console by starting Eclipse with the -consoleLog command-line argument.

We explicitly pass the VM because on Windows you have to use java.exe instead of javaw.exe if you want the Java console window to appear.

You can write any kind of IStatus object to the log file, including a MultiStatus if you have hierarchies of information to display. If you create your own subclass of the utility class Status, you can override the getMessage method to return extra information to be displayed in the log file.

The log level can be setup in the config.ini file of your application via the eclipse.log.level parameter. The value can be set to INFO, WARNING and ERROR. INFO will for example show all log message. By default Eclipse logs all messages.

2. SLF4J in eclipse applications

Many Java developers are more familiar with the SLF4J logging facade, which is more powerful than Eclipse’s default logger.

2.1. Obtaining the SLF4J library from Orbit

The Eclipse Orbit Project provides many different open source libraries, which can be obtained as OSGi bundles from Obrit’s p2 update sites. This makes it easy to use third party open source libraries for target definitions and a Maven Tycho build.

slf4j orbit updatesite

One of the most popular slf4j implementations is the Logback logger, which is also available on Orbit’s p2 update site.

logback orbit updatesite

The Orbit p2 update sites URLs change quite regularly. Therefore it is recommended to look in the Orbit downloads section to find the right p2 update site URL.

2.2. Using SLF4J

The SLF4J dependencies just have to be added to the desired bundle.

Use org.slf4j as imported package

After doing this the SLF4J logger API can be used in the classes of the bundle.

private static final Logger LOG = LoggerFactory.getLogger(ClassWithInfosToBeLogged.class);
It saves a lot of effort, when a Template for the creation of this LOG instance is created.

2.3. Configuring Logback

Usually Logback is configured by a logback.xml or logback-test.xml file. (see Logback configuration manual)

In an OSGi environment it is not that easy for Logback to automatically determine where the logback.xml logger configuration is stored.

For Logback the ch.qos.logback.classic.joran.JoranConfigurator is used to parse the logback.xml configuration file.

By obtaining the ch.qos.logback.classic.LoggerContext and using the JoranConfigurator the location of the logback.xml file can be set programmatically.

package com.vogella.logging.config;

import java.io.IOException;
import java.net.URL;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.service.datalocation.Location;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;

public class Activator implements BundleActivator {


    @Override
    public void start(BundleContext bundleContext) throws Exception {
        configureLogbackInBundle(bundleContext.getBundle());
    }

    @Override
    public void stop(BundleContext bundleContext) throws Exception {
    }

    private void configureLogbackInBundle(Bundle bundle) throws JoranException, IOException {
        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        JoranConfigurator jc = new JoranConfigurator();
        jc.setContext(context);
        context.reset();

        // overriding the log directory property programmatically
        String logDirProperty = // ... get alternative log directory location
        context.putProperty("LOG_DIR", logDirProperty);
        
        // this assumes that the logback.xml file is in the root of the bundle.
        URL logbackConfigFileUrl = FileLocator.find(bundle, new Path("logback.xml"),null);
        jc.doConfigure(logbackConfigFileUrl.openStream());
    }

}

In some cases it is pretty handy to have this logback.xml logger configuration in the configuration folder of the RCP application rather than bundled in a JAR file. So logback.xml logger configuration can easily be changed in a production environment if necessary. The local version of the logback.xml is still kept so that the developer does not have to copy the logback.xml file manually to the Platform.getInstallLocation() location.

private void configureLogbackExternal(Bundle bundle) throws JoranException, IOException {
    LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
    JoranConfigurator jc = new JoranConfigurator();
    jc.setContext(context);
    context.reset();

    // overriding the log directory property programmatically
    String logDirProperty = // ... get alternative log directory location
    context.putProperty("LOG_DIR", logDirProperty);

    // get the configuration location where the logback.xml is located
    Location configurationLocation = Platform.getInstallLocation();
    File logbackFile = new File(configurationLocation.getURL().getPath(), "logback.xml");
    if(logbackFile.exists()) {
        jc.doConfigure(logbackFile);
    } else {
        URL logbackConfigFileUrl = FileLocator.find(bundle, new Path("logback.xml"), null);
        jc.doConfigure(logbackConfigFileUrl.openStream());
    }
}

How to provide external static files like a logback.xml file for a product build with Maven Tycho can be found here: Eclipse Tycho Tutorial

The LOG_DIR property, which is overridden in the code above, can be obtained like this:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- With a context scope the ${LOG_DIR} variable can be obtained from the LoggerContext -->
    <!-- By using :- in the value attribute a default can be specified -->
    <property scope="context" name="LOG_DIRECTORY" value="${LOG_DIR}:-\home\default-log-dir" />

    <!-- Make use of the LOG_DIRECTORY property for the general xml configuration of Logback -->

</configuration>

3. Exercise - SLF4J and Logback in Eclipse applications

3.1. Target

Make use of SLF4J and Logback in an RCP application.

3.2. Obtaining the SLF4J and Logback library from Orbit

Install SLF4J and Logback into your IDE and reuse the IDE’s target platform or create a target definition file and add all necessary features, like eclipse SDK and logger libs, to it.

See how to obtain the SLF4J libraries from Orbit and Logback dependencies.

3.3. Create a plugin using SLF4J

Create a com.vogella.logging.rcp plug-in project, which uses the E4 Application template.

Add the SLF4J dependencies:

Use org.slf4j as imported package

Use a Logger in the generated AboutHandler class and log some debug messages or throw some Exceptions, which are logged.

package com.vogella.logging.rcp.handlers;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AboutHandler {

    private static final Logger LOG = LoggerFactory.getLogger(AboutHandler.class);

    @Execute
    public void execute(Shell shell) {
        LOG.debug("Executing about handler");
        MessageDialog.openInformation(shell, "About", "Eclipse 4 RCP Application");
    }
}
It saves a lot of effort, when a Template for the creation of this LOG instance is created.

3.4. Creating a plug-in that configures Logback

Create a com.vogella.logging.config plug-in project with an Activator.

The root folder of this plug-in should contain the following logback.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
            </Pattern>
        </layout>
    </appender>

    <logger name="com.vogella.logger" level="debug"
        additivity="false">
        <appender-ref ref="STDOUT" />
    </logger>

    <root level="debug">
        <appender-ref ref="STDOUT" />
    </root>

</configuration>

The following dependencies are required to configure Logback.

logback dependencies

Also using Imported Packages for the Logback dependencies would be preferable, but unfortunately Logback has so many packages that they won’t fit on the screenshot.

The Activator is supposed to initialize the Logback configuration.

package com.vogella.logging.config;

import java.io.IOException;
import java.net.URL;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.osgi.service.datalocation.Location;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;

public class Activator implements BundleActivator {


    @Override
    public void start(BundleContext bundleContext) throws Exception {
        configureLogbackInBundle(bundleContext.getBundle());
    }

    @Override
    public void stop(BundleContext bundleContext) throws Exception {
    }

    private void configureLogbackInBundle(Bundle bundle) throws JoranException, IOException {
        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        JoranConfigurator jc = new JoranConfigurator();
        jc.setContext(context);
        context.reset();

        // this assumes that the logback.xml file is in the root of the bundle.
        URL logbackConfigFileUrl = FileLocator.find(bundle, new Path("logback.xml"),null);
        jc.doConfigure(logbackConfigFileUrl.openStream());
    }

}

3.5. Startup the logging config bundle

The configuration of the SLF4J implementation (Logback) should be separated from the other bundles. So that no dependency to the com.vogella.logging.config bundle is necessary and other bundles just need to import the org.slf4j package, like it is done com.vogella.logging.rcp.

Due to that the com.vogella.logging.config bundle will not be started automatically. Therefore it must be added to the Start Levels in the product configuration.

Configure Start Levels in the Product

3.6. Validate

Start the sample RCP application and see whether the logging looks like expected according to your logback.xml configuration.

4. Logging resources

	include::../10_Include/sourcejava.adoc[]
If you need more assistance we offer https://learn.vogella.com/[Online Training] and https://www.vogella.com/training/[Onsite training] as well as https://www.vogella.com/consulting/[consulting]