GitHub

Configuration

You can edit this page on GitHub

Typically, tinylog 2 is configured via a properties file. The properties file should be located directly in the resource directory under the name tinylog.properties, so that tinylog can find the properties file automatically. In Maven or Gradle projects, the resource directory is usually src/main/resources. Additionally, a second properties file can be placed in src/test/resources to enable another configuration for tests. Plain IDE projects without any build tools usually have no dedicated resource directory. In this case, tinylog.properties can be placed directly in the source directory. For example, in plain Eclipse projects the source directory is usually just src.

Example of a simple properties file for writing all log entries (with the severity level info and higher) to log.txt:

writer       = file
writer.file  = log.txt
writer.level = info

If the properties file has a name other than tinylog.properties, or is stored somewhere else in the classpath or on the file system, the path can be passed via the system property tinylog.configuration.

Example:

java -jar -Dtinylog.configuration=/tinylog/configuration.properties application.jar

It is also possible to override properties that are set in tinylog.properties, or add additional properties via system properties. The property names for system properties are the same as in tinylog.properties, but require a "tinylog." prefix.

Example of overriding the severity level:

java -jar -Dtinylog.writer.level=debug application.jar

tinylog can also be configured programmatically by using the class Configuration. Individual properties can be set or overridden via Configuration.set(String key, String value). A complete configuration can also be passed as a map via Configuration.replace(Map<String, String> configuration). All properties that have already been set are overwritten. The configuration of tinylog is immutable, and as soon as the first log entry is issued, further configuration changes will be ignored.

Automatic Shutdown

By default, tinylog shuts down automatically together with the application. tinylog registers a shutdown hook that closes all writers and releases all resources. If an application also uses shutdown hooks and issues log entries in these shutdown hooks, automatic shutdown has to be disabled, and tinylog must be shut down manually.

Example:

autoshutdown = false # optional, default: true
Runtime.getRuntime().addShutdownHook(new Thread() {
    @Override
    public void run() {
        ProviderRegistry.getLoggingProvider().shutdown();
    }
});

Environment Variables

The values of properties can contain placeholders for environment variables. These placeholders are automatically resolved at runtime. The format of placeholders for environment variables is ${variable}.

Example:

writer      = file
writer.file = ${HOME}/log.txt

Format Pattern

A format pattern describes the format for outputting log entries. The default format pattern for the console writer and all file based writers is {date} [{thread}] {class}.{method}()\n{level}: {message}.

Placeholder Description
{closing-curly-bracket} Closing curly bracket: "{"
{class} Fully-qualified name of the class in which the log entry was issued
{class-name} Name of the class (without package) in which the log entry was issued
{context: key} Value from thread-based context ("key" should be replaced by a real key)
{date} Date and time of issuing the log entry. Optionally there can be a custom date format pattern such as "{date: HH:mm:ss.SSS}". The date format pattern is compatible with SimpleDateFormat and on Java 9 (or higher), also with DateTimeFormatter that supports milliseconds and nanoseconds. The default date format pattern is "yyyy-MM-dd HH:mm:ss".
{exception} Logged exception including stack trace
{file} Filename of the source file in which the log entry was issued
{level} Severity level of the log entry
{line} Line number of the source file in which the log entry was issued
{message} Logged message including exception and stack trace if present
{message-only} Only logged message without exception and stack trace
{method} Name of the method in which the log entry was issued
{opening-curly-bracket} Opening curly bracket: "}"
{package} Package in which the log entry was issued
{pid} Process ID of the application
{tag} Tag of log entry. By default, nothing will be output for untagged log entries. However, a default text can be output if explicitly configured, as in {tag: none} for example.
{thread} Name of the thread in which the log entry was issued
{thread-id} ID of the thread in which the log entry was issued

Example:

writer        = console
writer.format = {level}: {class}.{method}()\t{message}

Optionally, the minimum size of a placeholder or a group of placeholders can be defined. For example, this is useful to format placeholders as columns.

Example:

writer        = console
writer.format = {{level}:|min-size=8} {message}

