Rails でバッチ処理してみる 2

先日、Rails でバッチ処理してみるを書いたのですがバッチ実行関連で、ログ出力を中心に分かったことがあったので、備忘録的にまとめておきます。

参考

バッチ実行のログってどうやって扱うのか?

Rails でバッチ処理してみるの記事のように実装を行うと、
puts は rails runner を使って実行すれば表示されるので確認できます。
バッチ実行なら表示されないので何も残らず、何もわからないです。

lib/script/record_add.rb
1
2
3
4
5
6
7
8
9
10
module Script
class RecordAdd
def self.add
puts "アカウントを追加します。" #例えばこんなputs
Account.create()
end
end
end

Script::RecordAdd.add()

何を実行したのかであるとか証跡を取りたいこともあるでしょうから、ログを残せるように試みます。

とりあえずログが残せるようにします。

github - javan/wheneverを導入していることを前提として以下は進みます。

config/schedule.rb の編集

ログの書き出し先を定義します。

config/schedule.rb(一旦作成)
1
2
3
4
5
set :output, "log/cron_log.log"

every 1.minute do
runner "lib/script/record_add.rb",:environment => "development"
end

以上の書き方でも、動くことは動くのですが crontab に展開した時も相対パスになっており、危険を感じました。
絶対パスで書くのが直球なのですが、調べると、Rails.root を使う方法を見つけました。

記事を参考に、修正を行いました。

config/schedule.rb(修正)
1
2
3
4
5
6
7
8
9
require File.expand_path(File.dirname(__FILE__) + "/environment")
rails_env = ENV['RAILS_ENV'] || :development
set :environment, rails_env

set :output, "#{Rails.root}/log/cron_log.log"

every 1.minute do
runner "lib/script/record_add.rb",:environment => "development"
end

以上の通り修正して、RAILS_ENV=development bundle exec whenever --update-crontabを実行することで更新します。
実行すると log/cron_log.log が作成されます。
1 分ごとに実行するので、実行するタスクの中の puts(今回は”アカウントを追加します。”)が log/cron_log.log に追記され始めます。

ほっておくと永遠とログが増えます。
危険です。ディスク枯渇します。怖い。
対策します。


ログの最大サイズを定義する。

whenever ではログファイルのサイズを管理することはできないことがわかりました。
対応方法として、AcriveSupport::Logger を使うようです。
やってみます。

方針

ログローテートを行います(この単語は今回ログのこと調べ始めてから知りました。)。
テストなので 10 バイト超えたら、ファイルを切り替えて最大 3 ファイル、古いものから削除という形にします。

AcriveSupport::Logger でログ出力

lib/script/record_add.rb を編集します。

lib/script/record_add.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
module Script
class RecordAdd
def self.add
# 10 バイト超えたら、ファイルを切り替えて最大 3 ファイル、古いものから削除
logger = ActiveSupport::Logger.new( "#{Rails.root}/log/cron_log.log", 3, 10.bytes)
# ログを出力
logger.info "アカウントを追加します。"
Account.create()
end
end
end

Script::RecordAdd.add()

確認

lib/script/record_add.rb を書き換えているだけなので、crontab の更新が必須ではありません。
任意に実行してもらえばよいです。

待っていると、log/に log/cron_log.log cron_log.log.0 cron_log.log.1 とファイルが増えていきます。
最大のファイルサイズが 10 バイトなので 1 回のログ出力ごとにファイルが切り替えされます。


今回はログ出力について以前の記事の続編でした。
Rails のログはシステムで出力されるものしか知らなかったのです。
今回の AcriveSupport::Logger を使うとバッチ実行を問わず、ほしい部分を切り出して使えると感じました。
puts でデバッグから解放されそうです。

ではでは