passenger_mon 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/README +26 -0
  2. data/bin/passenger_mon +87 -0
  3. metadata +74 -0
data/README ADDED
@@ -0,0 +1,26 @@
1
+ ## tl;dr ##
2
+
3
+ Simple rails process monitoring for passenger 3.
4
+
5
+ ## Usage ##
6
+
7
+ passenger_mon needs to be run as root to properly get access to Passenger's
8
+ `passenger-memory-stats` output.
9
+
10
+ # Check for out of control processes every 10 seconds
11
+ sudo passenger_mon --interval=10
12
+
13
+
14
+ ## Problem
15
+
16
+ Currently, Passenger 3 (and previous versions) don't generate pidfiles or the
17
+ application processes it spawns. This makes it very difficult to monitor these
18
+ processes with tools like monit and [god](http://github.com/mojombo/god). Further
19
+ compounding this problem is the lack of any sort of per process memory threshold
20
+ for passenger.
21
+
22
+
23
+ ## Contributors
24
+
25
+ * Rick Bradley
26
+ * Alex Sharp
data/bin/passenger_mon ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'fileutils'
5
+
6
+ options = {}
7
+
8
+ op = OptionParser.new do |opts|
9
+ opts.banner = 'Usage: passenger_mon [options]'
10
+
11
+ opts.on("-i=SECONDS", "--interval=SECONDS", "Poll interval in seconds (default: 10)") do |interval|
12
+ options[:interval] = interval
13
+ end
14
+
15
+ opts.on("-m=MEMORY", "--memory=MB", "Memory threshold in MB (default: 800)") do |mb|
16
+ options[:threshold] = mb
17
+ end
18
+
19
+ opts.on_tail("-h", "--help", "show this message") do
20
+ abort(opts.to_s)
21
+ end
22
+ end.parse!
23
+
24
+ # set option defaults
25
+ options[:interval] ||= 10
26
+ options[:threshold] ||= 800
27
+ options[:threshold] = options[:threshold].to_i
28
+
29
+ process_name = 'passenger_mon'
30
+ pidfile = "/tmp/#{process_name}.pid"
31
+
32
+ # If a pidfile exists when we start up, we need to remove it.
33
+ # This probably means a non-clean shutdown the last time
34
+ # the program was shutdown.
35
+ if File.exist?(pidfile)
36
+ $stdout.puts "Existing pidfile found. Removing..."
37
+ FileUtils.rm(pidfile)
38
+ end
39
+
40
+ # remove the pidfile on shutdown
41
+ at_exit do
42
+ $stdout.puts "Removing pidfile."
43
+ FileUtils.rm(pidfile)
44
+ end
45
+
46
+ # write out the pidfile
47
+ File.open(pidfile, 'w') { |f| f.puts($$) }
48
+
49
+ require 'logger'
50
+ logger = Logger.new("/var/log/passenger_mon.log")
51
+
52
+ Signal.trap('INT') do
53
+ logger.info "Shutting down now..."
54
+ abort("\n")
55
+ end
56
+
57
+ kill_attempts = {}
58
+
59
+ loop do
60
+ logger.info "Checking for naughty processes..."
61
+
62
+ results = `passenger-memory-stats`
63
+ results = results.split("\n").grep(/Rails/)
64
+
65
+ results.each do |res|
66
+ pid, vm_size, vm_size_label, mem_res, *bullshit = res.strip.split(/\s+/)
67
+
68
+ # ultimately, we need to have some logic in here that decides when
69
+ # it's appropriate to do a kill -9. If a process has truly run out of
70
+ # control (say, it's trying to load a massive table into memory at once)
71
+ # then we need to be more aggressive with how we terminate the process.
72
+ if mem_res.to_i >= options[:threshold]
73
+ if kill_attempts.has_key?(pid)
74
+ kill_attempts[pid] += 1
75
+ else
76
+ kill_attempts[pid] = 1
77
+ end
78
+
79
+ logger.info "Killing process #{pid} using #{mem_res.to_i}mb of ram (Threshold=#{options[:threshold]}mb)"
80
+
81
+ # passenger treats the USR1 signal as a graceful shutdown.
82
+ Process.kill("USR1", pid.to_i)
83
+ end
84
+ end
85
+
86
+ sleep options[:interval].to_i
87
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: passenger_mon
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Alex Sharp
14
+ - Rick Bradley
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-03-09 00:00:00 -08:00
20
+ default_executable:
21
+ dependencies: []
22
+
23
+ description: Need to control the memory footprint of your passenger processes. You need passenger_mon, bro.
24
+ email:
25
+ - ajsharp@gmail.com
26
+ executables:
27
+ - passenger_mon
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - README
32
+ files:
33
+ - README
34
+ - bin/passenger_mon
35
+ has_rdoc: true
36
+ homepage: https://github.com/ajsharp/passenger_mon
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ hash: 57
50
+ segments:
51
+ - 1
52
+ - 8
53
+ - 7
54
+ version: 1.8.7
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 23
61
+ segments:
62
+ - 1
63
+ - 3
64
+ - 6
65
+ version: 1.3.6
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.7
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Rails process monitoring for passenger 3
73
+ test_files: []
74
+