freels-mongrel_proctitle 1.3.5.1

Sign up to get free protection for your applications and to get access to all the features.
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
data/Rakefile ADDED
@@ -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
data/bin/mongrel_top ADDED
@@ -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,3 @@
1
+ require 'mongrel'
2
+ require 'gem_plugin'
3
+ require 'mongrel_proctitle'
@@ -0,0 +1,181 @@
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
+
16
+ @updater_thread = Thread.new do
17
+ while true
18
+ @mutex.synchronize do
19
+ set_request_list_title
20
+ end
21
+ sleep 0.5
22
+ end
23
+ end
24
+ end
25
+
26
+ # Returns port used in title.
27
+ def port
28
+ @port
29
+ end
30
+
31
+ # Return port used in title.
32
+ def port=(new_port)
33
+ @port = new_port
34
+ end
35
+
36
+ # Returns revision used in title.
37
+ def revision
38
+ @revision ||= get_app_revision if self.respond_to?(:get_app_revision)
39
+ end
40
+
41
+ def request(&block)
42
+ titles, mutex = @titles, @mutex
43
+ mutex.synchronize do
44
+ @queue_length += 1
45
+ titles.push(self.title)
46
+ end
47
+ begin
48
+ yield
49
+ ensure
50
+ mutex.synchronize do
51
+ @queue_length -= 1
52
+ @request_count += 1
53
+
54
+ @last_time = Time.now.to_f - Thread.current[:arrived_at].to_f
55
+ @last_request_str = Thread.current[:request_str].to_s
56
+
57
+ @request_threads.delete(Thread.current)
58
+ set_request_list_title
59
+ end
60
+ end
61
+ end
62
+
63
+ def set_request_list_title(excluding = nil)
64
+ if @request_threads.empty?
65
+ set_idle
66
+ else
67
+ if defined?(Rails)
68
+ # find the first awake/critical thread and put it in the front
69
+ running_thread = @request_threads.detect {|thread| thread.status == "run" && excluding != thread }
70
+ @request_threads.unshift(@request_threads.delete(running_thread)) if running_thread
71
+ # this isn't exact, but it works for most situations
72
+ end
73
+ now = Time.now.to_f
74
+ list = @request_threads.inject([]) do |str, thread|
75
+ str << "#{time_delta_abbriv(now - thread[:arrived_at])} #{thread[:request_str]}"
76
+ end.join(" | ")
77
+ self.title = "handling #{list}"
78
+ end
79
+ end
80
+
81
+ def time_delta_abbriv(delta)
82
+ if delta < 60
83
+ "%.1fs" % delta
84
+ elsif delta < 3600
85
+ "#{delta.to_i / 60}m#{delta.to_i % 60}s"
86
+ elsif delta < 86400
87
+ "#{delta.to_i / 3600}h#{(delta.to_i % 3600) / 60}m"
88
+ else
89
+ "#{delta.to_i / 86400}d#{(delta.to_i % 86400) / 3600}h"
90
+ end
91
+ end
92
+
93
+ # Reports process as being idle.
94
+ def set_idle
95
+ str = "idle#{' '*20}"
96
+ str << "[last #{time_delta_abbriv(@last_time)} #{@last_request_str}]" if @last_time && @last_request_str
97
+ self.title = str
98
+ end
99
+
100
+ # Reports process as handling a socket.
101
+ def set_processing(socket)
102
+ self.title = "handling #{socket.peeraddr.last}"
103
+ end
104
+
105
+ # Reports process as handling a socket.
106
+ def set_handling(request)
107
+ params = request.params
108
+ address = params['REMOTE_ADDR']
109
+ method = params['REQUEST_METHOD']
110
+ path = params['REQUEST_PATH']
111
+ # path = "#{path[0, 60]}..." if path.length > 60
112
+ # Thread.current[:request_str] = "#{address}: #{method} #{path}"
113
+ Thread.current[:request_str] = "#{method} #{path}"
114
+ Thread.current[:arrived_at] = Time.now.to_f
115
+ @mutex.synchronize do
116
+ @request_threads.push(Thread.current)
117
+ set_request_list_title(Thread.current)
118
+ end
119
+ end
120
+
121
+ # Returns current title
122
+ def title
123
+ @title
124
+ end
125
+
126
+ # Sets process title.
127
+ def title=(title)
128
+ @title = title
129
+ update_process_title
130
+ end
131
+
132
+ # Updates the process title.
133
+ def update_process_title
134
+ title = "#{@prefix} ["
135
+ title << (@port ? "#{@port}" : "?")
136
+ title << (revision ? "/r#{revision}" : "")
137
+ title << "/#{@queue_length}"
138
+ title << "/#{@request_count}"
139
+ title << "]: #{@title}"
140
+ $0 = title
141
+ end
142
+
143
+ end
144
+
145
+ # Handler which sets process title before request.
146
+ class ProctitleHandler < HttpHandler
147
+ def initialize(titler)
148
+ @titler = titler
149
+ end
150
+
151
+ def process(request, response)
152
+ @titler.set_handling(request)
153
+ end
154
+ end
155
+
156
+ class HttpServer
157
+
158
+ def run_with_proctitle(*args)
159
+ @titler = Proctitler.new(self.port, File.basename($0))
160
+ @titler.set_idle
161
+ run_without_proctitle
162
+ end
163
+ alias_method :run_without_proctitle, :run
164
+ alias_method :run, :run_with_proctitle
165
+
166
+ def process_client_with_proctitle(client)
167
+ unless @handler
168
+ @handler = ProctitleHandler.new(@titler)
169
+ register("/", @handler, true)
170
+ end
171
+ @titler.request do
172
+ @titler.set_processing(client)
173
+ return process_client_without_proctitle(client)
174
+ end
175
+ end
176
+ alias_method :process_client_without_proctitle, :process_client
177
+ alias_method :process_client, :process_client_with_proctitle
178
+
179
+ end
180
+
181
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: freels-mongrel_proctitle
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.5.1
5
+ platform: ruby
6
+ authors:
7
+ - Arya Asemanfar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-08 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mongrel
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "1.1"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: gem_plugin
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.3
34
+ version:
35
+ description: The mongrel_proctitle Gem
36
+ email: arya@seriousbusiness.com
37
+ executables:
38
+ - mongrel_top
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README
43
+ files:
44
+ - LICENSE
45
+ - README
46
+ - Rakefile
47
+ - bin/mongrel_top
48
+ - lib/mongrel_proctitle.rb
49
+ - lib/arya-mongrel_proctitle/init.rb
50
+ has_rdoc: true
51
+ homepage: http://github.com/arya/mongrel_proctitle
52
+ post_install_message:
53
+ rdoc_options: []
54
+
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ requirements: []
70
+
71
+ rubyforge_project:
72
+ rubygems_version: 1.2.0
73
+ signing_key:
74
+ specification_version: 2
75
+ summary: The mongrel_proctitle Gem
76
+ test_files: []
77
+