Class: SidekiqLongRunningJobLogger
- Inherits:
-
Object
- Object
- SidekiqLongRunningJobLogger
- Defined in:
- lib/sidekiq_long_running_job_logger.rb
Instance Attribute Summary collapse
-
#thread ⇒ Object
readonly
Returns the value of attribute thread.
Instance Method Summary collapse
-
#initialize(stuck_sidekiq_job_minutes:) ⇒ SidekiqLongRunningJobLogger
constructor
A new instance of SidekiqLongRunningJobLogger.
- #start ⇒ Object
-
#stop ⇒ Object
Used for testing to stop the thread.
Constructor Details
#initialize(stuck_sidekiq_job_minutes:) ⇒ SidekiqLongRunningJobLogger
Returns a new instance of SidekiqLongRunningJobLogger.
6 7 8 9 10 11 12 13 |
# File 'lib/sidekiq_long_running_job_logger.rb', line 6 def initialize(stuck_sidekiq_job_minutes:) @mutex = Mutex.new @stop_requested = false # Assume that setting the value of `stuck_sidekiq_job_minutes` lower than 0 is a mistake and set it to 1. This makes # the code in this class easier to reason about. @stuck_sidekiq_job_minutes = stuck_sidekiq_job_minutes <= 0 ? 1 : stuck_sidekiq_job_minutes.ceil end |
Instance Attribute Details
#thread ⇒ Object (readonly)
Returns the value of attribute thread.
4 5 6 |
# File 'lib/sidekiq_long_running_job_logger.rb', line 4 def thread @thread end |
Instance Method Details
#start ⇒ Object
15 16 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 62 63 |
# File 'lib/sidekiq_long_running_job_logger.rb', line 15 def start @thread ||= begin hostname = Discourse.os_hostname seconds_to_sleep_between_checks = (@stuck_sidekiq_job_minutes * 60) / 2 Thread.new do loop do break if self.stop_requested? begin current_long_running_jobs = Set.new Sidekiq::Workers.new.each do |process_id, thread_id, work| next unless process_id.start_with?(hostname) if Time.at(work["run_at"]).to_i >= (Time.now - (60 * @stuck_sidekiq_job_minutes)).to_i next end jid = work.dig("payload", "jid") current_long_running_jobs << jid next if @seen_long_running_jobs&.include?(jid) if thread = Thread.list.find { |t| t["sidekiq_tid"] == thread_id } Rails.logger.warn(<<~MSG) Sidekiq job `#{work.dig("payload", "class")}` has been running for more than #{@stuck_sidekiq_job_minutes} minutes #{thread.backtrace.join("\n")} MSG end end @seen_long_running_jobs = current_long_running_jobs yield if block_given? rescue => error Discourse.warn_exception( error, message: "Unexpected error in SidekiqLongRunningJobChecker thread", ) end sleep seconds_to_sleep_between_checks end end end end |
#stop ⇒ Object
Used for testing to stop the thread. In production, the thread is expected to live for the lifetime of the process.
66 67 68 69 70 71 72 73 74 |
# File 'lib/sidekiq_long_running_job_logger.rb', line 66 def stop @mutex.synchronize { @stop_requested = true } if @thread @thread.wakeup @thread.join @thread = nil end end |