Module: Sidekiq::Logging

Defined in:
lib/sidekiq/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


49
50
51
52
53
54
55
56
# File 'lib/sidekiq/logging.rb', line 49

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


29
30
31
32
33
34
35
# File 'lib/sidekiq/logging.rb', line 29

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'.freeze] || job_hash["class".freeze]
  bid = job_hash['bid'.freeze]
  "#{klass} JID-#{job_hash['jid'.freeze]}#{" BID-#{bid}" if bid}"
end

.loggerObject


58
59
60
# File 'lib/sidekiq/logging.rb', line 58

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

.logger=(log) ⇒ Object


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

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


73
74
75
76
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
# File 'lib/sidekiq/logging.rb', line 73

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

.with_context(msg) ⇒ Object


41
42
43
44
45
46
47
# File 'lib/sidekiq/logging.rb', line 41

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

.with_job_hash_context(job_hash, &block) ⇒ Object


37
38
39
# File 'lib/sidekiq/logging.rb', line 37

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

Instance Method Details

#loggerObject


114
115
116
# File 'lib/sidekiq/logging.rb', line 114

def logger
  Sidekiq::Logging.logger
end