rack_proctitle 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README.md +34 -0
- data/lib/rack_proctitle.rb +94 -0
- metadata +58 -0
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2010 Arya Asemanfar
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# About
|
2
|
+
RackProctitle allows you to see what request a given server process is handling. By running "watch -n 0.1 ‘ps aux | grep “USER\|rack” ’ you can see all your rack processes, what request they’re currently handling and for how long (or if they’re idle), what their last request was and how long it took, how many requests have been handled in the life of this process, and the requests in queue.
|
3
|
+
|
4
|
+
It ends up being really useful to diagnose problems.
|
5
|
+
|
6
|
+
Example output:
|
7
|
+
|
8
|
+
rack/14a0b0 [1/682]: handling 0.0s /users/6014086
|
9
|
+
|
10
|
+
You can set a prefix, which will replace “rack” in the line above, and you can set an _APPLICATION\_VERSION_ constant which will be after the prefix. You can use this to distinguish between different rack processes if you run multiple applications on the same machine.
|
11
|
+
|
12
|
+
Concept and output formatting is based on Alexander Staubo’s [mongrel\_proctitle][mongrel_proctitle] but has more features, is thread safe, and is Rack compatible. For more information on why mongrel\_proctitle is not thread safe, [read this post][blog_post].
|
13
|
+
|
14
|
+
|
15
|
+
# Usage
|
16
|
+
sudo gem install rack_proctitle
|
17
|
+
|
18
|
+
In some file somewhere (optional):
|
19
|
+
|
20
|
+
APPLICATION_VERSION = File.read(File.join(RAILS\_ROOT, “REVISION”))[0,6] # if you use Capistrano, which creates a REVISION file for you.
|
21
|
+
|
22
|
+
In your rackup file (prefix is optional):
|
23
|
+
|
24
|
+
use RackProctitle, :prefix => “application_name”
|
25
|
+
|
26
|
+
We use _watch_ to get a continuously updating status of our rack processes:
|
27
|
+
|
28
|
+
watch -n 0.1 ‘ps aux | grep “USER\|application_name” | grep -v grep ; uptime; hostname’
|
29
|
+
|
30
|
+
The _watch_ linux utility is one of those things that is hard to Google, so here's the link if it's not installed or not in your package manager: [http://procps.sourceforge.net/](http://procps.sourceforge.net/)
|
31
|
+
|
32
|
+
|
33
|
+
[mongrel_proctitle]: http://github.com/alexstaubo/mongrel_proctitle
|
34
|
+
[blog_post]: http://asemanfar.com/Request-Queue-via-Mongrel-Proctitle
|
@@ -0,0 +1,94 @@
|
|
1
|
+
class RackProctitle
|
2
|
+
def initialize(app, options = nil)
|
3
|
+
@app = app
|
4
|
+
|
5
|
+
@title = "#{(options && options.delete(:prefix)) || 'rack'}"
|
6
|
+
@title << "/#{APPLICATION_VERSION}" if defined?(APPLICATION_VERSION)
|
7
|
+
@title << " [%d/%d]: %s"
|
8
|
+
|
9
|
+
@mutex = Mutex.new
|
10
|
+
@request_threads = []
|
11
|
+
@total_request_count = 0
|
12
|
+
|
13
|
+
start_updater_thread
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
ensure_updater_thread_running
|
18
|
+
Thread.current[:request_str] = ((env["REQUEST_URI"].nil? || env["REQUEST_URI"].empty?) ? "/" : env["REQUEST_URI"]).split("?", 2)[0]
|
19
|
+
Thread.current[:arrived_at] = Time.now.to_f
|
20
|
+
@mutex.synchronize do
|
21
|
+
@request_threads.push(Thread.current)
|
22
|
+
set_request_list_title
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
@app.call(env)
|
27
|
+
ensure
|
28
|
+
@mutex.synchronize do
|
29
|
+
@total_request_count += 1
|
30
|
+
|
31
|
+
@last_time = Time.now.to_f - Thread.current[:arrived_at].to_f
|
32
|
+
@last_request_str = Thread.current[:request_str].to_s
|
33
|
+
|
34
|
+
@request_threads.delete(Thread.current)
|
35
|
+
set_request_list_title
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
# This exists for cases like unicorn where the instance initialized and then the process is forked.
|
42
|
+
# Threads don't live through forks, so we have to start a new one inside each new process.
|
43
|
+
def ensure_updater_thread_running
|
44
|
+
if @pid != ::Process.pid
|
45
|
+
start_updater_thread
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def start_updater_thread
|
50
|
+
@updater_thread.kill if @updater_thread
|
51
|
+
@pid = ::Process.pid
|
52
|
+
@updater_thread = Thread.new do
|
53
|
+
while true
|
54
|
+
@mutex.synchronize do
|
55
|
+
set_request_list_title
|
56
|
+
end
|
57
|
+
sleep 0.5
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_request_list_title
|
63
|
+
current_status = if @request_threads.empty?
|
64
|
+
idle_message
|
65
|
+
else
|
66
|
+
now = Time.now.to_f
|
67
|
+
list = @request_threads.inject([]) do |str, thread|
|
68
|
+
str << "#{time_delta_abbriv(now - thread[:arrived_at])} #{thread[:request_str]}"
|
69
|
+
end.join(" | ")
|
70
|
+
"handling #{list}"
|
71
|
+
end
|
72
|
+
|
73
|
+
$0 = @title % [@request_threads.size, @total_request_count, current_status]
|
74
|
+
end
|
75
|
+
|
76
|
+
def idle_message
|
77
|
+
str = "idle#{' '*20}" # the spacing is for visual distinction in a list of processes.
|
78
|
+
str << "[last #{time_delta_abbriv(@last_time)} #{@last_request_str}]" if @last_time && @last_request_str
|
79
|
+
str
|
80
|
+
end
|
81
|
+
|
82
|
+
TIME_DELTA_STRS = %w{%.1fs %dm%ds %dh%dm %dd%dh}
|
83
|
+
def time_delta_abbriv(delta)
|
84
|
+
if delta < 60
|
85
|
+
TIME_DELTA_STRS[0] % delta
|
86
|
+
elsif delta < 3600
|
87
|
+
TIME_DELTA_STRS[1] % [delta.to_i / 60, delta.to_i % 60]
|
88
|
+
elsif delta < 86400
|
89
|
+
TIME_DELTA_STRS[2] % [delta.to_i / 3600, (delta.to_i % 3600) / 60]
|
90
|
+
else
|
91
|
+
TIME_DELTA_STRS[3] % [delta.to_i / 86400, (delta.to_i % 86400) / 3600]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack_proctitle
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Arya Asemanfar
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-16 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: aryaasemanfar@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
files:
|
26
|
+
- lib/rack_proctitle.rb
|
27
|
+
- LICENSE
|
28
|
+
- README.md
|
29
|
+
has_rdoc: true
|
30
|
+
homepage: http://github.com/arya/rack_proctitle
|
31
|
+
licenses: []
|
32
|
+
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options:
|
35
|
+
- --charset=UTF-8
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: "0"
|
43
|
+
version:
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: "0"
|
49
|
+
version:
|
50
|
+
requirements: []
|
51
|
+
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 1.3.5
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: A utility to update the proctite of Rack process with helpful information.
|
57
|
+
test_files: []
|
58
|
+
|