3

I am trying to add a logger to one of my programs, mainly to replace the System.out.println(), and it seems to give me some problems. This is my first time using a logger, so I am a noob at it.

I had a look at a multitude of links over the past days but still haven't managed to make my logger catch an exception; here are some of the links I looked at (some of them are 5 years old and might need updates):

I am using:

  • slf4j-api-1.7.22.jar
  • slf4j-simple-1.7.22.jar
  • jdk1.8.0_71
  • IntelliJ 2016.3.2

The simpleLogger.properties is placed directly in the resources package, this file is loaded before the logger is created, the file is loaded correctly as I can modify the date-time as I need it to be (and other settings work as well).

Part of the Main class:

...
private Logger LOG; //field
...

public static void main(String[] args) {
    launch(args);
}

...

@Override
public void start(Stage primaryStage) {
    /*Create logger*/
    createLogger();
    LOG.info("Stage start.");
    ...
}

...

private void createLogger() {
    try {
        Properties properties = new Properties();
        properties.load(LOGGER_PROPERTIES); //path to prop file
    } catch (IOException e) {
        e.printStackTrace();
    }

    LOG = LoggerFactory.getLogger(Main.class);
    LOG.info("Logger initialised.");

    LOG.trace("test trace"); //not working
    LOG.debug("test debug"); //not working
    LOG.info("test info");
    LOG.warn("test warning");
    LOG.error("test error");
}

The simpleLogger.properties file:

org.slf4j.simpleLogger.logFile=System.out
# org.slf4j.simpleLogger.defaultLogLevel=
# org.slf4j.simpleLogger.log.a.b.c=
org.slf4j.simpleLogger.showDateTime=true
org.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss:SSS
org.slf4j.simpleLogger.showThreadName=false
org.slf4j.simpleLogger.showLogName=false
org.slf4j.simpleLogger.showShortLogName=true
org.slf4j.simpleLogger.levelInBrackets=true
# org.slf4j.simpleLogger.warnLevelString=

# THE FORMAT TRIED
#org.slf4j.simpleLogger.SimpleFormatter.format = [%1$tc] %4$s: %2$s - %5$s %6$s%n
#java.util.logging.SimpleFormatter.format = [%1$tc] %4$s: %2$s - %5$s %6$s%n
#java.util.logging.SimpleFormatter.format="%1$tc %2$s%n%4$s: %5$s%6$s%n"
#org.slf4j.simpleLogger.format=[%1$tc] %4$s: %2$s - %5$s %6$s%n %7$s
#org.slf4j.helpers.MessageFormatter.format = [%1$tc] %4$s: %2$s - %5$s %6$s%n %7$s
#java.util.logging.SimpleFormatter.format="%1$tc %2$s%n%4$s: %5$s%6$s%n"

Part of the class where I am attempting to create an exception:

LOG.info("Creating window - More info: loading.. .fxml");
try {
    BP_INFO = FXMLLoader.load(getClass().getResource("/fxml/ImageInf_.fxml")); //HERE change back to ImageInfo.fxml
    LOG.info("Creating window - More info: loaded .fxml successfully.");
} catch (IOException e) {
    //  HERE not showing anything below
    System.out.println("CATCH - From Sys out");
    LOG.error("CATCH - EXCEPTION", (Throwable) e);
    LOG.error("Creating window - More info: Exception");
    LOG.error("Creating window - More info: Exception", e);        
    LOG.error("Creating window - More info: Exception {}", e);
    LOG.error("Creating window - More info: Exception {} {} {}", Level.INFO, e.getMessage(), e);
    //  e.printStackTrace();
}

Console output:

12:17:08:995 [INFO] Main - Logger initialised.
12:17:08:996 [INFO] Main - test info
12:17:08:997 [WARN] Main - test warning
12:17:08:997 [ERROR] Main - test error
12:17:08:997 [INFO] Main - Stage start.
...
12:17:27:140 [INFO] View - Creating window - More info: loading.. .fxml
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
...

Problem 1:

As you can see trace and debug are not working. I have tried all the properties in the prop. file and some more as well but so far did not manage to catch any exception or apply a specific format.

Problem 2:

As you can see, the exception is also not logged at all.

Additional info: I have reset IntelliJ settings, I have been cleaning the win %temp% folder various times, I have been cleaning caches and restarted Intellij various times; all this in an attempt if the prop. file was not read correctly or kept somewhere in a cache.

