raindrops 0.4.1 → 0.5.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.
- 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)
|