arya-mongrel_proctitle 1.2.7

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.
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2008, Ryan Tomayko
2
+ Copyright (c) 2007, Alexander Staubo
3
+
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without modification, are
7
+ permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this list of
10
+ conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice, this list
13
+ of conditions and the following disclaimer in the documentation and/or other materials
14
+ provided with the distribution.
15
+
16
+ * The names of its contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND WITHOUT ANY
20
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
24
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ POSSIBILITY OF SUCH DAMAGE.
data/README ADDED
@@ -0,0 +1,96 @@
1
+ Mongrel process title GemPlugin
2
+ ===============================
3
+
4
+ This is a simple plugin for Mongrel which changes the process title to reflect
5
+ what it's currently doing. You can then determine a given Mongrel server's
6
+ status using "ps".
7
+
8
+ For example:
9
+
10
+ mongrel_rails [10010/2/358]: handling 127.0.0.1: HEAD /feed/cal/global/91/6de4, GET /feed/index
11
+ | | | | | |
12
+ | | | | | The current req (method / path)
13
+ | | | | |
14
+ | | | | The client IP
15
+ | | | |
16
+ | | | What it's doing
17
+ | | |
18
+ | | Requests processed during server lifetime
19
+ | |
20
+ | Requests currently queued/being processed concurrently
21
+ |
22
+ The port that Mongrel is serving
23
+
24
+ This is almost entirely based on Alexander Staubo's Rails plugin with the same
25
+ name:
26
+
27
+ http://purefiction.net/mongrel_proctitle/
28
+
29
+ The main difference is that the GemPlugin will automatically be loaded by all
30
+ mongrels without additional code changes or configuration.
31
+
32
+ This is a fork of rtomayko's fork of mongrel_proctitle that displays the current request
33
+ instead of the most recent received request, as well a list of the request queue.
34
+
35
+ Monitoring Mongrels
36
+ -------------------
37
+
38
+ Once the program is installed, you should be able to see the formatted process
39
+ title by running:
40
+
41
+ $ ps -axwwo pid,command | grep mongrel_rails
42
+
43
+ See ps(1) for more options. You may want to include %cpu, rsz, %mem, or other
44
+ fields in output.
45
+
46
+ There's also a `mongrel_top` executable included in the gem that works like
47
+ top(1) but displays only mongrel processes:
48
+
49
+ $ mongrel_top
50
+
51
+ By default, `mongrel_top` updates the display every 0.25 seconds and shows the
52
+ pid and process title. You can select a different interval and fields with the
53
+ -s and -o arguments, respectively:
54
+
55
+ $ mongrel_top -s 0.1 -o pid,%cpu,rsz,command
56
+
57
+ The "command" field must be included.
58
+
59
+ Installation
60
+ ------------
61
+
62
+ This version of the plugin is packaged specifically as a Mongrel GemPlugin. Install
63
+ using:
64
+
65
+ gem install mongrel_proctitle --source=http://tomayko.com
66
+
67
+ Once installed, all new mongrels will automatically load the plugin during startup. If
68
+ you would prefer to control which mongrels load the plugin, do not install this gem.
69
+ Use the directions below instead.
70
+
71
+ Installing into a specific Rails app only
72
+ -----------------------------------------
73
+
74
+ See Alexander Staubo's original project:
75
+
76
+ http://purefiction.net/mongrel_proctitle/
77
+
78
+ Showing your application-specific revision/release in the title
79
+ -------------------------------------------------------------------
80
+
81
+ In your application's start-up process, re-open Mongrel::Proctitler
82
+ and define a get_app_revision method. In a Rails app, a good place
83
+ to do this is in RAILS_ROOT/config/environments/production.rb. An
84
+ example get_app_revision method might look like:
85
+
86
+ def get_app_revision
87
+ `cat ./REVISION`.chomp
88
+ end
89
+
90
+ License
91
+ -------
92
+
93
+ I've included the LICENSE file from the original mongrel_proctitle distribution. It is
94
+ the "New and Simplified BSD License". More information on this license can be found at:
95
+
96
+ http://www.opensource.org/licenses/bsd-license.php
@@ -0,0 +1,60 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/rdoctask'
6
+ require 'rake/contrib/rubyforgepublisher'
7
+ require 'fileutils'
8
+ include FileUtils
9
+
10
+ CLEAN.include [ "pkg", "lib/*.bundle", "*.gem", ".config", "**/*.log" ]
11
+
12
+ desc "Build package"
13
+ task :default => [:package]
14
+
15
+ version = "1.2.5"
16
+ name = "mongrel_proctitle"
17
+
18
+ spec =
19
+ Gem::Specification.new do |s|
20
+ s.name = name
21
+ s.version = version
22
+ s.platform = Gem::Platform::RUBY
23
+ s.summary = "The mongrel_proctitle GemPlugin"
24
+ s.description = s.summary
25
+ s.author = "Ryan Tomayko"
26
+ s.email = "rtomayko@gmail.com"
27
+ s.homepage = "http://github.com/rtomayko/mongrel_proctitle"
28
+ s.add_dependency('mongrel', '>= 1.1')
29
+ s.add_dependency('gem_plugin', '>= 0.2.3')
30
+ s.has_rdoc = true
31
+ s.extra_rdoc_files = [ "README" ]
32
+ s.bindir = "bin"
33
+ s.executables = [ "mongrel_top" ]
34
+ s.files = %w(LICENSE README Rakefile) +
35
+ Dir.glob("{bin,doc/rdoc,test,lib}/**/*")
36
+ s.require_path = "lib"
37
+ s.rubyforge_project = "orphans"
38
+ end
39
+
40
+ Rake::GemPackageTask.new(spec) do |p|
41
+ p.gem_spec = spec
42
+ p.need_zip = true
43
+ p.need_tar_gz = true
44
+ end
45
+
46
+ task :install => [:package] do
47
+ sh %{gem install pkg/#{name}-#{version}.gem}
48
+ end
49
+
50
+ task :uninstall => [:clean] do
51
+ sh %{gem uninstall #{name}}
52
+ end
53
+
54
+ desc 'Publish gems and other distributables to tomayko.com'
55
+ task :release => [:package] do
56
+ sh <<-end
57
+ ssh tomayko.com 'mkdir -p /dist/#{name}' && \
58
+ rsync -azP pkg/#{name}-#{version}.* tomayko.com:/dist/#{name}/
59
+ end
60
+ end
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $last_update = nil
4
+ $clear_char = `tput clear`
5
+
6
+ def usage
7
+ puts "usage: #{File.basename($0)} [-s delay] [-o fields]"
8
+ end
9
+
10
+ def die(*message)
11
+ STDERR.puts "fatal: #{format(*message)}" if message.any?
12
+ exit 1
13
+ end
14
+
15
+ # clear the terminal
16
+ def clear_screen
17
+ STDOUT.write($clear_char)
18
+ end
19
+
20
+ # clear the terminal and then write output.
21
+ def update_screen(output)
22
+ if output != $last_update
23
+ clear_screen
24
+ puts(output)
25
+ end
26
+ end
27
+
28
+ def terminal_columns
29
+ @terminal_columns ||=
30
+ if (cols = `tput cols`) == ""
31
+ 80
32
+ else
33
+ cols.to_i
34
+ end
35
+ end
36
+
37
+ trap("INT") {
38
+ STDERR.puts "\nbailing ..."
39
+ exit 0
40
+ }
41
+
42
+ # time to wait between updates
43
+ interval = 0.25
44
+
45
+ # the fields to show in our display (see ps -o)
46
+ fields = "pid,command"
47
+
48
+ # parse arguments.
49
+ # TODO: use getoptlong
50
+ argv = ARGV.map { |a| a.split('=', 2) }.flatten
51
+ while argv.any?
52
+ arg = argv.shift
53
+ case arg
54
+ when /^-(s|-delay)$/
55
+ interval = argv.shift.to_f
56
+ when /^-(o|-fields)$/
57
+ fields = argv.shift
58
+ when /^-(h|-help)$/
59
+ usage and exit(0)
60
+ else
61
+ usage and die
62
+ end
63
+ end
64
+
65
+ # Builds the process output display.
66
+ def process_display(fields, interval)
67
+ now = Time.now.strftime('%a %b %d %H:%M:%S %Y')
68
+ cols = terminal_columns
69
+ processes =
70
+ `ps axww -o #{fields}`.grep(/mongrel_rails/).map do |line|
71
+ line.strip!
72
+ line.sub! /\s+SHELL=.*$/, '' # weird MacOS X issue
73
+ line.sub! /(?:ruby\d*: )?mongrel_rails /, '' # remove $0 prefix
74
+ line.sub! /\(ruby\d*\)/, '' # remove (ruby) suffix
75
+ line[0,cols].chomp
76
+ end
77
+ output = [
78
+ (' ' * (cols - now.length)) + now + "\r" +
79
+ "Mongrel Top (delay: #{interval})",
80
+ "",
81
+ processes,
82
+ "",
83
+ "#{processes.length} process(es)"
84
+ ]
85
+ output.flatten.join("\n")
86
+ end
87
+
88
+ while true
89
+ output = process_display(fields, interval)
90
+ update_screen(output)
91
+ sleep(interval)
92
+ end
@@ -0,0 +1,146 @@
1
+ module Mongrel
2
+
3
+ # Mongrel process title modification.
4
+ class Proctitler
5
+
6
+ # Initializes titler.
7
+ def initialize(port, prefix)
8
+ @prefix = prefix
9
+ @port = port
10
+ @mutex = Mutex.new
11
+ @titles = []
12
+ @request_threads = []
13
+ @queue_length = 0
14
+ @request_count = 0
15
+ end
16
+
17
+ # Returns port used in title.
18
+ def port
19
+ @port
20
+ end
21
+
22
+ # Return port used in title.
23
+ def port=(new_port)
24
+ @port = new_port
25
+ end
26
+
27
+ # Returns revision used in title.
28
+ def revision
29
+ @revision ||= get_app_revision if self.respond_to?(:get_app_revision)
30
+ end
31
+
32
+ def request(&block)
33
+ titles, mutex = @titles, @mutex
34
+ mutex.synchronize do
35
+ @queue_length += 1
36
+ titles.push(self.title)
37
+ end
38
+ begin
39
+ yield
40
+ ensure
41
+ mutex.synchronize do
42
+ @queue_length -= 1
43
+ @request_count += 1
44
+ @request_threads.delete(Thread.current)
45
+ set_request_list_title
46
+ end
47
+ end
48
+ end
49
+
50
+ def set_request_list_title(excluding = nil)
51
+ if @request_threads.empty?
52
+ set_idle
53
+ else
54
+ if defined?(Rails)
55
+ # find the first awake/critical thread and put it in the front
56
+ running_thread = @request_threads.detect {|thread| thread.status == "run" && excluding != thread }
57
+ @request_threads.unshift(@request_threads.delete(running_thread)) if running_thread
58
+ # this isn't exact, but it works for most situations
59
+ end
60
+ self.title = "handling #{@request_threads.collect {|t| t[:request_str]}.join(', ')}"
61
+ end
62
+ end
63
+
64
+ # Reports process as being idle.
65
+ def set_idle
66
+ self.title = "idle"
67
+ end
68
+
69
+ # Reports process as handling a socket.
70
+ def set_processing(socket)
71
+ self.title = "handling #{socket.peeraddr.last}"
72
+ end
73
+
74
+ # Reports process as handling a socket.
75
+ def set_handling(request)
76
+ params = request.params
77
+ address = params['REMOTE_ADDR']
78
+ method = params['REQUEST_METHOD']
79
+ path = params['REQUEST_PATH']
80
+ path = "#{path[0, 60]}..." if path.length > 60
81
+ Thread.current[:request_str] = "#{address}: #{method} #{path}"
82
+ @request_threads.push(Thread.current)
83
+ set_request_list_title(Thread.current)
84
+ end
85
+
86
+ # Returns current title
87
+ def title
88
+ @title
89
+ end
90
+
91
+ # Sets process title.
92
+ def title=(title)
93
+ @title = title
94
+ update_process_title
95
+ end
96
+
97
+ # Updates the process title.
98
+ def update_process_title
99
+ title = "#{@prefix} ["
100
+ title << (@port ? "#{@port}" : "?")
101
+ title << (revision ? "/r#{revision}" : "")
102
+ title << "/#{@queue_length}"
103
+ title << "/#{@request_count}"
104
+ title << "]: #{@title}"
105
+ $0 = title
106
+ end
107
+
108
+ end
109
+
110
+ # Handler which sets process title before request.
111
+ class ProctitleHandler < HttpHandler
112
+ def initialize(titler)
113
+ @titler = titler
114
+ end
115
+
116
+ def process(request, response)
117
+ @titler.set_handling(request)
118
+ end
119
+ end
120
+
121
+ class HttpServer
122
+
123
+ def run_with_proctitle(*args)
124
+ @titler = Proctitler.new(self.port, File.basename($0))
125
+ @titler.set_idle
126
+ run_without_proctitle
127
+ end
128
+ alias_method :run_without_proctitle, :run
129
+ alias_method :run, :run_with_proctitle
130
+
131
+ def process_client_with_proctitle(client)
132
+ unless @handler
133
+ @handler = ProctitleHandler.new(@titler)
134
+ register("/", @handler, true)
135
+ end
136
+ @titler.request do
137
+ @titler.set_processing(client)
138
+ return process_client_without_proctitle(client)
139
+ end
140
+ end
141
+ alias_method :process_client_without_proctitle, :process_client
142
+ alias_method :process_client, :process_client_with_proctitle
143
+
144
+ end
145
+
146
+ end
@@ -0,0 +1,3 @@
1
+ require 'mongrel'
2
+ require 'gem_plugin'
3
+ require 'mongrel_proctitle'
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arya-mongrel_proctitle
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.7
5
+ platform: ruby
6
+ authors:
7
+ - Arya Asemanfar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-05 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mongrel
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "1.1"
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: gem_plugin
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: 0.2.3
32
+ version:
33
+ description: The mongrel_proctitle Gem
34
+ email: arya@seriousbusiness.com
35
+ executables:
36
+ - mongrel_top
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - README
41
+ files:
42
+ - LICENSE
43
+ - README
44
+ - Rakefile
45
+ - bin/mognrel_top
46
+ - lib/mongrel_proctitle.rb
47
+ - lib/mongrel_proctitle/init.rb
48
+ has_rdoc: true
49
+ homepage: http://github.com/arya/mongrel_proctitle
50
+ post_install_message:
51
+ rdoc_options: []
52
+
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.2.0
71
+ signing_key:
72
+ specification_version: 2
73
+ summary: The mongrel_proctitle Gem
74
+ test_files: []
75
+