Logging to a file in Spring Boot

How to write log messages to a file with Spring Boot

Hey, why isn’t my Spring Boot application writing logs to a file?

You probably discovered this when you first started learning Spring Boot. You looked for a log file, but it wasn’t there. All the logs were just spewed out to the console, with nothing persisted. How useful is that?

So you re-ran your app, and then copied the logs somehow, and pasted them into Notepad so you could explore them.

Shouldn’t Spring Boot just write logs to a file by default?

The answer to that question can be partially explained by the fact that Spring Boot is designed to be run in environments at large scale. At scale, managing and maintaining log files starts to become a headache.

Once you start running even just dozens of Spring Boot apps in your data centre, it’s going to become difficult to rotate and search through hundreds of log files.

Having said that, not everyone is running at Netflix-scale, nor is everyone using bleeding-edge container platforms like Kubernetes. Sometimes you just want a good old log file which you can write to, and use to check your app is running okay.

So how to you get Spring Boot to write logs to a file?

In this article I’m going to cover the quickest way to do this, with minimum configuration. This means using Spring’s preferred logging framework, Logback.

Understanding Spring Boot’s logging defaults

As with most features in Spring Boot, logging is configured in an opinionated manner. This means that there is a “standard” Spring Boot way to do things, which is automatically implemented for you, unless you choose otherwise.

(At times I find this to be on the verge of sorcery.)

A new, freshly-generated Spring Boot application doesn’t come with any explicit logging configuration, and it will use Logback by default, the logging framework for Java, and the successor to the old log4j.

Logging is configured automatically when you add the spring-boot-starter-web dependency to your project.

You can customise the default logging configuration by:

  • Setting some specific Spring Boot properties (these can go in your application.properties, application.yml or as environment variables)

  • Adding a logback.xml onto the classpath, which Spring Boot will detect and use to configure Logback

  • Adding a logback-spring.xml onto the classpath, which Spring Boot will detect and use to configure Logback

Writing to a log file with Spring Boot

To make Spring Boot write to a log file, you can set the logging.file.path property in your application.properties file:

logging.file.path=.             # write logs to the current directory
logging.file.path=/home/logs    # write logs to /home/logs
logging.file.path=/mnt/logdir   # write logs to /mnt/logdir
# Or set logging.path if you're using Spring Boot 1.x

With this configuration, Spring Boot will write to the console and also to a log file called spring.log, at the path you specify.

If you want to choose your own log filename instead of spring.log, then you can set the property logging.file.name, in your application.properties, e.g.:

logging.file.name=myapp.log
logging.file.name=eggs.log
logging.file.name=fun_application.txt
# Or set logging.file if you're using Spring Boot 1.x

Configuring Spring Boot logging using environment variables

Just like most Spring Boot properties, you can set these properties using environment variables instead, if you like.

Just convert the property to upper-case, and change dots to underscores. So you can use environment variables like this:

# to change the log file path
LOGGING_FILE_PATH=/path/to/mylogs
# to change the log filename
LOGGING_FILE_NAME=myapp.log

WAIT BUT WHY

How do these tricks work? I think with Spring Boot it’s nice to understand the “why” sometimes.

We can see there’s a comment in the source code of LogFile which explains the main behaviour:

/**
 * A reference to a log output file. Log output files are specified using
 * {@code logging.file} or {@code logging.path} {@link Environment} properties. If the
 * {@code logging.file} property is not specified {@code "spring.log"} will be written in
 * the {@code logging.path} directory.
 */

And how is this achieved with Spring magic? Looking around the source code, I found these relevant clues (hunted down in Spring Boot v2.2.4):

  • spring-boot-starter-web includes the dependency spring-boot-starter-logging, which includes logback as a dependency. This means that Logback should appear on the classpath.

  • The abstract class LoggingSystem has some code which detects and return the logging system which is currently in use, by checking which classes are present in the classloader.

  • There’s an implementation of LoggingSystem, called LogbackLoggingSystem, which is basically a specialised implementation for Logback.

  • LogbackLoggingSystem uses the class DefaultLogbackConfiguration, which defines things like the standard configuration file locations for Logback (logback.xml, etc.)

  • Inside DefaultLogbackConfiguration, Spring Boot does some programmatic auto-configuration of Logback for us, so we don’t need to configure it manually.

Magic? Perhaps. Configurable, certainly. :-)

Leave a Comment

You can use Markdown in your comment. To write code, indent lines by 4 spaces.