August 14, 2022

tinylog Tutorial

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.