You can edit this page on GitHub

Unlike other logging frameworks, tinylog has a static logger. Thus, the logger class can be used directly without creating an instance of the logger. tinylog supports five different severity levels: trace, debug, info, warn, and error. The logging methods are named according to the severity levels (for example, Logger.trace() for trace). Which severity levels should be output is configurable.

Plain Text

The most common logging method is probably the plain text output:

Logger.trace("Hello World!");
Logger.debug("Hello World!");"Hello World!");
Logger.warn("Hello World!");
Logger.error("Hello World!");

Text with Arguments

Texts can be assembled at runtime by using "{}" placeholders. For performance reasons, "{}" placeholders should be used instead of manual concatenation of strings by using the "+" operator.

Logger.trace("Divide {} by {}", a, b);
Logger.debug("Divide {} by {}", a, b);"Divide {} by {}", a, b);
Logger.warn("Divide {} by {}", a, b);
Logger.error("Divide {} by {}", a, b);

Numbers can be formatted by using a DecimalFormat-compatible pattern within the curly brackets of a placeholder.

Logger.trace("Income: {0.00} EUR", amount);
Logger.debug("Income: {0.00} EUR", amount);"Income: {0.00} EUR", amount);
Logger.warn("Income: {0.00} EUR", amount);
Logger.error("Income: {0.00} EUR", amount);

Conditional formatting of numbers is possible by using a ChoiceFormat-compatible pattern within the curly brackets of a placeholder.

Logger.trace("There {0#are no files|1#is one file|1<are {} files}", count);
Logger.debug("There {0#are no files|1#is one file|1<are {} files}", count);"There {0#are no files|1#is one file|1<are {} files}", count);
Logger.warn("There {0#are no files|1#is one file|1<are {} files}", count);
Logger.error("There {0#are no files|1#is one file|1<are {} files}", count);


For performance reasons, objects should never be logged by calling the toString() method directly. tinylog has its own method for logging objects, which only calls the toString() method if a log entry is actually output.



Exceptions and other throwables can be directly passed to a logging method. An additional textual message is optional.


In tinylog, exceptions are always the first argument and passed before a message or other arguments.

Logger.trace(ex, "Cannot divide {} by {}", a, b);
Logger.debug(ex, "Cannot divide {} by {}", a, b);, "Cannot divide {} by {}", a, b);
Logger.warn(ex, "Cannot divide {} by {}", a, b);
Logger.error(ex, "Cannot divide {} by {}", a, b);

Lazy Logging

Sometimes a message or an argument must be computed specifically for logging. For expensive computations, lazy logging with lambda expressions is recommended, as these will only be evaluated if a log entry is actually output.

Logger.trace(() -> compute());
Logger.debug(() -> compute()); -> compute());
Logger.warn(() -> compute());
Logger.error(() -> compute());

Lambda expressions can also be passed as arguments for a text with "{}" placeholders:

Logger.trace("Expensive computation: {}", () -> compute());
Logger.debug("Expensive computation: {}", () -> compute());"Expensive computation: {}", () -> compute());
Logger.warn("Expensive computation: {}", () -> compute());
Logger.error("Expensive computation: {}", () -> compute());


tinylog supports tags for categorizing log entries. For example, tags can be output as part of the format pattern, or used to forward log entries to different writers.

Logger.tag("SYSTEM").trace("Hello World!");
Logger.tag("SYSTEM").debug("Hello World!");
Logger.tag("SYSTEM").info("Hello World!");
Logger.tag("SYSTEM").warn("Hello World!");
Logger.tag("SYSTEM").error("Hello World!");

If a tag is used extensively, an instance of a tagged logger can be held:

TaggedLogger logger = Logger.tag("SYSTEM");

Usually, the static logger is used for issuing untagged log entries. However, it is also possible to obtain an untagged logger instance that works exactly like the static logger:

TaggedLogger logger = Logger.tag(null);

Context Values

tinylog has a thread-based context for enriching log entries with additional values. Stored values are only visible for the thread in which a value has been set, and its child threads. For example, context values can be output as part of the format pattern.

ThreadContext.put("user", name);

Stored values are present, provided they are not explicitly removed. Therefore, the thread context should be cleared before a thread is returned to a thread pool. This is not necessary for threads that are not reused.