Class: ErrorRadar::ServerMonitor

Inherits:
Object
  • Object
show all
Defined in:
lib/error_radar/server_monitor.rb

Overview

Reads the live Sidekiq process registry from Redis and reports whether each EXPECTED process (configured via ErrorRadar.config.expected_servers) is currently alive. With no expectations configured it simply surfaces every live process so the dashboard still shows something useful.

Safe when Sidekiq is absent — every method degrades to empty results.

Defined Under Namespace

Classes: Status

Constant Summary collapse

DEAD_AFTER =

seconds without a heartbeat => process considered gone

60

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.statusesObject



15
16
17
# File 'lib/error_radar/server_monitor.rb', line 15

def self.statuses
  new.statuses
end

Instance Method Details

#expectedObject



19
20
21
# File 'lib/error_radar/server_monitor.rb', line 19

def expected
  ErrorRadar.config.expected_servers
end

#live_processesObject



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/error_radar/server_monitor.rb', line 56

def live_processes
  return [] unless defined?(::Sidekiq)

  require 'sidekiq/api'
  now = Time.now.to_f
  ::Sidekiq::ProcessSet.new.map do |p|
    {
      identity: p['identity'],
      hostname: p['hostname'],
      tag: p['tag'],
      queues: Array(p['queues']),
      concurrency: p['concurrency'],
      busy: p['busy'],
      rss: p['rss'],
      quiet: p['quiet'] == 'true' || p['quiet'] == true,
      started_at: p['started_at'] && Time.at(p['started_at']),
      beat_ago: p['beat'] ? (now - p['beat']).round : nil
    }
  end
rescue StandardError => e
  ErrorRadar::Tracking.warn_internal("ServerMonitor.live_processes failed: #{e.class}: #{e.message}")
  []
end

#statusesObject



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
# File 'lib/error_radar/server_monitor.rb', line 23

def statuses
  live = live_processes

  if expected.empty?
    return live.map do |p|
      Status.new(
        key: p[:identity],
        name: "#{p[:hostname]} #{p[:tag]}".strip,
        up: p[:beat_ago] && p[:beat_ago] <= DEAD_AFTER,
        processes: [p],
        last_beat_ago: p[:beat_ago]
      )
    end
  end

  expected.map do |exp|
    matched = live.select { |p| matches?(p, exp) }
    Status.new(
      key: exp[:key],
      name: exp[:name],
      up: matched.any? { |p| p[:beat_ago] && p[:beat_ago] <= DEAD_AFTER },
      processes: matched,
      last_beat_ago: matched.map { |p| p[:beat_ago] }.compact.min
    )
  end
end

#unexpected_processesObject



50
51
52
53
54
# File 'lib/error_radar/server_monitor.rb', line 50

def unexpected_processes
  return [] if expected.empty?

  live_processes.reject { |p| expected.any? { |exp| matches?(p, exp) } }
end