読者です 読者をやめる 読者になる 読者になる

こしごぇ(B)

旧:http://d.hatena.ne.jp/koshigoeb/

delayed_job の logrotate を使ったログローテーションって

どうやるものなんだろう。

  • logrotate を使わず TwP/logging の daily ローテーションもありだけど
  • logrotate の copytruncate は最終手段
  • delayed_job を Capistrano でオプション付きで起動してるので、logrotate の postscript で restart や start する場合は、同じオプションの指定が必要(だと思う)

Unicorn::Util.reopen_logs を使って USR1 シグナルでログのリオープンできるようにしたら良いのかなと思ったけど、どうも上手くいかない模様。

どうやら、delayed_job の Delayed::Worker.after_fork にて "a+" モードでリオープンしているため、Unicorn::Util.is_log? で許容するモードにマッチせずに対象外とされる模様。 (一律で a+ モードで開き直すという挙動は、それはそれで大丈夫なのかな?)

    def self.before_fork
      unless @files_to_reopen
        @files_to_reopen = []
        ObjectSpace.each_object(File) do |file|
          @files_to_reopen << file unless file.closed?
        end
      end

      backend.before_fork
    end

    def self.after_fork
      # Re-open file handles
      @files_to_reopen.each do |file|
        begin
          file.reopen file.path, 'a+'
          file.sync = true
        rescue ::Exception # rubocop:disable HandleExceptions, RescueException
        end
      end
      backend.after_fork
    end

んー、どうするのがいいんだろうか。

こんな感じはありだろうか?

class Delayed::Worker
  module TrapUsr1ForReopenLogs
    def start
      ObjectSpace.each_object(File) do |file|
        begin
          next unless file.path.ends_with?('.log')
          file.reopen file.path, 'a'
          file.sync = true
        rescue ::Exception # rubocop:disable HandleExceptions, RescueException
        end
      end

      trap('USR1') do
        Thread.new { say 'Reopen logs...' }
        Unicorn::Util.reopen_logs
      end
      super
    end
  end
  prepend Delayed::Worker::TrapUsr1ForReopenLogs
end