The indentation depth of new lines of a multi-line message is configurable. Each line will be indented by the defined number of spaces. Additionally, each tab at the beginning of a line will be replaced by the defined number of spaces.

Example:

writer        = console
writer.format = {level}: {message|indent=4}
Logger.info("Multiple lines\nFirst line\n\tLine with tabs\nAnother line");
INFO: Multiple lines
    First line
        Line with tabs
    Another line

By default, stack trace elements of an exception are indented by a tab. The exception class name and description are not indented. However, the indentation depth, defined above, works in exactly the same way for exceptions as for multi-line text messages.

Logger.error(exception);
ERROR: java.lang.RuntimeException: java.io.FileNotFoundException: file.log
        at Application.run(Application.java:14)
        at Application.main(Application.java:10)
    Caused by: java.io.FileNotFoundException: file.log
        at Application.main(Application.java:9)

Locale

The locale is primarily used for formatting numbers and dates. If not explicitly set, the default locale of the Java virtual machine is used.

Example:

locale = en_US

Severity Level

tinylog supports five different severity levels: trace, debug, info, warn, and error. Log entries with the severity level trace are the least important, and those with error the most important. For example, if info is set as severity level, only log entries with the severity level info and above (info, warn, and error) will be output, while all other log entries (trace and debug) will be ignored. By default, the severity level trace is enabled. This means that log entries with any severity level are output. The value off disables all kinds of logging.

Example:

level = info # optional, default: trace

If required, particular severity levels for packages or classes can be set. This overrides the default severity level.

Example:

level@org.tinylog = debug

If multiple writers are used, it is possible to define particular severity levels for them. In this case, these writers will only output log entries with the defined severity level or higher.

Example:

writer1       = console
writer1.level = debug

writer2       = file
writer2.file  = log.txt
writer2.level = info

System Properties

The values of properties can contain placeholders for system properties. These placeholders will be resolved at runtime automatically. The format of placeholders for system properties is #{key}.

Example:

writer        = console
writer.format = #{user.name}: {message}

Tags

Writers can be bound to a tag for only outputting log entries with a defined tag. If a writer is bound to a tag, all untagged log entries (and log entries with other tags) will be ignored by this writer.

Example:

writer     = console
writer.tag = SYSTEM
Logger.tag("SYSTEM").info("Hello World!"); // Output
Logger.info("Hello World!");               // Ignored

A minus "-" can be used as placeholder for untagged log entries.

Example:

writer     = console
writer.tag = -
Logger.tag("SYSTEM").info("Hello World!"); // Ignored
Logger.info("Hello World!");               // Output

Writers

A writer outputs issued log entries (for example to a log file or to the console). By default, all log entries will be written to the console if no other writer is configured. Out of the box, tinylog contains six different writers.

Writer Property Value Description
Console Writer console Writes log entries to the console
File Writer file Writes log entries to a defined file
Jdbc Writer jdbc Inserts log entries into a SQL database
Logcat Writer logcat Forwards log entries to Android’s native logging system
Rolling File Writer rolling file Like File Writer but uses multiple files by rotating them
Shared File Writer shared file Like File Writer but supports writing of multiple instances of an application to the same file

Example:

writer        = console
writer.level  = info
writer.format = {level}: {class}.{method}() {message}

Multiple writers can be used in parallel. For example, it is possible to write log entries to the console and to a log file. Each writer must be defined via a unique property that starts with "writer". These can be meaningful names, such as writerConsole or writerFile, or simply consecutively numbered names.

Example:

writer1       = console
writer1.level = debug

writer2       = file
writer2.level = info
writer2.file  = log.txt

The definition of format patterns and severity levels is optional. If not defined, default values will be used.

Console Writer

The console writer is the default writer of tinylog, and writes log entries to the console. By default, warnings and errors are written to the standard error stream (System.err), and all other severity levels to the standard output stream (System.out). The streams are configurable, and it is possible to output all log entries to the same stream, regardless of their severity level.

Example:

writer        = console
writer.level  = debug              # optional
writer.format = {level}: {message} # optional
writer.stream = err                # "err" or "out", optional

File Writer

