77

I have the followed imports:

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

and the following instantiation:

private static Logger logger = LoggerFactory.getLogger(Test.class);

and the following in my Main method:

logger.info("SOME MESSAGE: ");

However, I'm not able to find the output anywhere. All I see is that in my console there is:

21:21:24.235 [main] INFO  some_folder.Test - SOME MESSAGE: 

How do I locate the log file?

Note that the following are on my build path:

slf4j-api-1.7.5.jar

slf4j-log4j12-1.6.4.jar

I read the answer to similar questions but nobody actually says how to fix the problem.

user2763361
  • 3,789
  • 11
  • 45
  • 81
  • 2
    slf4j is only an API. You should have a concrete implementation (for example log4j). This concrete implementation has a config file which tells you where to store the logs. – Arnaud Denoyelle Feb 19 '14 at 13:30
  • 1
    @ArnaudDenoyelle He builds with slf4j-log4j12-1.6.4.jar which means he is including an implementation. – jmkgreen Feb 19 '14 at 13:31

4 Answers4

61

slf4j is only an API. You should have a concrete implementation (for example log4j). This concrete implementation has a config file which tells you where to store the logs.

enter image description here

When slf4j catches a log messages with a logger, it is given to an appender which decides what to do with the message. By default, the ConsoleAppender displays the message in the console.

The default configuration file is :

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">

  <Appenders>
    <!-- By default => console -->
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>

  <Loggers>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

If you put a configuration file available in the classpath, then your concrete implementation (in your case, log4j) will find and use it. See Log4J documentation.

Example of file appender :

<Appenders>
<File name="File" fileName="${filename}">
  <PatternLayout>
    <pattern>%d %p %C{1.} [%t] %m%n</pattern>
  </PatternLayout>
</File>

...
</Appenders>

Complete example with a file appender :

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">

  <Appenders>
    <File name="File" fileName="${filename}">
      <PatternLayout>
        <pattern>%d %p %C{1.} [%t] %m%n</pattern>
      </PatternLayout>
    </File>
  </Appenders>

  <Loggers>
    <Root level="error">
      <AppenderRef ref="File"/>
    </Root>
  </Loggers>

</Configuration>
Arnaud Denoyelle
  • 29,980
  • 16
  • 92
  • 148
  • I have log4j on my build path don't I? – user2763361 Feb 19 '14 at 13:32
  • @user2763361 Then you should put a log4j configuration file in your classpath and log4j will use it. – Arnaud Denoyelle Feb 19 '14 at 13:41
  • What do I need to call this config file for it to find it? – user2763361 Feb 19 '14 at 13:46
  • @user2763361 You do not need to explicitly call it. Log4J tries to find it at its initialization. You only have to place the file in the classpath. – Arnaud Denoyelle Feb 19 '14 at 13:48
  • Where does the log file get outputted though? – user2763361 Feb 19 '14 at 13:50
  • @user2763361 I put an example with a simple file appender. As you can see, there is a `fileName` attributes which indicates which file to user to output logs. – Arnaud Denoyelle Feb 19 '14 at 13:52
  • Where do I input the filename? What's `${filename}`? Also there are two chunks of code. Do I combine them into the same chunk of code? – user2763361 Feb 19 '14 at 13:53
  • @user2763361 1) you have to replace `${filename}` with the path where you want to have the log file. For example, `c:\path\to\your\logFile.txt` or `/var/log/yourAppName/errors.log`. 2) Yes, you must combine the 2 blocks of code. – Arnaud Denoyelle Feb 19 '14 at 13:57
  • @user2763361 There are mainly 2 parts in the config files : *Loggers* and *Appenders*. Loggers tell which message to catch and to which appenders they must be forwarded. Then Appenders decide what to do with them. You should look at the doc for more information because log4j can do a lot of stuff for you and it would be too long to explain here. – Arnaud Denoyelle Feb 19 '14 at 13:59
  • I set the row to be changed to ``, and removed the `...` in the second code block, combined them and pasted into `/src` as file `log4j.properties`. Then I hit CTRL+F11 in my main method and there was no log file outputted (still only output to console) – user2763361 Feb 19 '14 at 14:02
  • @user2763361 does log4j warn you that no config file was found? (it should be in the very first lines in the console) – Arnaud Denoyelle Feb 19 '14 at 14:04
  • It says `SLF4J: Class path contains multiple SLF4J bindings.` but that's it. But it outputs the logger to console properly. – user2763361 Feb 19 '14 at 14:04
  • @user2763361 You must solve this problem first because in this case, you are not sure that slf4j really uses log4j. – Arnaud Denoyelle Feb 19 '14 at 14:07
  • @user2763361 Are you sure that you do not have slf4j-simple.jar or slf4j-nop.jar? It would disturb slf4j. – Arnaud Denoyelle Feb 19 '14 at 14:08
  • In `Run configurations (on main method) -> classpath -> userentries` (Eclipse) I have `slf4j-api.jar`, `log4j-over-slf4j.jar`, `slf4j-api-1.7.5.jar`, `slf4j-log4j12-1.6.4.jar`. In `RightClick (on the project) -> build path -> configure build path -> libraries` I have `slf4j-api-1.7.5.jar` and `slf4j-log4j12-1.6.4.jar`. – user2763361 Feb 19 '14 at 14:11
  • @user2763361 Remove `log4j-over-slf4j.jar`. The binding between log4j and slf4j is already done by `slf4j-log4j12-1.6.4.jar`. Also remove `slf4j-api.jar`. You already got `slf4j-api-1.7.5.jar`. – Arnaud Denoyelle Feb 19 '14 at 14:14
  • Can I go the other way (remove 1.6.4 but keep the other one)? – user2763361 Feb 19 '14 at 14:15
  • @user2763361 I have never tried :). Provided that you don't have duplicates, it should not be a problem. – Arnaud Denoyelle Feb 19 '14 at 14:16
  • Sorry but what should I named the configuration file, and where to place it? I create file name logConfig.xml or logConfig.config, place in main directory, build project to .jar file, and event place config file in same folder with .jar file when running project but log only showed in console, no log file being created? – Pham X. Bach Oct 19 '22 at 08:00
