Rotating Rails Production Logs with LogRotate

Keep your log files in check as time goes on and make sure they don't fill up your server's disk space



Overview

One of those things you have to pay attention to on your production Rails servers is the size of the log files that your Rails application produces. I’ll be showing you how to logrotate Rails production logs each day to archive a copy of your logs and then compress them to save space and make them much more manageable.

Your log files can grow fast, especially if you have a lot of traffic. For example, after about 1 month, my log files are 300MB in size. Forget about that for a while and you could run out of disk space on your server and that would be bad.

Configuring Logrotate For Rails Production Logs

You might be surprised at just how easy to setup logrotate Rails logs is. The reason it is so handy is that a bunch of your operating system software is already using it. We just have to plug in our configuration and we’re set!

The first step is to open up /etc/logrotate.conf using vim or nano. Jump to the bottom of the file an add the following block of code. You’ll want to change the first line to match the location where your Rails app is deployed. Mine is under the deploy user’s home directory. Make sure to point to the log directory with the *.log bit on the end so that we rotate all the log files.

/home/deploy/APPNAME/current/log/*.log {
  daily
  missingok
  rotate 7
  compress
  delaycompress
  notifempty
  copytruncate
}

How It Works

This is fantastically easy. Each bit of the configuration does the following:

  • daily – Rotate the log files each day. You can also use weekly or monthly here instead.
  • missingok – If the log file doesn’t exist, ignore it
  • rotate 7 – Only keep 7 days of logs around
  • compress – GZip the log file on rotation
  • delaycompress – Rotate the file one day, then compress it the next day so we can be sure that it won’t interfere with the Rails server
  • notifempty – Don’t rotate the file if the logs are empty
  • copytruncate – Copy the log file and then empties it. This makes sure that the log file Rails is writing to always exists so you won’t get problems because the file does not actually change. If you don’t use this, you would need to restart your Rails application each time.

Running Logrotate

Since we just wrote this configuration, you’ll want to test it.

To run logrotate manually, we just do: sudo /usr/sbin/logrotate -f /etc/logrotate.conf

You’re going to want to run it a second time to make sure the delaycompress option is working and to actually compress the log. Here’s an example of what you’ll see if you ls the log folder after running logrotate twice:

Logrotate Rails 3 Production Log

You can see that the production.log still exists, production.log.1 is a copy of the logs between the first and second run of logrotate, and production.log.2.gz is the 300MB behemoth of a log file that we had before compressed nicely with Gzip. Once we get up to 7 log files, the next time logrotate runs, it will delete the oldest one so that we only have 7 days worth of logs. If you want to keep all the logs around, you can remove the rotate line from the configuration.

Plus, since we just edited the main logrotate.conf file, the cron job will automatically execute the logrotate Rails logs daily!

Setting Up LogRotate Rails Logs Isn’t So Bad After All!

Congratulations, you’re set! I’ve had a few cases where the filesystem filled up on a server before and believe me, that is no fun. This stackoverflow post also has a nice configuration for a weekly rotate that keeps a year’s worth of logs that you might find helpful.



Discussion


Gravatar
Guest on

Would it be good to backup the compressed log files off production server? Can we use backup gem for just that?

Gravatar
Chris Oliver (167,560 XP) on

You could. I rarely have the need for going back to logs over 2 weeks old, so I don't keep them around. If you need to, you can always sync those somewhere.


Gravatar
Marvin Danig (10 XP) on

To handle random spurts of excessive log generation tuck in 'maxsize [size]' option too. Maxsize ensure logrotation both weekly/daily etc. and also out of turn if the logfiles increase beyond a specified [size].

Gravatar
Chris Oliver (167,560 XP) on

Solid!


Gravatar
k092017 Mohammad Ali on

Hello Chris, Is there any way we can rename the file concatenating the date it rotates rather then "1".

Gravatar
Chris Oliver (167,560 XP) on

Looks like you can if you add the "dateext" option. More details here: http://www.thegeekstuff.com...

Gravatar
k092017 Mohammad Ali on

Thanks work perfect!!


Gravatar
Shadman Jamil on

Just want to share, If you want older files in a seperate directory then you may use "olddir" parameter in it; like :

/var/log/news/* {
monthly
rotate 2
olddir /var/log/news/old
missingok
compress
}


Gravatar
Akshay Mohite (10 XP) on

I have been thinking of implementing this since long back - finally implemented after reading this article.
Thanks for summing up this very well.

Gravatar
Drew Verlee on

The logrotate.conf file includes everything in /etc/logrotate.d/ (assuming you have the line `include logrotate.d/`), so i'm curious why you didn't choose to create a file like /logrotate.d/rails-app and include that above loging setup.

Gravatar
Chris Oliver (167,560 XP) on

Oh, I see what you mean. You could do that just as well, no particular reason either way.


Gravatar
Jerome . (100 XP) on

Add `this takes barely 5 minutes to read and complete` ;-). Concise badge. Also, your article should have a date on them (both created and updated); provides added insights as to potential gotchas from framework changes over time.

Gravatar
Jerome . (100 XP) on

er... and testing rotating a second time needs production traffic to run if `notifempty` is set !


Gravatar
Ruslan on

Thank you so much for this post! :)


Gravatar
Naqash Ahmad on

can i set the time for hourly backup manually ??
like at every hour's past 15 minutes ??


Gravatar
Drew Verlee on

why not create a application specific log file and place it in the /etc/logrotate.d folder?

Gravatar
Chris Oliver (167,560 XP) on

It will be application specific, but stays in the app's directory so you can keep it nice and organized next to the code.


Gravatar
Matt Bearman on

Thanks for the great guide.

Just in case anyone else gets this error:

error: skipping "$RAILS_DIR/log/development.log" because parent directory has insecure permissions (It's world writable or writable by group which is not "root") Set "su" directive in config file to tell logrotate which user/group should be used for rotation.

I was able to fix it by instructing the logrotate to run as the same user as my rails app (in my case deploy) instead of running as root:

$RAILS_DIR/log/*.log {
su deploy deploy
daily
missingok
rotate 7
compress
delaycompress
notifempty
copytruncate
}


Gravatar
silverdr on

Does one need to take any special care about race conditions between log rotation and the logger writing to the file being rotated?


Login or create an account to join the conversation.