Class: HeapScope::Monitor

Inherits:
Object
  • Object
show all
Defined in:
lib/heapscope/monitor.rb

Overview

In-process sampling monitor with optional anomaly alerts. Uses a low-priority background thread.

Defined Under Namespace

Classes: Alert, Sample

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(interval: 10, mode: :lightweight, max_samples: 1_000, alert: false, rss_alert_bytes: 25 * 1024 * 1024, live_alert_slots: 80_000) ⇒ Monitor

Returns a new instance of Monitor.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/heapscope/monitor.rb', line 24

def initialize(interval: 10, mode: :lightweight, max_samples: 1_000,
               alert: false, rss_alert_bytes: 25 * 1024 * 1024, live_alert_slots: 80_000)
  @interval = interval
  @mode = mode
  @max_samples = max_samples
  @alert = alert
  @rss_alert_bytes = rss_alert_bytes
  @live_alert_slots = live_alert_slots
  @samples = []
  @alerts = []
  @thread = nil
  @stop = false
  @collector = Collector.new
end

Instance Attribute Details

#alertsObject (readonly)

Returns the value of attribute alerts.



10
11
12
# File 'lib/heapscope/monitor.rb', line 10

def alerts
  @alerts
end

#intervalObject (readonly)

Returns the value of attribute interval.



10
11
12
# File 'lib/heapscope/monitor.rb', line 10

def interval
  @interval
end

#modeObject (readonly)

Returns the value of attribute mode.



10
11
12
# File 'lib/heapscope/monitor.rb', line 10

def mode
  @mode
end

#samplesObject (readonly)

Returns the value of attribute samples.



10
11
12
# File 'lib/heapscope/monitor.rb', line 10

def samples
  @samples
end

Class Method Details

.start(interval: 10, mode: :lightweight, max_samples: 1_000, alert: false, rss_alert_bytes: 25 * 1024 * 1024, live_alert_slots: 80_000) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
# File 'lib/heapscope/monitor.rb', line 12

def self.start(interval: 10, mode: :lightweight, max_samples: 1_000,
               alert: false, rss_alert_bytes: 25 * 1024 * 1024, live_alert_slots: 80_000)
  new(
    interval: interval,
    mode: mode,
    max_samples: max_samples,
    alert: alert,
    rss_alert_bytes: rss_alert_bytes,
    live_alert_slots: live_alert_slots
  ).tap(&:start)
end

Instance Method Details

#alert?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/heapscope/monitor.rb', line 39

def alert?
  @alert
end

#finish_reportObject



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
# File 'lib/heapscope/monitor.rb', line 73

def finish_report
  if samples.empty?
    return Report.new(
      summary: { healthy: true, samples: 0 },
      metadata: { kind: "monitor", alerts: [] }
    )
  end

  session_like = samples.map(&:snapshot)
  first = session_like.first
  last = session_like.last
  diff = Diff.new(first, last)
  analysis = Analyzer.new.analyze_diff(diff)
  series = build_timeline
  alert_payload = alerts.map(&:to_h)
  Report.from_diff(
    diff,
    analysis: analysis,
    metadata: {
      kind: "monitor",
      timeline: series,
      alerts: alert_payload,
      alert_count: alert_payload.size
    }
  )
end

#startObject



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/heapscope/monitor.rb', line 43

def start
  return self if @thread&.alive?

  @stop = false
  @thread = Thread.new do
    Thread.current.name = "heapscope-monitor" if Thread.current.respond_to?(:name=)
    Thread.current.abort_on_exception = false
    until @stop
      begin
        snap = @collector.capture(mode: @mode, metadata: { monitor: true })
        sample = Sample.new(at: Time.now.utc, snapshot: snap)
        maybe_alert!(sample)
        @samples << sample
        @samples.shift if @samples.size > @max_samples
      rescue StandardError => e
        HeapScope.config.log(:debug, "monitor sample failed: #{e.message}")
      end
      sleep @interval
    end
  end
  self
end

#stopObject



66
67
68
69
70
71
# File 'lib/heapscope/monitor.rb', line 66

def stop
  @stop = true
  @thread&.join(2)
  @thread = nil
  finish_report
end