Module: Puma::LogStats

Defined in:
lib/puma/plugin/log_stats.rb,
lib/puma/log_stats/version.rb

Constant Summary collapse

VERSION =
"0.1.3"

Class Attribute Summary collapse

Instance Method Summary collapse

Class Attribute Details

.critical_thresholdObject

Returns the value of attribute critical_threshold.



18
19
20
# File 'lib/puma/plugin/log_stats.rb', line 18

def critical_threshold
  @critical_threshold
end

.intervalObject

Interval between logging attempts in seconds.



9
10
11
# File 'lib/puma/plugin/log_stats.rb', line 9

def interval
  @interval
end

.notify_change_withObject

Returns the value of attribute notify_change_with.



12
13
14
# File 'lib/puma/plugin/log_stats.rb', line 12

def notify_change_with
  @notify_change_with
end

.warning_thresholdObject

Returns the value of attribute warning_threshold.



15
16
17
# File 'lib/puma/plugin/log_stats.rb', line 15

def warning_threshold
  @warning_threshold
end

Instance Method Details

#backlogObject



113
114
115
116
117
118
119
# File 'lib/puma/plugin/log_stats.rb', line 113

def backlog
  if clustered?
    @stats[:worker_status].sum { |s| s[:last_status].fetch(:backlog, 0) }
  else
    @stats.fetch(:backlog, 0)
  end
end

#booted_workersObject



101
102
103
# File 'lib/puma/plugin/log_stats.rb', line 101

def booted_workers
  @stats.fetch(:booted_workers, 1)
end

#change_level(level, message) ⇒ Object



61
62
63
64
65
66
67
# File 'lib/puma/plugin/log_stats.rb', line 61

def change_level(level, message)
  return if @load_level == level

  log("#{level.to_s.upcase}: #{message}")
  notify(level, message)
  @load_level = level
end

#check_alarmsObject



44
45
46
47
48
# File 'lib/puma/plugin/log_stats.rb', line 44

def check_alarms
  threshold_reached(:critical, LogStats.critical_threshold) ||
    threshold_reached(:warning, LogStats.warning_threshold) ||
    normal_load
end

#clustered?Boolean

Returns:

  • (Boolean)


93
94
95
# File 'lib/puma/plugin/log_stats.rb', line 93

def clustered?
  @stats.key?(:workers)
end

#log(str) ⇒ Object



85
86
87
# File 'lib/puma/plugin/log_stats.rb', line 85

def log(str)
  @launcher.log_writer.log("[#{Time.now}][puma #{Puma::Const::VERSION}] #{str}")
end

#max_threadsObject



129
130
131
132
133
134
135
# File 'lib/puma/plugin/log_stats.rb', line 129

def max_threads
  if clustered?
    @stats[:worker_status].sum { |s| s[:last_status].fetch(:max_threads, 0) }
  else
    @stats.fetch(:max_threads, 0)
  end
end

#normal_loadObject



57
58
59
# File 'lib/puma/plugin/log_stats.rb', line 57

def normal_load
  change_level(:normal, "Puma threads load is back to normal values")
end

#notify(level, message) ⇒ Object



69
70
71
72
73
74
75
# File 'lib/puma/plugin/log_stats.rb', line 69

def notify(level, message)
  if LogStats.notify_change_with == :sentry
    Sentry.capture_message(message, level: (level == :critical) ? :error : level) if defined?(Sentry) && level != :normal
  elsif LogStats.notify_change_with.respond_to?(:call)
    LogStats.notify_change_with.call(level: level, message: message, threads_load: threads_load)
  end
end

#pool_capacityObject



121
122
123
124
125
126
127
# File 'lib/puma/plugin/log_stats.rb', line 121

def pool_capacity
  if clustered?
    @stats[:worker_status].sum { |s| s[:last_status].fetch(:pool_capacity, 0) }
  else
    @stats.fetch(:pool_capacity, 0)
  end
end

#runningObject



105
106
107
108
109
110
111
# File 'lib/puma/plugin/log_stats.rb', line 105

def running
  if clustered?
    @stats[:worker_status].sum { |s| s[:last_status].fetch(:running, 0) }
  else
    @stats.fetch(:running, 0)
  end
end

#start(launcher) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/puma/plugin/log_stats.rb', line 22

def start(launcher)
  @launcher = launcher
  launcher.events.register(:state) do |state|
    if %i[halt restart stop].include?(state)
      @running = false
    end
  end

  in_background do
    @running = true
    @load_level = :normal
    while @running
      sleep LogStats.interval
      @previous_status_message = @status_message
      @stats = Puma.stats_hash
      @status_message = status_message
      log(@status_message) if @previous_status_message != @status_message
      check_alarms
    end
  end
end

#status_messageObject



77
78
79
80
81
82
83
# File 'lib/puma/plugin/log_stats.rb', line 77

def status_message
  if clustered?
    "cluster: #{booted_workers}/#{workers} workers: #{running}/#{max_threads} threads, #{pool_capacity} available, #{backlog} backlog"
  else
    "single: #{running}/#{max_threads} threads, #{pool_capacity} available, #{backlog} backlog"
  end
end

#threads_loadObject



89
90
91
# File 'lib/puma/plugin/log_stats.rb', line 89

def threads_load
  1.0 - pool_capacity.to_f / max_threads.to_f
end

#threshold_reached(level, threshold) ⇒ Object



50
51
52
53
54
55
# File 'lib/puma/plugin/log_stats.rb', line 50

def threshold_reached(level, threshold)
  return false if threads_load < threshold

  change_level(level, "Puma threads load is greater than #{threshold * 100}% (#{max_threads - pool_capacity}/#{max_threads})")
  true
end

#workersObject



97
98
99
# File 'lib/puma/plugin/log_stats.rb', line 97

def workers
  @stats.fetch(:workers, 1)
end