Logging
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 logging levels: TRACE < DEBUG < INFO < WARNING < ERROR. By default only log entries with the logging level INFO and higher (INFO, WARNING and ERROR) are output and all other log entries (TRACE and DEBUG) are ignored.
The logging methods are named according to the logging levels (e.g. Logger.trace() for TRACE). An exception is WARNING as the associated logging methods have the name warn().
Texts
The probably most common logging method is the simple text output:
TRACE | DEBUG | INFO | WARNING | ERROR |
---|---|---|---|---|
Method signature: Logger.trace(String message) Example: Logger.trace("My first log entry"); |
Method signature: Logger.debug(String message) Example: Logger.debug("My first log entry"); |
Method signature: Logger.info(String message) Example: Logger.info("My first log entry"); |
Method signature: Logger.warn(String message) Example: Logger.warn("My first log entry"); |
Method signature: Logger.error(String message) Example: Logger.error("My first log entry"); |
Objects
For performance reasons, objects shouldn't be logged by calling Object.toString(). tinylog has an innate method to log objects which only uses the toString() method if the log entry should really be output:
TRACE | DEBUG | INFO | WARNING | ERROR |
---|---|---|---|---|
Method signature: Logger.trace(Object obj) Example: Date date = new Date();
Logger.trace(date); |
Method signature: Logger.debug(Object obj) Example: Date date = new Date();
Logger.debug(date); |
Method signature: Logger.info(Object obj) Example: Date date = new Date();
Logger.info(date); |
Method signature: Logger.warn(Object obj) Example: Date date = new Date();
Logger.warn(date); |
Method signature: Logger.error(Object obj) Example: Date date = new Date();
Logger.error(date); |
Texts with arguments
Texts can be assembled at run time by using "{}" placeholders. Due to performance reasons, this method should be used instead of manual concatenation of strings using the "+" operator.
TRACE | DEBUG | INFO | WARNING | ERROR |
---|---|---|---|---|
Method signature: Logger.trace(String message, Object... arguments) Example: Logger.trace("Divide {} by {}", a, b); |
Method signature: Logger.debug(String message, Object... arguments) Example: Logger.debug("Divide {} by {}", a, b); |
Method signature: Logger.info(String message, Object... arguments) Example: Logger.info("Divide {} by {}", a, b); |
Method signature: Logger.warn(String message, Object... arguments) Example: Logger.warn("Divide {} by {}", a, b); |
Method signature: Logger.error(String message, Object... arguments) Example: Logger.error("Divide {} by {}", a, b); |
Exceptions
Usually it makes sense to log thrown exceptions, along with the stack trace, to make it easier to find the error. There is a corresponding logging method for this purpose (the "message" of the exception will be automatically included):
TRACE | DEBUG | INFO | WARNING | ERROR |
---|---|---|---|---|
Method signature: Logger.trace(Throwable exception) Example: try {
int d = a / b;
} catch (ArithmeticException ex) {
Logger.trace(ex);
} |
Method signature: Logger.debug(Throwable exception) Example: try {
int d = a / b;
} catch (ArithmeticException ex) {
Logger.debug(ex);
} |
Method signature: Logger.info(Throwable exception) Example: try {
int d = a / b;
} catch (ArithmeticException ex) {
Logger.info(ex);
} |
Method signature: Logger.warn(Throwable exception) Example: try {
int d = a / b;
} catch (ArithmeticException ex) {
Logger.warn(ex);
} |
Method signature: Logger.error(Throwable exception) Example: try {
int d = a / b;
} catch (ArithmeticException ex) {
Logger.error(ex);
} |
Exceptions with description
Optionally, the "message" of the exception can be amended by a distinct description:
TRACE | DEBUG | INFO | WARNING | ERROR |
---|---|---|---|---|
Method signature: Logger.trace(Throwable exception, String message, Object... arguments) Example: try {
int d = a / b;
} catch (ArithmeticException ex) {
Logger.trace(ex, "Cannot divide {} by {}", a, b);
} |
Method signature: Logger.debug(Throwable exception, String message, Object... arguments) Example: try {
int d = a / b;
} catch (ArithmeticException ex) {
Logger.debug(ex, "Cannot divide {} by {}", a, b);
} |
Method signature: Logger.info(Throwable exception, String message, Object... arguments) Example: try {
int d = a / b;
} catch (ArithmeticException ex) {
Logger.info(ex, "Cannot divide {} by {}", a, b);
} |
Method signature: Logger.warn(Throwable exception, String message, Object... arguments) Example: try {
int d = a / b;
} catch (ArithmeticException ex) {
Logger.warn(ex, "Cannot divide {} by {}", a, b);
} |
Method signature: Logger.error(Throwable exception, String message, Object... arguments) Example: try {
int d = a / b;
} catch (ArithmeticException ex) {
Logger.error(ex, "Cannot divide {} by {}", a, b);
} |
Lambda expressions
Sometimes a message or argument needs to be computed specifically for logging. Since tinylog 1.3, lambda expressions can be used for messages and arguments, which are expensive to compute, as they will be only evaluated if the log entry is really output.
TRACE | DEBUG | INFO | WARNING | ERROR |
---|---|---|---|---|
Method signature: Logger.trace(Supplier<?> supplier)
Logger.trace(String message, Supplier<?>... arguments) Example: Logger.trace(() -> compute());
Logger.trace("Expensive computation: {}", () -> compute()); |
Method signature: Logger.debug(Supplier<?> supplier)
Logger.debug(String message, Supplier<?>... arguments) Example: Logger.debug(() -> compute());
Logger.debug("Expensive computation: {}", () -> compute()); |
Method signature: Logger.info(Supplier<?> supplier)
Logger.info(String message, Supplier<?>... arguments) Example: Logger.info(() -> compute());
Logger.info("Expensive computation: {}", () -> compute()); |
Method signature: Logger.warn(Supplier<?> supplier)
Logger.warn(String message, Supplier<?>... arguments) Example: Logger.warn(() -> compute());
Logger.warn("Expensive computation: {}", () -> compute()); |
Method signature: Logger.error(Supplier<?> supplier)
Logger.error(String message, Supplier<?>... arguments) Example: Logger.error(() -> compute());
Logger.error("Expensive computation: {}", () -> compute()); |
Formatting
Since version 1.2, tinylog supports formatting numbers and choice format. Both work similar to MessageFormat and use also NumberFormat and ChoiceFormat, but the declaration is a bit shorter.
TRACE | DEBUG | INFO | WARNING | ERROR |
---|---|---|---|---|
Example formatting a number: Logger.trace("Income: {0.00} EUR", arg); Example choice format: Logger.trace("There {0#are no files|1#is one file|1<are {} files}", arg); |
Example formatting a number: Logger.debug("Income: {0.00} EUR", arg); Example choice format: Logger.debug("There {0#are no files|1#is one file|1<are {} files}", arg); |
Example formatting a number: Logger.info("Income: {0.00} EUR", arg); Example choice format: Logger.info("There {0#are no files|1#is one file|1<are {} files}", arg); |
Example formatting a number: Logger.warn("Income: {0.00} EUR", arg); Example choice format: Logger.warn("There {0#are no files|1#is one file|1<are {} files}", arg); |
Example formatting a number: Logger.error("Income: {0.00} EUR", arg); Example choice format: Logger.error("There {0#are no files|1#is one file|1<are {} files}", arg); |
Logging Context
Mapped Diagnostic Context (MDC) is in tinylog available as logging context and allows thread-based enrichment of log entries with additional data. Logging context requires tinylog 1.1 or later.
Method signature: LoggingContext.put(String key, Object value)) Example: LoggingContext.put("user", name); |
Values can be set for a thread and are active as long as they are not explicitly removed. Set values will be used by all log entries, which are triggered in the same thread as well as in all child threads. A child thread automatically pass values on to it's child threads, but can also locally overwrite values or remove them. If a thread should be returned to a thread pool, the logging context should be cleared before.