raindrops-maintained 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.document +7 -0
  3. data/.gitattributes +4 -0
  4. data/.gitignore +16 -0
  5. data/.manifest +62 -0
  6. data/.olddoc.yml +16 -0
  7. data/COPYING +165 -0
  8. data/GIT-VERSION-FILE +1 -0
  9. data/GIT-VERSION-GEN +40 -0
  10. data/GNUmakefile +4 -0
  11. data/LATEST +9 -0
  12. data/LICENSE +16 -0
  13. data/NEWS +384 -0
  14. data/README +101 -0
  15. data/TODO +3 -0
  16. data/archive/.gitignore +3 -0
  17. data/archive/slrnpull.conf +4 -0
  18. data/examples/linux-listener-stats.rb +122 -0
  19. data/examples/middleware.ru +5 -0
  20. data/examples/watcher.ru +4 -0
  21. data/examples/watcher_demo.ru +13 -0
  22. data/examples/yahns.conf.rb +30 -0
  23. data/examples/zbatery.conf.rb +16 -0
  24. data/ext/raindrops/extconf.rb +163 -0
  25. data/ext/raindrops/linux_inet_diag.c +713 -0
  26. data/ext/raindrops/my_fileno.h +16 -0
  27. data/ext/raindrops/raindrops.c +487 -0
  28. data/ext/raindrops/raindrops_atomic.h +23 -0
  29. data/ext/raindrops/tcp_info.c +245 -0
  30. data/lib/raindrops/aggregate/last_data_recv.rb +94 -0
  31. data/lib/raindrops/aggregate/pmq.rb +245 -0
  32. data/lib/raindrops/aggregate.rb +8 -0
  33. data/lib/raindrops/last_data_recv.rb +102 -0
  34. data/lib/raindrops/linux.rb +77 -0
  35. data/lib/raindrops/middleware/proxy.rb +40 -0
  36. data/lib/raindrops/middleware.rb +153 -0
  37. data/lib/raindrops/struct.rb +62 -0
  38. data/lib/raindrops/watcher.rb +428 -0
  39. data/lib/raindrops.rb +72 -0
  40. data/pkg.mk +151 -0
  41. data/raindrops-maintained.gemspec +1 -0
  42. data/raindrops.gemspec +26 -0
  43. data/setup.rb +1586 -0
  44. data/test/ipv6_enabled.rb +9 -0
  45. data/test/rack_unicorn.rb +11 -0
  46. data/test/test_aggregate_pmq.rb +65 -0
  47. data/test/test_inet_diag_socket.rb +16 -0
  48. data/test/test_last_data_recv.rb +57 -0
  49. data/test/test_last_data_recv_unicorn.rb +69 -0
  50. data/test/test_linux.rb +281 -0
  51. data/test/test_linux_all_tcp_listen_stats.rb +66 -0
  52. data/test/test_linux_all_tcp_listen_stats_leak.rb +43 -0
  53. data/test/test_linux_ipv6.rb +166 -0
  54. data/test/test_linux_middleware.rb +64 -0
  55. data/test/test_linux_reuseport_tcp_listen_stats.rb +51 -0
  56. data/test/test_middleware.rb +128 -0
  57. data/test/test_middleware_unicorn.rb +37 -0
  58. data/test/test_middleware_unicorn_ipv6.rb +37 -0
  59. data/test/test_raindrops.rb +207 -0
  60. data/test/test_raindrops_gc.rb +38 -0
  61. data/test/test_struct.rb +54 -0
  62. data/test/test_tcp_info.rb +88 -0
  63. data/test/test_watcher.rb +186 -0
  64. 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
@@ -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