Module: Subserver::Logging

Defined in:
lib/subserver/logging.rb

Defined Under Namespace

Classes: Pretty, WithoutTimestamp

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.initialize_logger(log_target = STDOUT) ⇒ Object



53
54
55
56
57
58
59
60
# File 'lib/subserver/logging.rb', line 53

def self.initialize_logger(log_target = STDOUT)
  oldlogger = defined?(@logger) ? @logger : nil
  @logger = Logger.new(log_target)
  @logger.level = Logger::INFO
  @logger.formatter = ENV['DYNO'] ? WithoutTimestamp.new : Pretty.new
  oldlogger.close if oldlogger && !$TESTING # don't want to close testing's STDOUT logging
  @logger
end

.job_hash_context(job_hash) ⇒ Object



33
34
35
36
37
38
39
# File 'lib/subserver/logging.rb', line 33

def self.job_hash_context(job_hash)
  # If we're using a wrapper class, like ActiveJob, use the "wrapped"
  # attribute to expose the underlying thing.
  klass = job_hash['wrapped'] || job_hash["class"]
  bid = job_hash['bid']
  "#{klass} JID-#{job_hash['jid']}#{" BID-#{bid}" if bid}"
end

.loggerObject



62
63
64
# File 'lib/subserver/logging.rb', line 62

def self.logger
  defined?(@logger) ? @logger : initialize_logger
end

.logger=(log) ⇒ Object



66
67
68
# File 'lib/subserver/logging.rb', line 66

def self.logger=(log)
  @logger = (log ? log : Logger.new(File::NULL))
end

.reopen_logsObject

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



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/subserver/logging.rb', line 77

def self.reopen_logs
  to_reopen = []
  append_flags = File::WRONLY | File::APPEND

  ObjectSpace.each_object(File) do |fp|
    begin
      if !fp.closed? && fp.stat.file? && fp.sync && (fp.fcntl(Fcntl::F_GETFL) & append_flags) == append_flags
        to_reopen << fp
      end
    rescue IOError, Errno::EBADF
    end
  end

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

    begin
      b = File.stat(fp.path)
      next if orig_st.ino == b.ino && orig_st.dev == b.dev
    rescue Errno::ENOENT
    end

    begin
      File.open(fp.path, 'a') { |tmpfp| fp.reopen(tmpfp) }
      fp.sync = true
      nr += 1
    rescue IOError, Errno::EBADF
      # not much we can do...
    end
  end
  nr
rescue RuntimeError => ex
  # RuntimeError: ObjectSpace is disabled; each_object will only work with Class, pass -X+O to enable
  puts "Unable to reopen logs: #{ex.message}"
end

.tidObject



29
30
31
# File 'lib/subserver/logging.rb', line 29

def self.tid
  Thread.current['subserver_tid'] ||= (Thread.current.object_id ^ ::Process.pid).to_s(36)
end

.with_context(msg) ⇒ Object



45
46
47
48
49
50
51
# File 'lib/subserver/logging.rb', line 45

def self.with_context(msg)
  Thread.current[:subserver_context] ||= []
  Thread.current[:subserver_context] << msg
  yield
ensure
  Thread.current[:subserver_context].pop
end

.with_job_hash_context(job_hash, &block) ⇒ Object



41
42
43
# File 'lib/subserver/logging.rb', line 41

def self.with_job_hash_context(job_hash, &block)
  with_context(job_hash_context(job_hash), &block)
end

Instance Method Details

#loggerObject



118
119
120
# File 'lib/subserver/logging.rb', line 118

def logger
  Subserver::Logging.logger
end