raindrops-maintained 0.21.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.
- checksums.yaml +7 -0
- data/.document +7 -0
- data/.gitattributes +4 -0
- data/.gitignore +16 -0
- data/.manifest +62 -0
- data/.olddoc.yml +16 -0
- data/COPYING +165 -0
- data/GIT-VERSION-FILE +1 -0
- data/GIT-VERSION-GEN +40 -0
- data/GNUmakefile +4 -0
- data/LATEST +9 -0
- data/LICENSE +16 -0
- data/NEWS +384 -0
- data/README +101 -0
- data/TODO +3 -0
- data/archive/.gitignore +3 -0
- data/archive/slrnpull.conf +4 -0
- data/examples/linux-listener-stats.rb +122 -0
- data/examples/middleware.ru +5 -0
- data/examples/watcher.ru +4 -0
- data/examples/watcher_demo.ru +13 -0
- data/examples/yahns.conf.rb +30 -0
- data/examples/zbatery.conf.rb +16 -0
- data/ext/raindrops/extconf.rb +163 -0
- data/ext/raindrops/linux_inet_diag.c +713 -0
- data/ext/raindrops/my_fileno.h +16 -0
- data/ext/raindrops/raindrops.c +487 -0
- data/ext/raindrops/raindrops_atomic.h +23 -0
- data/ext/raindrops/tcp_info.c +245 -0
- data/lib/raindrops/aggregate/last_data_recv.rb +94 -0
- data/lib/raindrops/aggregate/pmq.rb +245 -0
- data/lib/raindrops/aggregate.rb +8 -0
- data/lib/raindrops/last_data_recv.rb +102 -0
- data/lib/raindrops/linux.rb +77 -0
- data/lib/raindrops/middleware/proxy.rb +40 -0
- data/lib/raindrops/middleware.rb +153 -0
- data/lib/raindrops/struct.rb +62 -0
- data/lib/raindrops/watcher.rb +428 -0
- data/lib/raindrops.rb +72 -0
- data/pkg.mk +151 -0
- data/raindrops-maintained.gemspec +1 -0
- data/raindrops.gemspec +26 -0
- data/setup.rb +1586 -0
- data/test/ipv6_enabled.rb +9 -0
- data/test/rack_unicorn.rb +11 -0
- data/test/test_aggregate_pmq.rb +65 -0
- data/test/test_inet_diag_socket.rb +16 -0
- data/test/test_last_data_recv.rb +57 -0
- data/test/test_last_data_recv_unicorn.rb +69 -0
- data/test/test_linux.rb +281 -0
- 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 +166 -0
- data/test/test_linux_middleware.rb +64 -0
- data/test/test_linux_reuseport_tcp_listen_stats.rb +51 -0
- data/test/test_middleware.rb +128 -0
- data/test/test_middleware_unicorn.rb +37 -0
- data/test/test_middleware_unicorn_ipv6.rb +37 -0
- data/test/test_raindrops.rb +207 -0
- data/test/test_raindrops_gc.rb +38 -0
- data/test/test_struct.rb +54 -0
- data/test/test_tcp_info.rb +88 -0
- data/test/test_watcher.rb +186 -0
- metadata +193 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
require 'test/unit'
|
3
|
+
require 'raindrops'
|
4
|
+
|
5
|
+
class TestRaindropsGc < Test::Unit::TestCase
|
6
|
+
|
7
|
+
# we may need to create more garbage as GC may be less aggressive
|
8
|
+
# about expiring things. This is completely unrealistic code,
|
9
|
+
# though...
|
10
|
+
def test_gc
|
11
|
+
assert_nothing_raised do
|
12
|
+
1000000.times { |i| Raindrops.new(24); [] }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
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
|
data/test/test_struct.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'raindrops'
|
3
|
+
|
4
|
+
class TestRaindrops < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_struct_new
|
7
|
+
@rw = Raindrops::Struct.new(:r, :w)
|
8
|
+
assert @rw.kind_of?(Class)
|
9
|
+
end
|
10
|
+
|
11
|
+
TMP = Raindrops::Struct.new(:r, :w)
|
12
|
+
|
13
|
+
def test_init_basic
|
14
|
+
tmp = TMP.new
|
15
|
+
assert_equal 0, tmp.r
|
16
|
+
assert_equal 1, tmp.incr_r
|
17
|
+
assert_equal 1, tmp.r
|
18
|
+
assert_equal({ :r => 1, :w => 0 }, tmp.to_hash)
|
19
|
+
|
20
|
+
assert_equal 1, tmp[0]
|
21
|
+
assert_equal 0, tmp[1]
|
22
|
+
assert_equal [ :r, :w ], TMP::MEMBERS
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_init
|
26
|
+
tmp = TMP.new(5, 6)
|
27
|
+
assert_equal({ :r => 5, :w => 6 }, tmp.to_hash)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_dup
|
31
|
+
a = TMP.new(5, 6)
|
32
|
+
b = a.dup
|
33
|
+
assert_equal({ :r => 5, :w => 6 }, b.to_hash)
|
34
|
+
assert_nothing_raised { 4.times { b.decr_r } }
|
35
|
+
assert_equal({ :r => 1, :w => 6 }, b.to_hash)
|
36
|
+
assert_equal({ :r => 5, :w => 6 }, a.to_hash)
|
37
|
+
end
|
38
|
+
|
39
|
+
class Foo < Raindrops::Struct.new(:a, :b, :c, :d)
|
40
|
+
def to_ary
|
41
|
+
@raindrops.to_ary
|
42
|
+
end
|
43
|
+
|
44
|
+
def hello
|
45
|
+
"world"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_subclass
|
50
|
+
assert_equal [0, 0, 0, 0], Foo.new.to_ary
|
51
|
+
assert_equal "world", Foo.new.hello
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
require 'test/unit'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'raindrops'
|
5
|
+
require 'socket'
|
6
|
+
require 'pp'
|
7
|
+
$stderr.sync = $stdout.sync = true
|
8
|
+
class TestTCP_Info < Test::Unit::TestCase
|
9
|
+
|
10
|
+
TEST_ADDR = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
|
11
|
+
|
12
|
+
# Linux kernel commit 5ee3afba88f5a79d0bff07ddd87af45919259f91
|
13
|
+
TCP_INFO_useful_listenq = `uname -r`.strip >= '2.6.24'
|
14
|
+
|
15
|
+
def test_tcp_server_unacked
|
16
|
+
return if RUBY_PLATFORM !~ /linux/ # unacked not implemented on others...
|
17
|
+
s = TCPServer.new(TEST_ADDR, 0)
|
18
|
+
rv = Raindrops::TCP_Info.new s
|
19
|
+
c = TCPSocket.new TEST_ADDR, s.addr[1]
|
20
|
+
tmp = Raindrops::TCP_Info.new s
|
21
|
+
TCP_INFO_useful_listenq and assert_equal 1, tmp.unacked
|
22
|
+
|
23
|
+
assert_equal 0, rv.unacked
|
24
|
+
a = s.accept
|
25
|
+
tmp = Raindrops::TCP_Info.new s
|
26
|
+
assert_equal 0, tmp.unacked
|
27
|
+
before = tmp.object_id
|
28
|
+
|
29
|
+
tmp.get!(s)
|
30
|
+
assert_equal before, tmp.object_id
|
31
|
+
|
32
|
+
ensure
|
33
|
+
[ c, a, s ].compact.each(&:close)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_accessors
|
37
|
+
s = TCPServer.new TEST_ADDR, 0
|
38
|
+
tmp = Raindrops::TCP_Info.new s
|
39
|
+
tcp_info_methods = tmp.methods - Object.new.methods
|
40
|
+
assert tcp_info_methods.size >= 32
|
41
|
+
tcp_info_methods.each do |m|
|
42
|
+
next if m.to_sym == :get!
|
43
|
+
next if ! tmp.respond_to?(m)
|
44
|
+
val = tmp.__send__ m
|
45
|
+
assert_kind_of Integer, val
|
46
|
+
assert val >= 0
|
47
|
+
end
|
48
|
+
assert tmp.respond_to?(:state), 'every OS knows about TCP state, right?'
|
49
|
+
ensure
|
50
|
+
s.close
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_tcp_server_delayed
|
54
|
+
delay = 0.010
|
55
|
+
delay_ms = (delay * 1000).to_i
|
56
|
+
s = TCPServer.new(TEST_ADDR, 0)
|
57
|
+
c = TCPSocket.new TEST_ADDR, s.addr[1]
|
58
|
+
c.syswrite "."
|
59
|
+
sleep(delay * 1.2)
|
60
|
+
a = s.accept
|
61
|
+
i = Raindrops::TCP_Info.new(a)
|
62
|
+
assert i.last_data_recv >= delay_ms, "#{i.last_data_recv} < #{delay_ms}"
|
63
|
+
ensure
|
64
|
+
c.close if c
|
65
|
+
a.close if a
|
66
|
+
s.close
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_tcp_server_state_closed
|
70
|
+
s = TCPServer.new(TEST_ADDR, 0)
|
71
|
+
c = TCPSocket.new(TEST_ADDR, s.addr[1])
|
72
|
+
i = Raindrops::TCP_Info.allocate
|
73
|
+
a = s.accept
|
74
|
+
i.get!(a)
|
75
|
+
state = i.state
|
76
|
+
if Raindrops.const_defined?(:TCP)
|
77
|
+
assert_equal state, Raindrops::TCP[:ESTABLISHED]
|
78
|
+
end
|
79
|
+
c = c.close
|
80
|
+
sleep(0.01) # wait for kernel to update state
|
81
|
+
i.get!(a)
|
82
|
+
assert_not_equal state, i.state
|
83
|
+
ensure
|
84
|
+
s.close if s
|
85
|
+
c.close if c
|
86
|
+
a.close if a
|
87
|
+
end
|
88
|
+
end if defined? Raindrops::TCP_Info
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
require "test/unit"
|
3
|
+
require "raindrops"
|
4
|
+
begin
|
5
|
+
require 'aggregate'
|
6
|
+
require 'rack'
|
7
|
+
rescue LoadError => e
|
8
|
+
warn "W: #{e} skipping #{__FILE__}"
|
9
|
+
end
|
10
|
+
|
11
|
+
class TestWatcher < Test::Unit::TestCase
|
12
|
+
TEST_ADDR = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
|
13
|
+
def check_headers(headers)
|
14
|
+
%w(X-Count X-Std-Dev X-Min X-Max X-Mean
|
15
|
+
X-Outliers-Low X-Outliers-Low X-Last-Reset).each { |x|
|
16
|
+
assert_kind_of String, headers[x], "#{x} missing"
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def teardown
|
21
|
+
@app.shutdown
|
22
|
+
@ios.each { |io| io.close unless io.closed? }
|
23
|
+
end
|
24
|
+
|
25
|
+
def setup
|
26
|
+
@ios = []
|
27
|
+
@srv = TCPServer.new TEST_ADDR, 0
|
28
|
+
@ios << @srv
|
29
|
+
@port = @srv.addr[1]
|
30
|
+
@client = TCPSocket.new TEST_ADDR, @port
|
31
|
+
@addr = "#{TEST_ADDR}:#{@port}"
|
32
|
+
@ios << @client
|
33
|
+
@app = Raindrops::Watcher.new :delay => 0.001
|
34
|
+
@req = Rack::MockRequest.new @app
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_index
|
38
|
+
resp = @req.get "/"
|
39
|
+
assert_equal 200, resp.status.to_i
|
40
|
+
t = Time.parse resp.headers["Last-Modified"]
|
41
|
+
assert_in_delta Time.now.to_f, t.to_f, 2.0
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_active_txt
|
45
|
+
resp = @req.get "/active/#@addr.txt"
|
46
|
+
assert_equal 200, resp.status.to_i
|
47
|
+
assert_equal "text/plain", resp.headers["Content-Type"]
|
48
|
+
check_headers(resp.headers)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_invalid
|
52
|
+
assert_nothing_raised do
|
53
|
+
@req.get("/active/666.666.666.666%3A666.txt")
|
54
|
+
@req.get("/queued/666.666.666.666%3A666.txt")
|
55
|
+
@req.get("/active/666.666.666.666%3A666.html")
|
56
|
+
@req.get("/queued/666.666.666.666%3A666.html")
|
57
|
+
end
|
58
|
+
addr = @app.instance_eval do
|
59
|
+
@peak_active.keys + @peak_queued.keys +
|
60
|
+
@resets.keys + @active.keys + @queued.keys
|
61
|
+
end
|
62
|
+
assert addr.grep(/666\.666\.666\.666/).empty?, addr.inspect
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_active_html
|
66
|
+
resp = @req.get "/active/#@addr.html"
|
67
|
+
assert_equal 200, resp.status.to_i
|
68
|
+
assert_equal "text/html", resp.headers["Content-Type"]
|
69
|
+
check_headers(resp.headers)
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_queued_txt
|
73
|
+
resp = @req.get "/queued/#@addr.txt"
|
74
|
+
assert_equal 200, resp.status.to_i
|
75
|
+
assert_equal "text/plain", resp.headers["Content-Type"]
|
76
|
+
check_headers(resp.headers)
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_queued_html
|
80
|
+
resp = @req.get "/queued/#@addr.html"
|
81
|
+
assert_equal 200, resp.status.to_i
|
82
|
+
assert_equal "text/html", resp.headers["Content-Type"]
|
83
|
+
check_headers(resp.headers)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_reset
|
87
|
+
resp = @req.post "/reset/#@addr"
|
88
|
+
assert_equal 302, resp.status.to_i
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_tail
|
92
|
+
env = @req.class.env_for "/tail/#@addr.txt"
|
93
|
+
status, headers, body = @app.call env
|
94
|
+
assert_equal "text/plain", headers["Content-Type"]
|
95
|
+
assert_equal 200, status.to_i
|
96
|
+
tmp = []
|
97
|
+
body.each do |x|
|
98
|
+
assert_kind_of String, x
|
99
|
+
tmp << x
|
100
|
+
break if tmp.size > 1
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_tail_queued_min
|
105
|
+
env = @req.class.env_for "/tail/#@addr.txt?queued_min=1"
|
106
|
+
status, headers, body = @app.call env
|
107
|
+
assert_equal "text/plain", headers["Content-Type"]
|
108
|
+
assert_equal 200, status.to_i
|
109
|
+
tmp = []
|
110
|
+
body.each do |x|
|
111
|
+
tmp = TCPSocket.new TEST_ADDR, @port
|
112
|
+
@ios << tmp
|
113
|
+
assert_kind_of String, x
|
114
|
+
assert_equal 1, x.strip.split(/\s+/).last.to_i
|
115
|
+
break
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_x_current_header
|
120
|
+
env = @req.class.env_for "/active/#@addr.txt"
|
121
|
+
_status, headers, _body = @app.call(env)
|
122
|
+
assert_equal "0", headers["X-Current"], headers.inspect
|
123
|
+
|
124
|
+
env = @req.class.env_for "/queued/#@addr.txt"
|
125
|
+
_status, headers, _body = @app.call(env)
|
126
|
+
assert_equal "1", headers["X-Current"], headers.inspect
|
127
|
+
|
128
|
+
@ios << @srv.accept
|
129
|
+
sleep 0.1
|
130
|
+
|
131
|
+
env = @req.class.env_for "/queued/#@addr.txt"
|
132
|
+
_status, headers, _body = @app.call(env)
|
133
|
+
assert_equal "0", headers["X-Current"], headers.inspect
|
134
|
+
|
135
|
+
env = @req.class.env_for "/active/#@addr.txt"
|
136
|
+
_status, headers, _body = @app.call(env)
|
137
|
+
assert_equal "1", headers["X-Current"], headers.inspect
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_peaks
|
141
|
+
env = @req.class.env_for "/active/#@addr.txt"
|
142
|
+
_status, headers, _body = @app.call(env.dup)
|
143
|
+
start = headers["X-First-Peak-At"]
|
144
|
+
assert headers["X-First-Peak-At"], headers.inspect
|
145
|
+
assert headers["X-Last-Peak-At"], headers.inspect
|
146
|
+
assert_nothing_raised { Time.parse(headers["X-First-Peak-At"]) }
|
147
|
+
assert_nothing_raised { Time.parse(headers["X-Last-Peak-At"]) }
|
148
|
+
before = headers["X-Last-Peak-At"]
|
149
|
+
|
150
|
+
env = @req.class.env_for "/queued/#@addr.txt"
|
151
|
+
_status, headers, _body = @app.call(env)
|
152
|
+
assert_nothing_raised { Time.parse(headers["X-First-Peak-At"]) }
|
153
|
+
assert_nothing_raised { Time.parse(headers["X-Last-Peak-At"]) }
|
154
|
+
assert_equal before, headers["X-Last-Peak-At"], "should not change"
|
155
|
+
|
156
|
+
sleep 2
|
157
|
+
env = @req.class.env_for "/active/#@addr.txt"
|
158
|
+
_status, headers, _body = @app.call(env.dup)
|
159
|
+
assert_equal before, headers["X-Last-Peak-At"], headers.inspect
|
160
|
+
|
161
|
+
@ios << @srv.accept
|
162
|
+
begin
|
163
|
+
@srv.accept_nonblock
|
164
|
+
assert false, "we should not get here"
|
165
|
+
rescue => e
|
166
|
+
assert_kind_of Errno::EAGAIN, e
|
167
|
+
end
|
168
|
+
sleep 0.1
|
169
|
+
env = @req.class.env_for "/queued/#@addr.txt"
|
170
|
+
_status, headers, _body = @app.call(env.dup)
|
171
|
+
assert headers["X-Last-Peak-At"], headers.inspect
|
172
|
+
assert_nothing_raised { Time.parse(headers["X-Last-Peak-At"]) }
|
173
|
+
assert before != headers["X-Last-Peak-At"]
|
174
|
+
|
175
|
+
queued_before = headers["X-Last-Peak-At"]
|
176
|
+
|
177
|
+
sleep 2
|
178
|
+
|
179
|
+
env = @req.class.env_for "/queued/#@addr.txt"
|
180
|
+
_status, headers, _body = @app.call(env)
|
181
|
+
assert_equal "0", headers["X-Current"]
|
182
|
+
assert_nothing_raised { Time.parse(headers["X-Last-Peak-At"]) }
|
183
|
+
assert_equal queued_before, headers["X-Last-Peak-At"], "should not change"
|
184
|
+
assert_equal start, headers["X-First-Peak-At"]
|
185
|
+
end
|
186
|
+
end if RUBY_PLATFORM =~ /linux/ && defined?(Aggregate) && defined?(Rack)
|
metadata
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: raindrops-maintained
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.21.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- raindrops hackers
|
8
|
+
bindir: bin
|
9
|
+
cert_chain: []
|
10
|
+
date: 2024-03-19 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: aggregate
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '0.2'
|
19
|
+
type: :development
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '0.2'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: test-unit
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '3.0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '3.0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: posix_mq
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '2.0'
|
47
|
+
type: :development
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.0'
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: rack
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.2'
|
61
|
+
- - "<"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '4'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '1.2'
|
71
|
+
- - "<"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '4'
|
74
|
+
description: |-
|
75
|
+
raindrops is a real-time stats toolkit to show statistics for Rack HTTP
|
76
|
+
servers. It is designed for preforking servers such as unicorn, but
|
77
|
+
should support any Rack HTTP server on platforms supporting POSIX shared
|
78
|
+
memory. It may also be used as a generic scoreboard for sharing atomic
|
79
|
+
counters across multiple processes.
|
80
|
+
email: raindrops-public@yhbt.net
|
81
|
+
executables: []
|
82
|
+
extensions:
|
83
|
+
- ext/raindrops/extconf.rb
|
84
|
+
extra_rdoc_files:
|
85
|
+
- README
|
86
|
+
- LICENSE
|
87
|
+
- NEWS
|
88
|
+
- ext/raindrops/raindrops.c
|
89
|
+
- ext/raindrops/linux_inet_diag.c
|
90
|
+
- ext/raindrops/tcp_info.c
|
91
|
+
files:
|
92
|
+
- ".document"
|
93
|
+
- ".gitattributes"
|
94
|
+
- ".gitignore"
|
95
|
+
- ".manifest"
|
96
|
+
- ".olddoc.yml"
|
97
|
+
- COPYING
|
98
|
+
- GIT-VERSION-FILE
|
99
|
+
- GIT-VERSION-GEN
|
100
|
+
- GNUmakefile
|
101
|
+
- LATEST
|
102
|
+
- LICENSE
|
103
|
+
- NEWS
|
104
|
+
- README
|
105
|
+
- TODO
|
106
|
+
- archive/.gitignore
|
107
|
+
- archive/slrnpull.conf
|
108
|
+
- examples/linux-listener-stats.rb
|
109
|
+
- examples/middleware.ru
|
110
|
+
- examples/watcher.ru
|
111
|
+
- examples/watcher_demo.ru
|
112
|
+
- examples/yahns.conf.rb
|
113
|
+
- examples/zbatery.conf.rb
|
114
|
+
- ext/raindrops/extconf.rb
|
115
|
+
- ext/raindrops/linux_inet_diag.c
|
116
|
+
- ext/raindrops/my_fileno.h
|
117
|
+
- ext/raindrops/raindrops.c
|
118
|
+
- ext/raindrops/raindrops_atomic.h
|
119
|
+
- ext/raindrops/tcp_info.c
|
120
|
+
- lib/raindrops.rb
|
121
|
+
- lib/raindrops/aggregate.rb
|
122
|
+
- lib/raindrops/aggregate/last_data_recv.rb
|
123
|
+
- lib/raindrops/aggregate/pmq.rb
|
124
|
+
- lib/raindrops/last_data_recv.rb
|
125
|
+
- lib/raindrops/linux.rb
|
126
|
+
- lib/raindrops/middleware.rb
|
127
|
+
- lib/raindrops/middleware/proxy.rb
|
128
|
+
- lib/raindrops/struct.rb
|
129
|
+
- lib/raindrops/watcher.rb
|
130
|
+
- pkg.mk
|
131
|
+
- raindrops-maintained.gemspec
|
132
|
+
- raindrops.gemspec
|
133
|
+
- setup.rb
|
134
|
+
- test/ipv6_enabled.rb
|
135
|
+
- test/rack_unicorn.rb
|
136
|
+
- test/test_aggregate_pmq.rb
|
137
|
+
- test/test_inet_diag_socket.rb
|
138
|
+
- test/test_last_data_recv.rb
|
139
|
+
- test/test_last_data_recv_unicorn.rb
|
140
|
+
- test/test_linux.rb
|
141
|
+
- test/test_linux_all_tcp_listen_stats.rb
|
142
|
+
- test/test_linux_all_tcp_listen_stats_leak.rb
|
143
|
+
- test/test_linux_ipv6.rb
|
144
|
+
- test/test_linux_middleware.rb
|
145
|
+
- test/test_linux_reuseport_tcp_listen_stats.rb
|
146
|
+
- test/test_middleware.rb
|
147
|
+
- test/test_middleware_unicorn.rb
|
148
|
+
- test/test_middleware_unicorn_ipv6.rb
|
149
|
+
- test/test_raindrops.rb
|
150
|
+
- test/test_raindrops_gc.rb
|
151
|
+
- test/test_struct.rb
|
152
|
+
- test/test_tcp_info.rb
|
153
|
+
- test/test_watcher.rb
|
154
|
+
homepage: https://yhbt.net/raindrops/
|
155
|
+
licenses:
|
156
|
+
- LGPL-2.1+
|
157
|
+
metadata: {}
|
158
|
+
rdoc_options: []
|
159
|
+
require_paths:
|
160
|
+
- lib
|
161
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: 1.9.3
|
166
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
167
|
+
requirements:
|
168
|
+
- - ">="
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '0'
|
171
|
+
requirements: []
|
172
|
+
rubygems_version: 3.6.0.dev
|
173
|
+
specification_version: 4
|
174
|
+
summary: real-time stats for preforking Rack servers
|
175
|
+
test_files:
|
176
|
+
- test/test_aggregate_pmq.rb
|
177
|
+
- test/test_inet_diag_socket.rb
|
178
|
+
- test/test_last_data_recv.rb
|
179
|
+
- test/test_last_data_recv_unicorn.rb
|
180
|
+
- test/test_linux.rb
|
181
|
+
- test/test_linux_all_tcp_listen_stats.rb
|
182
|
+
- test/test_linux_all_tcp_listen_stats_leak.rb
|
183
|
+
- test/test_linux_ipv6.rb
|
184
|
+
- test/test_linux_middleware.rb
|
185
|
+
- test/test_linux_reuseport_tcp_listen_stats.rb
|
186
|
+
- test/test_middleware.rb
|
187
|
+
- test/test_middleware_unicorn.rb
|
188
|
+
- test/test_middleware_unicorn_ipv6.rb
|
189
|
+
- test/test_raindrops.rb
|
190
|
+
- test/test_raindrops_gc.rb
|
191
|
+
- test/test_struct.rb
|
192
|
+
- test/test_tcp_info.rb
|
193
|
+
- test/test_watcher.rb
|