Roger
Roger

Reputation: 3959

What is the best way to rotate logs for rails application

I have a 1GB slice from slicehost and I have 4 projects running on that box. All 4 applications are ruby on rails application. I was wondering what is the best way to ensure that log files are rotated.

I would prefer to have 4 different log files one for each app rather than having one big log file for all 4 applications.

I am running ubuntu.

I am running passenger.

Upvotes: 16

Views: 9852

Answers (7)

Jinbo
Jinbo

Reputation: 427

ActiveSupport::Logger is the default logger according to the Rails General Configuration.

This will rotate the log files for every 512 megabytes, and keep the latest 50 ones.

config.logger = ActiveSupport::Logger.new(Rails.root.join('log', "#{Rails.env}.log"), 50, 512 * 1024 * 1024)

Upvotes: 0

Joshua Vanner
Joshua Vanner

Reputation: 1

To avoid needing to restart the app, as noted above, you can use the following complete logrotate configuration:

/etc/logrotate.d/rails

<path_to_rails_app>/log/*.log {
  daily
  size 100M
  missingok
  notifempty
  rotate 4
  compress
  delaycompress
  copytruncate
  nodateext
 }

Upvotes: 0

Shyam Habarakada
Shyam Habarakada

Reputation: 15795

We recently had to deal with this, and realized that logrotate is not the best solution. Using it requires that you restart the rails app every time logs are rotated, which seems like an unnecessary performance hit.

A better solution is to override the default rails logger in your application's configuration file(s).

# in config/environments/development.rb
config.logger = Logger.new("#{Rails.env}.log", "daily")

and, then use a script that cleans up files older than n days. You could use logrotate for this part if you like. We use a rake task like,

desc "Cleanup application logs older than 30 days"
task :logs => :environment do
  require 'fileutils'
  Dir.glob("#{Rails.root}/log/*.log.*").
    select{|f| File.mtime(f) < (Time.now - (60*60*24*30)) }. # older than 30 days
    each { |f| 
      puts "Removing #{f}"
      FileUtils.rm f 
    }
end

Upvotes: 5

Duke
Duke

Reputation: 7442

Here's my capistrano installation procedure. I copy this into the deploy file and just run it when I create the server environment for the application, or if there are any changes to the logrotate configuration.

namespace :setup do
  task :install_logrotation, :roles => :app do
    logrotate = <<-BASH 
      #{shared_path}/log/*.log {
        daily
        missingok
        rotate 30
        compress
        size 5M
        delaycompress
        sharedscripts
        postrotate
          #{signal_unicorn("USR1")}
        endscript
      }
    BASH
    tmpfile = "/tmp/#{application}.logrotate"

    put(logrotate, tmpfile)
    run "#{sudo} chown root:root #{tmpfile} && #{sudo} mv -f #{tmpfile} /etc/logrotate.d/#{application}"
  end
end

(Oh, and signal_unicorn just does a "#{sudo} kill -s #{signal} cat #{unicorn_pid}"; USR1 tells it to reload all its files so it will append to the new log file.)

Have fun!

Upvotes: 2

Gabe Kopley
Gabe Kopley

Reputation: 16687

I'd just use the built-in rotation offered by the rails logger:

# in config/application.rb
config.logger = Logger.new(Rails.root.join('log', "#{Rails.env}.log"), 3, 10.megabytes)

This will rotate the log files once they reach 10MB and save the 3 most recent rotated logs.

Upvotes: 6

Jed Smith
Jed Smith

Reputation: 15974

This is meta-programming and whether it should be on ServerFault or SO is debatable.

logrotate, a standard package for a number of operating systems, and you can apt-get install logrotate to get it if you do not already. It can be coerced into rotating whatever logs you want, using whatever schedule you want, and with differing policies a la "gzip 7 days then rm" per-file.

Investigate /etc/logrotate.d.

Upvotes: 3

Bill Turner
Bill Turner

Reputation: 3697

I also use logrotate (you'll have to install via apt-get). Create a new logrotate file in your /etc/logrotate.d/ directory. Here's an example of one of mine:

# for the rails logs
/home/apps/*/shared/log/*log {
  daily
  rotate 14
  notifempty
  missingok
  compress
  sharedscripts
  postrotate
    /usr/bin/touch /home/apps/application1/current/tmp/restart.txt
    /usr/bin/touch /home/apps/application2/current/tmp/restart.txt
  endscript
}
# for the apache logs
/home/apps/logs/*log {
  daily
  rotate 14
  notifempty
  missingok
  compress
  sharedscripts
  postrotate
    /etc/init.d/apache2 restart
  endscript
}

This rotates both rails production.log logs and the apache access/error logs (I run my apps under passenger).

Upvotes: 17

Related Questions