raindrops 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +2 -1
- data/.gitignore +4 -0
- data/.wrongdoc.yml +4 -0
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +2 -196
- data/Gemfile +7 -0
- data/LICENSE +1 -1
- data/README +17 -47
- data/Rakefile +0 -104
- data/examples/linux-listener-stats.rb +123 -0
- data/examples/{config.ru → middleware.ru} +1 -1
- data/examples/watcher.ru +4 -0
- data/examples/watcher_demo.ru +13 -0
- data/examples/zbatery.conf.rb +13 -0
- data/ext/raindrops/extconf.rb +5 -0
- data/ext/raindrops/linux_inet_diag.c +449 -151
- data/ext/raindrops/linux_tcp_info.c +170 -0
- data/ext/raindrops/my_fileno.h +36 -0
- data/ext/raindrops/raindrops.c +232 -20
- data/lib/raindrops.rb +20 -7
- data/lib/raindrops/aggregate.rb +8 -0
- data/lib/raindrops/aggregate/last_data_recv.rb +86 -0
- data/lib/raindrops/aggregate/pmq.rb +239 -0
- data/lib/raindrops/last_data_recv.rb +100 -0
- data/lib/raindrops/linux.rb +26 -16
- data/lib/raindrops/middleware.rb +112 -41
- data/lib/raindrops/middleware/proxy.rb +34 -0
- data/lib/raindrops/struct.rb +15 -0
- data/lib/raindrops/watcher.rb +362 -0
- data/pkg.mk +171 -0
- data/raindrops.gemspec +10 -20
- data/test/ipv6_enabled.rb +10 -0
- data/test/rack_unicorn.rb +12 -0
- data/test/test_aggregate_pmq.rb +65 -0
- data/test/test_inet_diag_socket.rb +13 -0
- data/test/test_last_data_recv_unicorn.rb +69 -0
- data/test/test_linux.rb +55 -57
- data/test/test_linux_all_tcp_listen_stats.rb +66 -0
- data/test/test_linux_all_tcp_listen_stats_leak.rb +43 -0
- data/test/test_linux_ipv6.rb +158 -0
- data/test/test_linux_tcp_info.rb +61 -0
- data/test/test_middleware.rb +15 -2
- data/test/test_middleware_unicorn.rb +37 -0
- data/test/test_middleware_unicorn_ipv6.rb +37 -0
- data/test/test_raindrops.rb +65 -1
- data/test/test_raindrops_gc.rb +23 -1
- data/test/test_watcher.rb +85 -0
- metadata +69 -22
- data/examples/linux-tcp-listener-stats.rb +0 -44
data/test/test_raindrops_gc.rb
CHANGED
@@ -13,4 +13,26 @@ class TestRaindropsGc < Test::Unit::TestCase
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
def test_gc_postfork
|
17
|
+
tmp = Raindrops.new 2
|
18
|
+
pid = fork do
|
19
|
+
1000000.times do
|
20
|
+
tmp = Raindrops.new 2
|
21
|
+
tmp.to_ary
|
22
|
+
end
|
23
|
+
end
|
24
|
+
_, status = Process.waitpid2(pid)
|
25
|
+
assert status.success?
|
26
|
+
assert_equal [ 0, 0 ], tmp.to_ary
|
27
|
+
tmp.incr 1
|
28
|
+
assert_equal [ 0, 1 ], tmp.to_ary
|
29
|
+
pid = fork do
|
30
|
+
tmp.incr 1
|
31
|
+
exit([ 0, 2 ] == tmp.to_ary)
|
32
|
+
end
|
33
|
+
_, status = Process.waitpid2(pid)
|
34
|
+
assert status.success?
|
35
|
+
assert_equal [ 0, 2 ], tmp.to_ary
|
36
|
+
end
|
37
|
+
end if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby" &&
|
38
|
+
ENV["STRESS"].to_i != 0
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
require "test/unit"
|
3
|
+
require "rack"
|
4
|
+
require "raindrops"
|
5
|
+
|
6
|
+
class TestWatcher < Test::Unit::TestCase
|
7
|
+
TEST_ADDR = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
|
8
|
+
def check_headers(headers)
|
9
|
+
%w(X-Count X-Std-Dev X-Min X-Max X-Mean
|
10
|
+
X-Outliers-Low X-Outliers-Low X-Last-Reset).each { |x|
|
11
|
+
assert_kind_of String, headers[x], "#{x} missing"
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
@app.shutdown
|
17
|
+
@ios.each { |io| io.close unless io.closed? }
|
18
|
+
end
|
19
|
+
|
20
|
+
def setup
|
21
|
+
@ios = []
|
22
|
+
@srv = TCPServer.new TEST_ADDR, 0
|
23
|
+
@ios << @srv
|
24
|
+
@port = @srv.addr[1]
|
25
|
+
@client = TCPSocket.new TEST_ADDR, @port
|
26
|
+
@addr = "#{TEST_ADDR}:#{@port}"
|
27
|
+
@ios << @client
|
28
|
+
@app = Raindrops::Watcher.new :delay => 0.001
|
29
|
+
@req = Rack::MockRequest.new @app
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_index
|
33
|
+
resp = @req.get "/"
|
34
|
+
assert_equal 200, resp.status.to_i
|
35
|
+
t = Time.parse resp.headers["Last-Modified"]
|
36
|
+
assert_in_delta Time.now.to_f, t.to_f, 2.0
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_active_txt
|
40
|
+
resp = @req.get "/active/#@addr.txt"
|
41
|
+
assert_equal 200, resp.status.to_i
|
42
|
+
assert_equal "text/plain", resp.headers["Content-Type"]
|
43
|
+
check_headers(resp.headers)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_active_html
|
47
|
+
resp = @req.get "/active/#@addr.html"
|
48
|
+
assert_equal 200, resp.status.to_i
|
49
|
+
assert_equal "text/html", resp.headers["Content-Type"]
|
50
|
+
check_headers(resp.headers)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_reset
|
54
|
+
resp = @req.post "/reset/#@addr"
|
55
|
+
assert_equal 302, resp.status.to_i
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_tail
|
59
|
+
env = @req.class.env_for "/tail/#@addr.txt"
|
60
|
+
status, headers, body = @app.call env
|
61
|
+
assert_equal "text/plain", headers["Content-Type"]
|
62
|
+
assert_equal 200, status.to_i
|
63
|
+
tmp = []
|
64
|
+
body.each do |x|
|
65
|
+
assert_kind_of String, x
|
66
|
+
tmp << x
|
67
|
+
break if tmp.size > 1
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_tail_queued_min
|
72
|
+
env = @req.class.env_for "/tail/#@addr.txt?queued_min=1"
|
73
|
+
status, headers, body = @app.call env
|
74
|
+
assert_equal "text/plain", headers["Content-Type"]
|
75
|
+
assert_equal 200, status.to_i
|
76
|
+
tmp = []
|
77
|
+
body.each do |x|
|
78
|
+
tmp = TCPSocket.new TEST_ADDR, @port
|
79
|
+
@ios << tmp
|
80
|
+
assert_kind_of String, x
|
81
|
+
assert_equal 1, x.strip.split(/\s+/).last.to_i
|
82
|
+
break
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end if RUBY_PLATFORM =~ /linux/
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: raindrops
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 4
|
9
|
-
- 1
|
10
|
-
version: 0.4.1
|
4
|
+
prerelease:
|
5
|
+
version: 0.5.0
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- raindrops hackers
|
@@ -15,15 +10,27 @@ autorequire:
|
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
12
|
|
18
|
-
date:
|
13
|
+
date: 2011-03-17 00:00:00 +00:00
|
19
14
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: bundler
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 1.0.10
|
25
|
+
type: :development
|
26
|
+
version_requirements: *id001
|
22
27
|
description: |-
|
23
|
-
Raindrops is a real
|
28
|
+
Raindrops is a real-time stats toolkit to show statistics for Rack HTTP
|
24
29
|
servers. It is designed for preforking servers such as Rainbows! and
|
25
30
|
Unicorn, but should support any Rack HTTP server under Ruby 1.9, 1.8 and
|
26
|
-
|
31
|
+
Rubinius on platforms supporting POSIX shared memory. It may also be
|
32
|
+
used as a generic scoreboard for sharing atomic counters across multiple
|
33
|
+
processes.
|
27
34
|
email: raindrops@librelist.com
|
28
35
|
executables: []
|
29
36
|
|
@@ -35,51 +42,87 @@ extra_rdoc_files:
|
|
35
42
|
- NEWS
|
36
43
|
- ChangeLog
|
37
44
|
- lib/raindrops.rb
|
45
|
+
- lib/raindrops/aggregate.rb
|
46
|
+
- lib/raindrops/aggregate/last_data_recv.rb
|
47
|
+
- lib/raindrops/aggregate/pmq.rb
|
48
|
+
- lib/raindrops/last_data_recv.rb
|
38
49
|
- lib/raindrops/linux.rb
|
39
50
|
- lib/raindrops/middleware.rb
|
51
|
+
- lib/raindrops/middleware/proxy.rb
|
40
52
|
- lib/raindrops/struct.rb
|
53
|
+
- lib/raindrops/watcher.rb
|
54
|
+
- ext/raindrops/raindrops.c
|
41
55
|
- ext/raindrops/linux_inet_diag.c
|
56
|
+
- ext/raindrops/linux_tcp_info.c
|
42
57
|
files:
|
43
58
|
- .document
|
44
59
|
- .gitignore
|
45
60
|
- .manifest
|
61
|
+
- .wrongdoc.yml
|
46
62
|
- COPYING
|
47
63
|
- ChangeLog
|
48
64
|
- GIT-VERSION-FILE
|
49
65
|
- GIT-VERSION-GEN
|
50
66
|
- GNUmakefile
|
67
|
+
- Gemfile
|
68
|
+
- LATEST
|
51
69
|
- LICENSE
|
52
70
|
- NEWS
|
53
71
|
- README
|
54
72
|
- Rakefile
|
55
73
|
- TODO
|
56
|
-
- examples/
|
57
|
-
- examples/
|
74
|
+
- examples/linux-listener-stats.rb
|
75
|
+
- examples/middleware.ru
|
76
|
+
- examples/watcher.ru
|
77
|
+
- examples/watcher_demo.ru
|
78
|
+
- examples/zbatery.conf.rb
|
58
79
|
- ext/raindrops/extconf.rb
|
59
80
|
- ext/raindrops/linux_inet_diag.c
|
81
|
+
- ext/raindrops/linux_tcp_info.c
|
82
|
+
- ext/raindrops/my_fileno.h
|
60
83
|
- ext/raindrops/raindrops.c
|
61
84
|
- ext/raindrops/raindrops_atomic.h
|
62
85
|
- lib/raindrops.rb
|
86
|
+
- lib/raindrops/aggregate.rb
|
87
|
+
- lib/raindrops/aggregate/last_data_recv.rb
|
88
|
+
- lib/raindrops/aggregate/pmq.rb
|
89
|
+
- lib/raindrops/last_data_recv.rb
|
63
90
|
- lib/raindrops/linux.rb
|
64
91
|
- lib/raindrops/middleware.rb
|
92
|
+
- lib/raindrops/middleware/proxy.rb
|
65
93
|
- lib/raindrops/struct.rb
|
94
|
+
- lib/raindrops/watcher.rb
|
95
|
+
- pkg.mk
|
66
96
|
- raindrops.gemspec
|
67
97
|
- setup.rb
|
98
|
+
- test/ipv6_enabled.rb
|
99
|
+
- test/rack_unicorn.rb
|
100
|
+
- test/test_aggregate_pmq.rb
|
101
|
+
- test/test_inet_diag_socket.rb
|
102
|
+
- test/test_last_data_recv_unicorn.rb
|
68
103
|
- test/test_linux.rb
|
104
|
+
- test/test_linux_all_tcp_listen_stats.rb
|
105
|
+
- test/test_linux_all_tcp_listen_stats_leak.rb
|
106
|
+
- test/test_linux_ipv6.rb
|
69
107
|
- test/test_linux_middleware.rb
|
108
|
+
- test/test_linux_tcp_info.rb
|
70
109
|
- test/test_middleware.rb
|
110
|
+
- test/test_middleware_unicorn.rb
|
111
|
+
- test/test_middleware_unicorn_ipv6.rb
|
71
112
|
- test/test_raindrops.rb
|
72
113
|
- test/test_raindrops_gc.rb
|
73
114
|
- test/test_struct.rb
|
115
|
+
- test/test_watcher.rb
|
74
116
|
has_rdoc: true
|
75
117
|
homepage: http://raindrops.bogomips.org/
|
76
118
|
licenses: []
|
77
119
|
|
78
120
|
post_install_message:
|
79
121
|
rdoc_options:
|
80
|
-
- -Na
|
81
122
|
- -t
|
82
123
|
- raindrops - real-time stats for preforking Rack servers
|
124
|
+
- -W
|
125
|
+
- http://bogomips.org/raindrops.git/tree/%s
|
83
126
|
require_paths:
|
84
127
|
- lib
|
85
128
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -87,30 +130,34 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
87
130
|
requirements:
|
88
131
|
- - ">="
|
89
132
|
- !ruby/object:Gem::Version
|
90
|
-
hash: 3
|
91
|
-
segments:
|
92
|
-
- 0
|
93
133
|
version: "0"
|
94
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
135
|
none: false
|
96
136
|
requirements:
|
97
137
|
- - ">="
|
98
138
|
- !ruby/object:Gem::Version
|
99
|
-
hash: 3
|
100
|
-
segments:
|
101
|
-
- 0
|
102
139
|
version: "0"
|
103
140
|
requirements: []
|
104
141
|
|
105
142
|
rubyforge_project: rainbows
|
106
|
-
rubygems_version: 1.
|
143
|
+
rubygems_version: 1.6.2
|
107
144
|
signing_key:
|
108
145
|
specification_version: 3
|
109
146
|
summary: real-time stats for preforking Rack servers
|
110
147
|
test_files:
|
148
|
+
- test/test_aggregate_pmq.rb
|
149
|
+
- test/test_inet_diag_socket.rb
|
150
|
+
- test/test_last_data_recv_unicorn.rb
|
111
151
|
- test/test_linux.rb
|
152
|
+
- test/test_linux_all_tcp_listen_stats.rb
|
153
|
+
- test/test_linux_all_tcp_listen_stats_leak.rb
|
154
|
+
- test/test_linux_ipv6.rb
|
112
155
|
- test/test_linux_middleware.rb
|
156
|
+
- test/test_linux_tcp_info.rb
|
113
157
|
- test/test_middleware.rb
|
158
|
+
- test/test_middleware_unicorn.rb
|
159
|
+
- test/test_middleware_unicorn_ipv6.rb
|
114
160
|
- test/test_raindrops.rb
|
115
161
|
- test/test_raindrops_gc.rb
|
116
162
|
- test/test_struct.rb
|
163
|
+
- test/test_watcher.rb
|
@@ -1,44 +0,0 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
|
-
|
3
|
-
# this is used to show or watch the number of active and queued
|
4
|
-
# connections on any listener socket from the command line
|
5
|
-
|
6
|
-
require 'raindrops'
|
7
|
-
require 'optparse'
|
8
|
-
require 'ipaddr'
|
9
|
-
usage = "Usage: #$0 [-d delay] ADDR..."
|
10
|
-
ARGV.size > 0 or abort usage
|
11
|
-
delay = false
|
12
|
-
|
13
|
-
# "normal" exits when driven on the command-line
|
14
|
-
trap(:INT) { exit 130 }
|
15
|
-
trap(:PIPE) { exit 0 }
|
16
|
-
|
17
|
-
opts = OptionParser.new('', 24, ' ') do |opts|
|
18
|
-
opts.banner = usage
|
19
|
-
opts.on('-d', '--delay=delay') { |nr| delay = nr.to_i }
|
20
|
-
opts.parse! ARGV
|
21
|
-
end
|
22
|
-
|
23
|
-
ARGV.each do |addr|
|
24
|
-
addr =~ %r{\A(127\..+):(\d+)\z} or next
|
25
|
-
host, port = $1, $2
|
26
|
-
hex_port = '%X' % port.to_i
|
27
|
-
ip_addr = IPAddr.new(host)
|
28
|
-
hex_host = ip_addr.hton.each_byte.inject('') { |s,o| s << '%02X' % o }
|
29
|
-
socks = File.readlines('/proc/net/tcp')
|
30
|
-
hex_addr = "#{hex_host}:#{hex_port}"
|
31
|
-
if socks.grep(/^\s+\d+:\s+#{hex_addr}\s+/).empty? &&
|
32
|
-
! socks.grep(/^\s+\d+:\s+00000000:#{hex_port}\s+/).empty?
|
33
|
-
warn "W: #{host}:#{port} (#{hex_addr}) not found in /proc/net/tcp"
|
34
|
-
warn "W: Did you mean 0.0.0.0:#{port}?"
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
fmt = "% 19s % 10u % 10u\n"
|
39
|
-
printf fmt.tr('u','s'), *%w(address active queued)
|
40
|
-
|
41
|
-
begin
|
42
|
-
stats = Raindrops::Linux.tcp_listener_stats(ARGV)
|
43
|
-
stats.each { |addr,stats| printf fmt, addr, stats.active, stats.queued }
|
44
|
-
end while delay && sleep(delay)
|