This tutorial shows logging in Java application using the tinylog lightweight logging framework.

P.S Tested with tinylog 2.3.2.

1. tinylog Dependency

For tinylog logging, we need to add tinylog-api and tinylog-impl to the project classpath.

pom.xml

  <dependency>
      <groupId>org.tinylog</groupId>
      <artifactId>tinylog-api</artifactId>
      <version>2.3.2</version>
  </dependency>

  <dependency>
      <groupId>org.tinylog</groupId>
      <artifactId>tinylog-impl</artifactId>
      <version>2.3.2</version>
  </dependency>

2. tinylog Hello World

The tinylog has a static logger; therefore, we no need to create an instance of the logger class like the below:

  // no need to declare Logger, tinylog provide static Logger
  // private static Logger logger = Logger.getLogger(HelloWorld.class.getName());

HelloWorld.java

package com.favtuts;

import org.tinylog.Logger;

public class HelloWorld {

    // no need declare Logger like other logging frameworks

    public static void main(String[] args) {

        Logger.info("Hello World tinylog!");

        Logger.trace("This is trace!");

        Logger.debug("This is debug!");

        Logger.info("This is info!");

        Logger.warn("This is warn!");

        Logger.error("This is error!");

    }

}

Output

2021-06-09 14:39:01 [main] com.favtuts.HelloWorld.main()
INFO: Hello World tinylog!
2021-06-09 14:39:01 [main] com.favtuts.HelloWorld.main()
TRACE: This is trace!
2021-06-09 14:39:01 [main] com.favtuts.HelloWorld.main()
DEBUG: This is debug!
2021-06-09 14:39:01 [main] com.favtuts.HelloWorld.main()
INFO: This is info!
2021-06-09 14:39:01 [main] com.favtuts.HelloWorld.main()
WARN: This is warn!
2021-06-09 14:39:01 [main] com.favtuts.HelloWorld.main()
ERROR: This is error!

3. tinylog Logging Levels

The tinylog supports five logging levels:

  • trace
  • debug
  • info
  • warn
  • error

In tinylog, the default logging level is trace.

4. Logs with the arguments

In tinylog, we can use {} placeholders to represent the arguments.

  Logger.trace("arg1 {} and arg2 {}", a, b);
  Logger.debug("arg1 {} and arg2 {}", a, b);
  Logger.info("arg1 {} and arg2 {}", a, b);
  Logger.warn("arg1 {} and arg2 {}", a, b);
  Logger.error("arg1 {} and arg2 {}", a, b);

Below is a complete tinylog example to logs with arguments.

LogWithArguments.java

package com.favtuts;

import org.tinylog.Logger;

public class LogWithArguments {

  public static void main(String[] args) {

      String msg = "info";
      int number = 9;

      Logger.info("This is {}, {}", msg, number);

      Logger.error("This is {}", "error");

  }

}

Output

2021-06-09 15:08:36 [main] com.favtuts.LogWithArguments.main()
INFO: This is info, 9
2021-06-09 15:08:36 [main] com.favtuts.LogWithArguments.main()
ERROR: This is error

5. tinylog.properties

In tinylog, it defaults to find the tinylog.properties file from the project classpath; the tinylog.properties defined the configuration values for the tinylog.

Below is the example of a tinylog.properties, it logs the message to the Console via a custom format, and set the logging level to info.

src/main/resources/tinylog.properties

# logs to Console
writer        = console
writer.format = {date: HH:mm:ss.SSS} {level}: {message}
writer.level  = info
  Logger.info("Hello World tinylog!");
  Logger.trace("This is trace!");
  Logger.debug("This is debug!");
  Logger.info("This is info!");
  Logger.warn("This is warn!");
  Logger.error("This is error!");

Output

14:52:03.774 INFO: Hello World TinyLog!
14:52:03.777 INFO: This is info!
14:52:03.777 WARN: This is earn!
14:52:03.777 ERROR: This is error!

6. tinylog.configuration

We can pass the tinylog.properties file to the application via the system property tinylog.configuration.

$ java -jar -Dtinylog.configuration=/path/tinylog.properties application.jar

# the name of tinylog.properties is optional, it can be any name.
$ java -jar -Dtinylog.configuration=/path/abcdefg.properties application.jar

7. Send logs to a file

The below example logs an exception and sends it to a file.

src/main/resources/tinylog.properties

# logs to a file
writer       = file
writer.file  = log.txt
writer.level = info

LogWithException.java

package com.mkyong;

import org.tinylog.Logger;

public class LogWithException {

  public static void main(String[] args) {

      try {
          int answer = 1 / 0;
          System.out.println(answer);
      } catch (Exception ex) {
          Logger.error(ex);
      }

  }

}

All logged messages send to file log.txt.

log.txt