The file writer writes log entries to a defined file. The only required property is writer.file for the absolute or relative path to a log file. Optionally, the output can be buffered. In this case, new log entries are written to a buffer and output to the log file, together with a delay. This will be significantly faster, especially in connection with activation of the writing thread.

By default, an existing log file is overwritten at startup. However, the append mode can be enabled to have an endless log file that is continued at startup.

The file writer uses the standard charset of the Java virtual machine by default. However, it is possible to configure any charset that is supported by the current Java virtual machine. Since Java 7, the charsets US-ASCII, ISO-8859-1, UTF-8, and UTF-16 are guaranteed to be available on every implementation of the Java platform.

Example:

writer          = file
writer.level    = debug              # optional
writer.format   = {level}: {message} # optional
writer.file     = log.txt            # required, absolute or relative path
writer.charset  = UTF-8              # optional
writer.append   = true               # optional, default: false
writer.buffered = true               # optional, default: false

JDBC Writer

The JDBC writer inserts log entries into a defined table of an SQL database or a Java EE data source. For establishing the connection, the properties writer.url for the connection URL, and writer.table for the name of the database table, are required. Connection URLs for Java EE data sources and JDBC can be configured in the same way. tinylog will detect (on the basis of the URL) if it is a data source or JDBC. Username and password must not be configured for Java EE data sources in tinylog, as they are usually already defined in the data source itself.

The fields of a database table have to be mapped to format patterns like writer.field.LEVEL = {level} for example. The property name always starts with writer.field and ends with the field name in the database table. In the previous example, the field name would be LEVEL. The property value can be a usual format pattern. Complex format patterns with multiple placeholders such as writer.field.MESSAGE = {class}.{method}() {message} are supported. If a format pattern contains only one placeholder, the curly brackets are optional. For example, writer.field.LEVEL = {level} and writer.field.LEVEL = level are identical.

Most placeholders are resolved to a string, and expect a textual SQL type such as VARCHAR or CLOB for the mapped field. Exceptions are {date} which expects TIMESTAMP or DATETIME and {line}, {pid}, and {thread-id} which expect a numeric SQL type, such as NUMBER, INT, or BIGINT.

Optionally, inserts can be executed in a batch mode. In this case, new log entries are held in a buffer and are inserted into the table together with a delay. This will be significantly faster, especially in connection with activation of the writing thread.

Prepared statements are used to avoid security vulnerability by SQL injections. Automatically reestablishing database connections in case of connection losses is supported, but has to be activated explicitly.

Example for JDBC:

writer                 = jdbc
writer.level           = debug                               # optional
writer.url             = jdbc:mysql://localhost:3306/example # required
writer.table           = LOG_ENTRIES                         # required
writer.user            = jeffrey                             # if required by database
writer.password        = Ya3D_frgTr                          # if required by database
writer.reconnect       = true                                # optional, default: false
writer.batch           = true                                # optional, default: false
writer.field.TIMESTAMP = date                                # short for {date}
writer.field.LEVEL     = level                               # short for {level}
writer.field.MESSAGE   = {class}.{method}() {message}

Example for Java EE data source:

writer                 = jdbc
writer.level           = debug                               # optional
writer.url             = java:comp/env/jdbc/ExampleDS        # required
writer.table           = LOG_ENTRIES                         # required
writer.reconnect       = true                                # optional, default: false
writer.batch           = true                                # optional, default: false
writer.field.TIMESTAMP = date                                # short for {date}
writer.field.LEVEL     = level                               # short for {level}
writer.field.MESSAGE   = {class}.{method}() {message}

Logcat Writer

The logcat writer forwards log entries to Android’s native logging system (known as logcat). This writer is only available on Android. By default, tinylog derives the tag automatically from the class name. The simple class name without package is used and stripped to 23 characters if too long. This is because 23 characters are the maximum supported length for tags by logcat. The tag is configurable, and any format pattern can be used.

Example:

writer       = logcat
writer.level = trace  # optional
writer.tag   = {tag}  # optional, default: {class-name}

Rolling File Writer

