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 writer
, writer2
, writer3
, 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 writerConsole
, writerFile
, writerJDBC
, 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