class PassengerMonitor::Monitor
Constants
- DEFAULT_LOG_FILE
- DEFAULT_MEMORY_LIMIT
Default allowed memory limit for a passenger worker (MB)
- DEFAULT_PROCESS_NAME_REGEX
- DEFAULT_WAIT_TIME
default waiting time after graceful kill attempt to kill process forcefully
Public Class Methods
Sets memory limit, log file, wait time, process name regex and logger
# File lib/passenger_monitor/monitor.rb, line 29 def initialize(params = {}) params = params.to_hash @memory_limit = fetch_memory_limit(params) @log_file = fetch_log_file(params) @wait_time = fetch_wait_time(params) @process_name_regex = fetch_process_name_regex(params) @logger = Logger.new(@log_file) end
Initialize the service and apply a check on all passenger processes given `configurations` (defaults to `{}`)
Parameters:¶ ↑
- config
-
Hash which includes the configurations keys i.e.
1. :memory_limit - allowed memory limit for a passenger worker 2. :log_file - the name of the log file 3. :wait_time - the time to wait to kill the worker forcefully 4. :process_name_regex - regex for the passenger worker of the application
# File lib/passenger_monitor/monitor.rb, line 23 def self.run(config = {}) new(config).check end
Public Instance Methods
Checks memory of all the passenger processes and for bloadted workers it creates thread for each to kill it.
# File lib/passenger_monitor/monitor.rb, line 41 def check @logger.info 'Checking bloated Passenger workers' threads = [] passenger_workers_details.each_line do |line| next unless (line =~ @process_name_regex) pid, memory_usage = extract_stats(line) # If a given passenger process is bloated try to # kill it gracefully and if it fails, force killing it if bloated?(pid, memory_usage) threads << Thread.new { self.handle_bloated_process(pid) } end end threads.map(&:join) @logger.info 'Finished checking for bloated Passenger workers' end
Private Instance Methods
Check if a given process is exceeding memory limit
# File lib/passenger_monitor/monitor.rb, line 143 def bloated?(pid, size) bloated = size > @memory_limit @logger.error "Found bloated worker: #{pid} - #{size}MB" if bloated bloated end
Extracts pid and memory usage of a single Passenger worker
# File lib/passenger_monitor/monitor.rb, line 137 def extract_stats(line) stats = line.split return stats[0].to_i, stats[3].to_f end
# File lib/passenger_monitor/monitor.rb, line 84 def fetch_log_file(params) params.key?(:log_file) ? params[:log_file] : DEFAULT_LOG_FILE end
# File lib/passenger_monitor/monitor.rb, line 80 def fetch_memory_limit(params) params.key?(:memory_limit) ? params[:memory_limit].to_f : DEFAULT_MEMORY_LIMIT end
# File lib/passenger_monitor/monitor.rb, line 92 def fetch_process_name_regex(params) if params.key?(:process_name_regex) Regexp.new(params[:process_name_regex].to_s) else DEFAULT_PROCESS_NAME_REGEX end end
# File lib/passenger_monitor/monitor.rb, line 88 def fetch_wait_time(params) params.key?(:wait_time) ? params[:wait_time].to_i : DEFAULT_WAIT_TIME end
Kill it gracefully
# File lib/passenger_monitor/monitor.rb, line 125 def kill(pid) @logger.error "Trying to kill #{pid} gracefully..." Process.kill("SIGUSR1", pid) end
Kill it forcefully
# File lib/passenger_monitor/monitor.rb, line 131 def kill!(pid) @logger.fatal "Force kill: #{pid}" Process.kill("TERM", pid) end
Fetches the stats of passenger-memory-stats from system. Using `env -i` to remove surrounding environment of bundle.
# File lib/passenger_monitor/monitor.rb, line 102 def passenger_workers_details passenger_memory_status_path = `env -i which passenger-memory-stats` `env -i #{ passenger_memory_status_path }` end
Wait for process to be killed
# File lib/passenger_monitor/monitor.rb, line 119 def wait @logger.error "Waiting for worker to shutdown..." sleep(DEFAULT_WAIT_TIME) end