The rolling file writer writes log entries to rolling log files. The log file can be defined as a pattern that will be resolved at runtime. For example, in the file pattern writer.file = log.{count}.txt, the placeholder {count} is replaced by a consecutive number. The name of the first log file is log.0.txt, the second log file is log.1.txt, and so on. Besides {count} there are {date} for the current date and time and {pid} for the process ID.

Placeholder Description
{count} Consecutive number, starting with "0"
{date} Current date and time. Optionally there can be a custom date format pattern such as "{date: HH:mm:ss.SSS}". The date format pattern is compatible with SimpleDateFormat and on Java 9 (or higher), also with DateTimeFormatter that supports milliseconds and nanoseconds. The default date format pattern is "yyyy-MM-dd_HH-mm-ss".
{pid} Process ID of the application

Multiple placeholders can be combined in a file pattern, for example in writer.file = /{date:yyyy}/{date:MM}/log-{pid}.{count}. Here, the log files are created in a directory with the current year in a subdirectory with the current month. The log file name contains the process ID of the application. Log files with the same process ID are numbered consecutively for each process ID, starting with "0".

When a new log file has to be started, it can be defined via policies. This can happen daily, after a specified file size and/or at startup. Multiple policies can be combined comma-separated with each other. The default is at startup.

Policies Property Value Description
Daily Policy daily Starts a new log file every day. The time can be defined in 24-hour clock time format, such as: daily: 03:00. The default is at midnight (00:00).
Size Policy size Starts a new log file when the current file exceeds the defined maximum file size. The definition of the file size is mandatory. For example, size: 10mb would start a new log file when the current exceeds 10 MB.
Startup Policy startup Starts a new log file at every startup of the application.

The maximum number of log files that should be kept can be configured via the property writer.backups. When the total number of log files exceed the configured number of backups, old log files will be deleted. If nothing has been configured, no log files will be deleted.

Optionally, the output can be buffered. In this case, new log entries are written to a buffer and output to the log file, together with a delay. This will be significantly faster, especially in connection with activation of the writing thread.

The rolling file writer uses the standard charset of the Java virtual machine by default. However, it is possible to configure any charset that is supported by the current Java virtual machine. Since Java 7, the charsets US-ASCII, ISO-8859-1, UTF-8, and UTF-16 are guaranteed to be available on every implementation of the Java platform.

Example:

writer          = rolling file
writer.level    = debug                 # optional
writer.format   = {level}: {message}    # optional
writer.file     = log_{count}.txt       # required, absolute or relative path with placeholders
writer.charset  = UTF-8                 # optional
writer.buffered = true                  # optional, default: false
writer.policies = startup, daily: 03:00 # optional, default: startup
writer.backups  = 100                   # optional

The rolling file writer can also be used if several instances of an application should write to log files on the same machine. In this case, it is strongly recommended to include the process ID placeholder {pid} in the file path pattern to avoid any concurrent access to the same log files. The process ID placeholder ensures that each process has its own log file.

Shared File Writer

The shared file writer writes log entries to a defined file, and allows multiple instances of an application to write to the same log file simultaneously, without overriding each other. The only required property is writer.file for the absolute or relative path to the log file.

By default, an already existing log file is overwritten at startup of the first instance of the application. All later instances share the log file with the first instance, without overwriting the file. The append mode can be enabled to have an endless log file that will always be continued, and never overwritten at startup of the first instance.

The shared file writer uses the standard charset of the Java virtual machine by default. However, it is possible to configure any charset that is supported by the current Java virtual machine. Since Java 7, the charsets US-ASCII, ISO-8859-1, UTF-8, and UTF-16 are guaranteed to be available on every implementation of the Java platform.

Example:

writer          = shared file
writer.level    = debug              # optional
writer.format   = {level}: {message} # optional
writer.file     = log.txt            # required, absolute or relative path
writer.charset  = UTF-8              # optional
writer.append   = true               # optional, default: false

Writing Thread

Writers can be executed in a separate thread. The advantage is that the application itself will not be blocked by slow IO operations. The writing thread runs with low priority and shuts down automatically, together with the application.

Example:

writingthread = true # optional, default: false