Module: Resque::Pool::Logging

Extended by:
Logging
Included in:
Resque::Pool, Resque::Pool, CLI, CLI, Killer, Logging
Defined in:
lib/resque/pool/logging.rb

Constant Summary collapse

PROCLINE_PREFIX =
"resque-pool-master"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.is_log?(fp) ⇒ Boolean

Used by reopen_logs, borrowed from Unicorn...

Returns:

  • (Boolean)


96
97
98
99
100
101
102
103
104
105
# File 'lib/resque/pool/logging.rb', line 96

def self.is_log?(fp)
  append_flags = File::WRONLY | File::APPEND

  ! fp.closed? &&
    fp.stat.file? &&
    fp.sync &&
    (fp.fcntl(Fcntl::F_GETFL) & append_flags) == append_flags
  rescue IOError, Errno::EBADF
    false
end

.reopen_logs!Object

This reopens ALL logfiles in the process that have been rotated using logrotate(8) (without copytruncate) or similar tools. A File object is considered for reopening if it is:

1) opened with the O_APPEND and O_WRONLY flags
2) the current open file handle does not match its original open path
3) unbuffered (as far as userspace buffering goes, not O_SYNC)

Returns the number of files reopened

This was mostly copied from Unicorn 4.8.2 to simplify reopening logs in the same way that Unicorn does. Original comments and explanations are left intact.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/resque/pool/logging.rb', line 17

def self.reopen_logs!
  to_reopen      = [ ]
  reopened_count = 0

  ObjectSpace.each_object(File) { |fp| is_log?(fp) and to_reopen << fp }
  log "Flushing #{to_reopen.length} logs"

  to_reopen.each do |fp|
    orig_st = begin
      fp.stat
    rescue IOError, Errno::EBADF # race
      next
    end

    begin
      b = File.stat(fp.path)
      # Skip if reopening wouldn't do anything
      next if orig_st.ino == b.ino && orig_st.dev == b.dev
    rescue Errno::ENOENT
    end

    begin
      fp.reopen(fp.path,
                mode: "a",
                external_encoding: fp.external_encoding,
                internal_encoding: fp.internal_encoding)

      fp.sync = true
      fp.flush # IO#sync=true may not implicitly flush
      new_st = fp.stat

      # this should only happen in the master:
      if orig_st.uid != new_st.uid || orig_st.gid != new_st.gid
        fp.chown(orig_st.uid, orig_st.gid)
      end

      log "Reopened logfile: #{fp.path}"
      reopened_count += 1
    rescue IOError, Errno::EBADF
      # not much we can do...
    end
  end

  reopened_count
end

Instance Method Details

#appObject

Include optional app name in procline



87
88
89
90
91
# File 'lib/resque/pool/logging.rb', line 87

def app
  app_name   = self.respond_to?(:app_name)       && self.app_name
  app_name ||= self.class.respond_to?(:app_name) && self.class.app_name
  app_name ? "[#{app_name}]" : ""
end

#log(message) ⇒ Object

TODO: make this use an actual logger



73
74
75
76
77
# File 'lib/resque/pool/logging.rb', line 73

def log(message)
  return if $skip_logging
  puts "resque-pool-manager#{app}[#{Process.pid}]: #{message}"
  #$stdout.fsync
end

#log_worker(message) ⇒ Object

TODO: make this use an actual logger



80
81
82
83
84
# File 'lib/resque/pool/logging.rb', line 80

def log_worker(message)
  return if $skip_logging
  puts "resque-pool-worker#{app}[#{Process.pid}]: #{message}"
  #$stdout.fsync
end

#procline(string) ⇒ Object

Given a string, sets the procline ($0) Procline is always in the format of:

resque-pool-master: STRING


68
69
70
# File 'lib/resque/pool/logging.rb', line 68

def procline(string)
  $0 = "#{PROCLINE_PREFIX}#{app}: #{string}"
end