Simplify your logging with tinylog 1.0
With a size of only 75 KB, tinylog is a lightweight alternative to the widespread classical logging frameworks Log4j and Logback. The final version 1.0 has been just released at the end of March, after three years of development. In several design issues, tinylog takes a deliberately different approach from classical logging frameworks in Java. This article will show the differences as well as the similarities to Log4j and Logback and give a brief introduction in tinylog.
Static logger
Usually for each class, in which logging is used, an own instance of a logger has to be created. All these loggers are named hierarchically, typically by the fully qualified class name. In SLF4J (Logback’s logging API) as well as Log4j 1.x, it is necessary to pass explicitly the class name:
public class MyClass { private static final Logger logger = Logger.getLogger(MyClass.class); }
As it is usual for routine work, this creation of the logger is often copied from other classes. But in this case, it is easy to forget changing the class parameter, which can lead to wrong log entries. To avoid such problems, Log4j 2.x is able to detect the class by itself. Passing the class name as parameter isn’t anymore necessary. tinylog goes one step further and resigns the need of creating for each class an own instance of the logger. Instead tinylog has a static logger on which all logging methods can be called directly:
public class Application { public static void main(String[] args) { Logger.info("Hello {}!", args[0]); } }
Configuration
There are three ways to configure tinylog: by a properties file, by system properties (can be set as “‑D” parameter) and programmatically by a fluent API. Configurations are changeable during runtime and will be always set atomic as a whole. For productive environments, it is recommended to put the properties file with the name “tinylog.properties” in the default package. tinylog will load this properties file by default if no other configuration has been explicitly specified.
By default, tinylog outputs only log entries with the logging level info or higher. All others will be discarded. Especially for development environments, it makes sense to change the global logging level to debug and maybe some packages or classes to trace. A properties file with defined log format and logging level might be look like this example:
tinylog.level = debug tinylog.level@com.example = trace tinylog.format = {level}: {class}.{method}()\t{message}
Logging writers
tinylog writes all log entries to the console by default. This default behavior can be overwritten by defining another writer. Besides writing to the console, writing to files and SQL databases is supported. tinylog has three different writers for writing to files: FileWriter
, SharedFileWriter
and RollingFileWriter
. The FileWriter
writes log entries to a defined log file. For example, it can be defined in a properties file in this way:
tinylog.writer = file tinylog.writer.filename = log.txt
The SharedFileWriter
works in the same way as the FileWriter
, but supports simultaneously logging of multiple instances of an application to the same log file without any conflicts. The RollingFileWriter
allows continuing existing log files after restarting the application. It is possible to specify by policies, when a new log file has to be started. A defined number of old log files can be stored as backups. In this example, a new log file will be started daily and the log files from the last seven days will be stored as backup, named by a timestamp:
tinylog.writer = rollingfile tinylog.writer.filename = log.txt tinylog.writer.policies = daily tinylog.writer.backups = 7 tinylog.writer.label = timestamp
Performance
In general, logging costs only a few nanoseconds per log entry. Nevertheless it is possible to improve the speed by several options. The most effective way is to enable buffered writing by setting the property ” tinylog.writer.buffered=true
” and activating the writing thread by ” tinylog.writingthread=true
” to avoid that the main application is blocked by slow IO operations. But both have the disadvantage that possibly the last – and thus the most important – log entries are lost after a crash of the JVM.
Particularly for large projects, it is common to output the class and method name together with each log entry to simplify finding the corresponding code. But Log4j as well as Logback warn that this will result in performance loss, because the generation of such stack trace information is expensive. Due to its architecture, tinylog always knows the exact depth of the caller in the stack trace. Thus, tinylog can just extract the single required stack trace element instead of generating the whole stack trace. This makes logging multiple times faster without forgoing important stack trace information.
Conclusion
This article could give only a brief introduction in tinylog. A complete manual of all configuration parameters can be found on the tinylog website. tinylog is published under the Apache License 2, thus it can be used in open source as well as in commercial projects. There are also a facade for Log4j 1.x and a binding for SLF4J to simplify migrations. Among other features, includes and excludes for writes as well as a MailWriter
for sending logs by mails are planned for the coming release.