43

As already mentioned its just a facade and it helps to switch between different logger implementation easily. For example if you want to use log4j implementation.

A sample code would looks like below.

If you use maven get the dependencies

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.6</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.5</version>
    </dependency>

Have the below in log4j.properties in location src/main/resources/log4j.properties

            log4j.rootLogger=DEBUG, STDOUT, file

            log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
            log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
            log4j.appender.STDOUT.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

            log4j.appender.file=org.apache.log4j.RollingFileAppender
            log4j.appender.file.File=mylogs.log
            log4j.appender.file.layout=org.apache.log4j.PatternLayout
            log4j.appender.file.layout.ConversionPattern=%d{dd-MM-yyyy HH:mm:ss} %-5p %c{1}:%L - %m%n

Hello world code below would prints in console and to a log file as per above configuration.

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

            public class HelloWorld {
              public static void main(String[] args) {
                Logger logger = LoggerFactory.getLogger(HelloWorld.class);
                logger.info("Hello World");
              }
            }

enter image description here

Jay
  • 9,189
  • 12
  • 56
  • 96
  • Do I need to put it in `src/main/resources`? Because I don't have `main` as a subfolder to `src`. So I just put it in `src`. Then I overwrote your `mylogs.log` to `/home/user/workspace/project/src/mylogs.log`, then ran `HelloWorld`, and it didn't output a log file in the desired location. (No error message just no output) – user2763361 Feb 19 '14 at 13:58
  • Yes, if its a maven project you would have folders created automatically /src/main/resources/. Please see the screen shot above. – Jay Feb 19 '14 at 14:04
  • It's not a Maven project so I only put it in `src`. – user2763361 Feb 19 '14 at 14:05
  • Yes, you would put in /src/ folder. – Jay Feb 19 '14 at 14:11
  • 3
    This is a much cleaner implementation than writing it in XML. – wheeler May 04 '17 at 15:46
  • this ans is the most complete one. thank you so much – ahrooran Dec 04 '20 at 07:41
4

It does not write to a file by default. You would need to configure something like the RollingFileAppender and have the root logger write to it (possibly in addition to the default ConsoleAppender).

jmkgreen
  • 1,633
  • 14
  • 22
1

The log file is not visible because the slf4j configuration file location needs to passed to the java run command using the following arguments .(e.g.)

-Dlogging.config={file_location}\log4j2.xml 

or this:

-Dlog4j.configurationFile={file_location}\log4j2.xml
naimdjon
  • 3,162
  • 1
  • 20
  • 41