2010年12月6日月曜日

Rake タスクのログをとる

Rake を使ってタスク管理をしていると、タスクの実行や終了のログを(例えば Log4r なんかを使って)ファイルに取りたいことがある。いままでは

task :foo do |t|
  $log.info "#{t} start"

  puts :foo

  $log.info "#{t} end"
end

として、タスクの最初と最後にログコマンドをタスクごとに書いていた。Rake に詳しければもっと楽なやり方あるよな〜と思いつつ、2, 3 年は羊のようにログコマンドを書いてきた。

昨日流石にいやになった。

一念発起 rake.rb をつまみ読みし、エレガントかどうかは別にともかく目的を果たせる方法を見つけた。Rakefile を以下のように書くと Log4r でタスクの開始/終了の記録を取る事ができる:

require 'log4r'

$log = Log4r::Logger.new ''
$log.level = Log4r::INFO
log_file = 'rake.log'
formatter = Log4r::PatternFormatter.new pattern:'%d [%l]: %M', date: '%Y/%m/%d %H:%M:%S'
$log.outputters = Log4r::FileOutputter.new 'rake', {
  :filename => log_file,
  :formatter => formatter}

task :foo do 
  puts "hello foo"
end

task :hoge do
  puts "hello hoge"
end

########## Rakefile の最後に以下を加える #########
module Rake
  class Task
    def log
      actions.unshift Proc.new {$log.info "#{@name} start"}
      actions.push Proc.new {$log.info "#{@name} end"}
    end
  end
end

Rake.application.tasks.each {|t| t.log}

以下のようなログが取れる。

2010-12-06 15:43:50 [INFO]: hoge start
2010-12-06 15:43:50 [INFO]: hoge end
2010-12-06 15:43:50 [INFO]: foo start
2010-12-06 15:43:50 [INFO]: foo end

Rake::Task#log はタスクオブジェクトのインスタンス変数(配列)@actions の先頭と最後にログコマンドを紛れ込ませるメソッド。で、

Rake.application.task.each {|t| t.log} 

をすると、それまでに定義されてきたタスク全てに対してこの log メソッドを送り、ログコマンドを注入できる(上記のように Rakefile の最後に書けば全部のタスクのログを取る事になる)。

これでタスクごとに2行も悶々と書き足すことから解放された(動的タスクには使えないが、まぁいいか)。2,3 年も我慢せず、もっと早く調べればよかった。

ちゃんと rake.rb をよんでないので、わざわざ @actions とかインスタンス配列を用意している理由がわからない。うまくいかないケースがある予感もするのだけどひとまずは気にしないことに...

0 件のコメント:

コメントを投稿