A common requirement in web applications is to support a rolling log system, so that log files are rolled over on a schedule and archived after a certain point. Grails 3 uses Logback (considered the successor to log4j) as its logging library, and it’s quite simple to configure a rolling appender using Logback’s Groovy config format.
Grails includes a default Logback configuration at
grails-app/conf/logback.groovy. By default (as of Grails 3.2.1), this file (which follows the standard Logback groovy config format) configures a single appender, an instance of
STDOUT, and conditionally (when in development mode) an instance of
FULL_STACKTRACE. These may then be used by logger instances, which can target specific package names and log levels, and write to one or more appenders. You have access to the Grails
Environment, so you can configure different combinations of appenders for development and production.
logback.groovy file in Grails 3.2.1 is shown below.
Let’s add an instance of
RollingFileAppender for our production environment. Let’s say we want to split out our log files by day, and keep 30 days worth of log files around (deleting any older ones). In addition, we don’t have unlimited hard drive space, so we’ll also set a file size cap so that the total disk space used by our logs never exceeds 2GB.
Here’s our new appender:
An instance of
RollingFileAppender needs two “policies”, a
rollingPolicy (to define how to perform the rollover), and a
triggerPolicy (which specifies when the rollover should occur). In this case, our
TimeBasedRollingPolicy, which happens to implement the
TriggeringPolicy interface and therefore satisfies both policy requirements.
TimeBasedRollingPolicy is one of the most common rolling policies, and it will meet the majority of rolling log requirements.
TimeBasedRollingPolicy gets both it’s rolling behavior (creating a new log file with the current date/time in the file name) and it’s triggering behavior (rollover will occur based on the specified timestamp pattern) from the
The trigger policy is the most interesting part here - it takes an approach that bases the rollover occurrence on how specific you define the timestamp in the
fileNamePattern. So if you specify down to the month, rollover will occur each month. Specify a pattern down to the day, and it will occur daily). It’s easier to understand when you see it in action, so here’s some example patterns taken from Logback’s documentation:
Note that in the above examples we are configuring the timestamp in the filename of the log files. We can also use the timestamp to create a file directory structure, like this example:
Finally, adding a
gz file extension to our
fileNamePattern will apply the selected compression to the rolled-over log files:
Going back to our previous example, we’re setting a couple more properties on our
totalSizeCap. These are pretty simple to understand;
maxHistory sets the upper limit on how many log files to preserve (when the max is reached the oldest file is deleted), and
totalSizeCap sets a cap on how much disk space our log files are allowed to use (again, when the cap is reached the oldest files are deleted). There are other useful options you can set here, see the
TimeBasedRollingPolicy documentation for a full list and explanation.
Finally, let’s specify that we want our new
RollingFileAppender to be used in production mode only, while keeping the default
ConsoleAppender for development mode.
And with that, we have our rolling log system. Enjoy!
- Logback documentions: http://logback.qos.ch/documentation.html
- Logback Groovy config (from the official docs): http://logback.qos.ch/manual/groovy.html
- DZone - Logback Configuration Using Groovy: https://dzone.com/articles/logback-configuration-using-groovy