Any help is much appreciated. Please respond in a simplistic way.

Community
  • 1
  • 1
4673_j
  • 477
  • 1
  • 6
  • 20

3 Answers3

3

We may use Slf4j within a JavaFX project by using only these dependencies:

  • slf4j-api-1.7.22.jar
  • slf4j-simple-1.7.22.jar

Here's an example Application class:

...

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

public class Todo extends Application {

    private static final Logger log = LoggerFactory.getLogger(Todo.class);

    ...

    public static void main(String[] args) {

        log.info("launching...");
        log.warn("launching...");
        log.error("launching...");
        log.debug("launching...");
        log.trace("launching...");

        launch(args);
    }
}

Slf4j simple already has default settings that may be fine for various scenarios. That not being the case, the logger may be configured by adding simplelogger.properties to the classpath, which will be automatically picked up by Slf4j on application startup. The javadoc for the SimpleLogger class nicely enlists all the properties that may be configured.

The contents of a simplelogger.properties file that modifies the log level only:

org.slf4j.simpleLogger.defaultLogLevel=trace

And here is the output when running with the log level set to trace:

[main] INFO todo.Todo - launching... 
[main] WARN todo.Todo - launching... 
[main] ERROR todo.Todo - launching... 
[main] DEBUG todo.Todo - launching... 
[main] TRACE todo.Todo - launching...
rbento
  • 9,919
  • 3
  • 61
  • 61
  • Thanks for the effort, with the logger final, at which point do you load the `simplelogger.properties` file? – 4673_j Jan 11 '17 at 13:29
  • 2
    It's a regular java property file. Whenever it's present in the classpath slf4j automatically loads it to configure itself on application startup. It's described in the slf4j-simple docs. – rbento Jan 11 '17 at 13:34
2

Problem #1 (trace and debug level is not logged)

From the doc of SimpleLogger:

org.slf4j.simpleLogger.defaultLogLevel - Default log level for all instances of SimpleLogger. Must be one of ("trace", "debug", "info", "warn", "error" or "off"). If not specified, defaults to "info".

Because the defult level is info, and trace and debug levels are "under" info, they will be filtered out by the logger and will not reach the appender.

So if you add the following line in the properties file:

org.slf4j.simpleLogger.defaultLogLevel = trace

you should see also messages with trace and debug level.

Problem #2 (the error trace is not logged properly)

You are catching IOExceptions, but an InvocationTargetException is actually thrown (which one is not catched), therefore the execution will never enter your catch block. What you see on the console is an unhandled runtime exception printed.

DVarga
  • 21,311
  • 6
  • 55
  • 60
  • I tried this and you are correct, this solved part of the problem, I was not aware of that.. – 4673_j Jan 11 '17 at 13:04
  • Updated the answer regarding your problem with th exception. – DVarga Jan 11 '17 at 13:11
  • 1
    Um.. I'm not aware of the `InvocationTargetException`, I can see the problem is actually a different one here; how can I catch this exception then? – 4673_j Jan 11 '17 at 13:18
  • 1
    OH! wow.. I did not expect this, now it works if I just use `catch (Exception e)` ; how come is not catching `IOException`, at a lower level? – 4673_j Jan 11 '17 at 13:22
  • 1
    Yes, I just wanted to reply to catch `Exception` instead:) It works because `InvocationTargetException` is an `Exception` but it is not an `IOException`. – DVarga Jan 11 '17 at 13:24
  • Appreciate the effort and explanation, another request: how would your log look like if you would like to catch this ex.? ex: `LOG.error(... ;` – 4673_j Jan 11 '17 at 13:27
  • I guess two problems are more than enough for one question - which two are answered-, please ask another question to another problems, otherwise it will become a chat-apocalype :) – DVarga Jan 11 '17 at 13:30
  • Agreed, I will dig my way around for the formatting. Thanks again. – 4673_j Jan 11 '17 at 13:31
0

As described here, there could be per user configuration of Maven logging for one installation. I copied default simplelogger.properties to $M2_HOME/conf/logging and added:

org.slf4j.simpleLogger.log.com.example=trace

and it logs fine. This is not maybe the best solution, but the one I've found fitting my needs. You can log DEBUG but not TRACE as I remember I've read somewhere.