2021-06-09 15:20:53 [main] com.favtuts.LogWithException.main()
ERROR: java.lang.ArithmeticException: / by zero
at com.favtuts.LogWithException.main(LogWithException.java:10)

8. Send logs to Console and file

For multiple writers, we must provide a unique name for each writer. The writer’s name can be anything starts with writer.

We can use writerwriter2writer3, etc.

tinylog.properties

# logs to Console
writer        = console
writer.format = {date: HH:mm:ss.SSS} {level}: {message}
writer.level  = info

# logs to a file
writer2       = file
writer2.file  = log.txt
writer2.level = info

Or more meaning names, like writerConsolewriterFilewriterJDBC, etc.

tinylog.properties

# logs to Console
writerConsole      = console
writerConsole.format = {date: HH:mm:ss.SSS} {level}: {message}
writerConsole.level  = info

# logs to a file
writerFile       = file
writerFile.file  = log.txt
writerFile.level = info

9. Rolling File

Note
Read the official tinylog rolling file writer for a more detailed explanation.

The writer.policies = startup, daily: 00:00, size: 1mb tells tinylog to create a new log file or rotate the log file daily or based on file size, whichever hits first; the rest of the configuration values are self-explanatory.

tinylog.properties

# rolling file
writer          = rolling file
writer.level    = info
writer.format   = {date: HH:mm:ss.SSS} {level}: {message}
# writer.file     = {date:yyyy}/{date:MM}/log-{pid}.{count}.log
writer.file     = logs/{date:yyyy-MM-dd}-log.{count}.log
writer.latest   = logs/latest.log
writer.charset  = UTF-8
writer.buffered = true
writer.policies = startup, daily: 00:00, size: 1mb
writer.backups  = 100
writer.convert  = gzip

A tinylog example to test the rolling file.

RollingFileExample.java

package com.favtuts;

import org.tinylog.Logger;

public class RollingFileExample {

    public static void main(String[] args) {

        // create hello x 3 per line
        String line = "Hello tinylog! ";
        line = line + line + line;

        System.out.println(line);

        int count = 0;
        while (count < 100_000) {
            Logger.info(line + count);
            count++;
        }

        System.out.println("Done");
    }

}

The above example logs 100k lines, and it will generate around 6MB+ file size. For the writer policy of size: 1mb, it will generate 7 log files and gzip it, and the latest.log contains the latest logged messages.

P.S Both latest.log and 2021-06-09-log6.log.gz contain the same logged message.

tinylog writers
The tinylog provides seven different writers:

* Console

* File

* JDBC (Database)

* JSON

* Logcat (Android)

* Rolling file

* Shared File

Read more on this documentation – tinylog writers.

10. Tags

In tinylog, we can send logs to different writers by using tags, a handy feature.

TagExample.java

package com.favtuts;

import org.tinylog.Logger;

public class TagExample {

  public static void main(String[] args) {

      Logger.info("normal");

      // send to writer tagged `system`
      Logger.tag("system").error("this is system!");

      // send to writer tagged `api`
      Logger.tag("api").info("This is normal api log!");

  }

}

tinylog.properties

# logs to Console
writer        = console
writer.format = {date: HH:mm:ss.SSS} {level}: {message}
writer.level  = info

# logs to a file, tag `api`
writer2       = file
writer2.tag   = api
writer2.file  = logs/api.log
writer2.format={date: yyyy-MM-dd HH:mm:ss.SSS} {level}: {message}
writer2.level = info

# logs to a file, tag `system`
writer3       = file
writer3.tag   = system
writer3.file  = logs/system.log
writer3.format={date: yyyy-MM-dd HH:mm:ss.SSS} {level}: {message}

Output, the writer console has no tag; it will display all the logged messages.

17:15:55.236 INFO: normal
17:15:55.239 INFO: This is normal api log!
17:15:55.239 ERROR: this is system!

The logs tagged with api will send to the writer tagged with api.

logs/api.log

2021-06-09 17:15:55.239 INFO: This is normal api log!

The logs tagged with system will send to the writer tagged with system.

logs/system.log

2021-06-09 17:15:55.239 ERROR: this is system!

11. Writing thread and async logger

The tinylog supports asynchronous loggers or non-blocked loggers using writing thread, which enable writers to run in a separate thread.

tinylog.properties

# optional, default: false
writingthread = true

Enable this writingthread in tinylog.properties for better logging performance.

12. Why Choose tinylog?

The tinylog is fast; read this benchmark.

13. Further Reading

The tinylog documentation is very detail and organized, make sure to check it for a detailed explanation.

14. Download Source Code

$ git clone https://github.com/favtuts/java-core-tutorials-examples

$ cd java-logging/tinylog

15. References

Leave a Reply

Your email address will not be published. Required fields are marked *