mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
Instrument requests count (#2106)
* Instrument requests count * Fix existing tests * Add history * add new test
This commit is contained in:
parent
6f59df8dc0
commit
a391634a34
6 changed files with 65 additions and 7 deletions
|
@ -5,6 +5,7 @@
|
||||||
* Configuration: `environment` is read from `RAILS_ENV`, if `RACK_ENV` can't be found (#2022)
|
* Configuration: `environment` is read from `RAILS_ENV`, if `RACK_ENV` can't be found (#2022)
|
||||||
* `Puma.stats` now returns a Hash instead of a JSON string (#2086)
|
* `Puma.stats` now returns a Hash instead of a JSON string (#2086)
|
||||||
* `GC.compact` is called before fork if available (#2093)
|
* `GC.compact` is called before fork if available (#2093)
|
||||||
|
* Add `requests_count` to workers stats. (#2106)
|
||||||
|
|
||||||
* Bugfixes
|
* Bugfixes
|
||||||
* Your bugfix goes here (#Github Number)
|
* Your bugfix goes here (#Github Number)
|
||||||
|
|
|
@ -94,7 +94,7 @@ module Puma
|
||||||
|
|
||||||
def ping!(status)
|
def ping!(status)
|
||||||
@last_checkin = Time.now
|
@last_checkin = Time.now
|
||||||
captures = status.match(/{ "backlog":(?<backlog>\d*), "running":(?<running>\d*), "pool_capacity":(?<pool_capacity>\d*), "max_threads": (?<max_threads>\d*) }/)
|
captures = status.match(/{ "backlog":(?<backlog>\d*), "running":(?<running>\d*), "pool_capacity":(?<pool_capacity>\d*), "max_threads": (?<max_threads>\d*), "requests_count": (?<requests_count>\d*) }/)
|
||||||
@last_status = captures.names.inject({}) do |hash, key|
|
@last_status = captures.names.inject({}) do |hash, key|
|
||||||
hash[key.to_sym] = captures[key].to_i
|
hash[key.to_sym] = captures[key].to_i
|
||||||
hash
|
hash
|
||||||
|
@ -296,7 +296,8 @@ module Puma
|
||||||
r = server.running || 0
|
r = server.running || 0
|
||||||
t = server.pool_capacity || 0
|
t = server.pool_capacity || 0
|
||||||
m = server.max_threads || 0
|
m = server.max_threads || 0
|
||||||
payload = %Q!#{base_payload}{ "backlog":#{b}, "running":#{r}, "pool_capacity":#{t}, "max_threads": #{m} }\n!
|
rc = server.requests_count || 0
|
||||||
|
payload = %Q!#{base_payload}{ "backlog":#{b}, "running":#{r}, "pool_capacity":#{t}, "max_threads": #{m}, "requests_count": #{rc} }\n!
|
||||||
io << payload
|
io << payload
|
||||||
rescue IOError
|
rescue IOError
|
||||||
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
Thread.current.purge_interrupt_queue if Thread.current.respond_to? :purge_interrupt_queue
|
||||||
|
|
|
@ -36,6 +36,7 @@ module Puma
|
||||||
|
|
||||||
attr_reader :thread
|
attr_reader :thread
|
||||||
attr_reader :events
|
attr_reader :events
|
||||||
|
attr_reader :requests_count
|
||||||
attr_accessor :app
|
attr_accessor :app
|
||||||
|
|
||||||
attr_accessor :min_threads
|
attr_accessor :min_threads
|
||||||
|
@ -85,6 +86,8 @@ module Puma
|
||||||
@mode = :http
|
@mode = :http
|
||||||
|
|
||||||
@precheck_closing = true
|
@precheck_closing = true
|
||||||
|
|
||||||
|
@requests_count = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_accessor :binder, :leak_stack_on_error, :early_hints
|
attr_accessor :binder, :leak_stack_on_error, :early_hints
|
||||||
|
@ -626,6 +629,8 @@ module Puma
|
||||||
#
|
#
|
||||||
# Finally, it'll return +true+ on keep-alive connections.
|
# Finally, it'll return +true+ on keep-alive connections.
|
||||||
def handle_request(req, lines)
|
def handle_request(req, lines)
|
||||||
|
@requests_count +=1
|
||||||
|
|
||||||
env = req.env
|
env = req.env
|
||||||
client = req.io
|
client = req.io
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ module Puma
|
||||||
running: @server.running || 0,
|
running: @server.running || 0,
|
||||||
pool_capacity: @server.pool_capacity || 0,
|
pool_capacity: @server.pool_capacity || 0,
|
||||||
max_threads: @server.max_threads || 0,
|
max_threads: @server.max_threads || 0,
|
||||||
|
requests_count: @server.requests_count || 0,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ class TestCLI < Minitest::Test
|
||||||
body = s.read
|
body = s.read
|
||||||
s.close
|
s.close
|
||||||
|
|
||||||
assert_match(/{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":16,"max_threads":16}/, body.split(/\r?\n/).last)
|
assert_match(/{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":16,"max_threads":16,"requests_count":0}/, body.split(/\r?\n/).last)
|
||||||
|
|
||||||
ensure
|
ensure
|
||||||
cli.launcher.stop
|
cli.launcher.stop
|
||||||
|
@ -91,9 +91,9 @@ class TestCLI < Minitest::Test
|
||||||
body = http.request(req).body
|
body = http.request(req).body
|
||||||
end
|
end
|
||||||
|
|
||||||
expected_stats = /{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":16,"max_threads":16}/
|
expected_stats = /{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":16,"max_threads":16,"requests_count":0}/
|
||||||
assert_match(expected_stats, body.split(/\r?\n/).last)
|
assert_match(expected_stats, body.split(/\r?\n/).last)
|
||||||
assert_equal([:started_at, :backlog, :running, :pool_capacity, :max_threads], Puma.stats.keys)
|
assert_equal([:started_at, :backlog, :running, :pool_capacity, :max_threads, :requests_count], Puma.stats.keys)
|
||||||
|
|
||||||
ensure
|
ensure
|
||||||
cli.launcher.stop
|
cli.launcher.stop
|
||||||
|
@ -136,7 +136,7 @@ class TestCLI < Minitest::Test
|
||||||
body = s.read
|
body = s.read
|
||||||
s.close
|
s.close
|
||||||
|
|
||||||
assert_match(/\{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","workers":2,"phase":0,"booted_workers":2,"old_workers":0,"worker_status":\[\{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","pid":\d+,"index":0,"phase":0,"booted":true,"last_checkin":"[^"]+","last_status":\{"backlog":0,"running":2,"pool_capacity":2,"max_threads":2\}\},\{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","pid":\d+,"index":1,"phase":0,"booted":true,"last_checkin":"[^"]+","last_status":\{"backlog":0,"running":2,"pool_capacity":2,"max_threads":2\}\}\]\}/, body.split("\r\n").last)
|
assert_match(/\{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","workers":2,"phase":0,"booted_workers":2,"old_workers":0,"worker_status":\[\{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","pid":\d+,"index":0,"phase":0,"booted":true,"last_checkin":"[^"]+","last_status":\{"backlog":0,"running":2,"pool_capacity":2,"max_threads":2,"requests_count":0\}\},\{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","pid":\d+,"index":1,"phase":0,"booted":true,"last_checkin":"[^"]+","last_status":\{"backlog":0,"running":2,"pool_capacity":2,"max_threads":2,"requests_count":0\}\}\]\}/, body.split("\r\n").last)
|
||||||
ensure
|
ensure
|
||||||
if UNIX_SKT_EXIST && HAS_FORK
|
if UNIX_SKT_EXIST && HAS_FORK
|
||||||
cli.launcher.stop
|
cli.launcher.stop
|
||||||
|
@ -171,7 +171,7 @@ class TestCLI < Minitest::Test
|
||||||
body = s.read
|
body = s.read
|
||||||
s.close
|
s.close
|
||||||
|
|
||||||
assert_match(/{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":16,"max_threads":16}/, body.split("\r\n").last)
|
assert_match(/{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":16,"max_threads":16,"requests_count":0}/, body.split("\r\n").last)
|
||||||
ensure
|
ensure
|
||||||
if UNIX_SKT_EXIST
|
if UNIX_SKT_EXIST
|
||||||
cli.launcher.stop
|
cli.launcher.stop
|
||||||
|
@ -202,6 +202,48 @@ class TestCLI < Minitest::Test
|
||||||
t.join if UNIX_SKT_EXIST
|
t.join if UNIX_SKT_EXIST
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_control_requests_count
|
||||||
|
tcp = UniquePort.call
|
||||||
|
cntl = UniquePort.call
|
||||||
|
url = "tcp://127.0.0.1:#{cntl}/"
|
||||||
|
|
||||||
|
cli = Puma::CLI.new ["-b", "tcp://127.0.0.1:#{tcp}",
|
||||||
|
"--control-url", url,
|
||||||
|
"--control-token", "",
|
||||||
|
"test/rackup/lobster.ru"], @events
|
||||||
|
|
||||||
|
t = Thread.new do
|
||||||
|
cli.run
|
||||||
|
end
|
||||||
|
|
||||||
|
wait_booted
|
||||||
|
|
||||||
|
s = TCPSocket.new "127.0.0.1", cntl
|
||||||
|
s << "GET /stats HTTP/1.0\r\n\r\n"
|
||||||
|
body = s.read
|
||||||
|
s.close
|
||||||
|
|
||||||
|
assert_match(/{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":\d+,"running":\d+,"pool_capacity":\d+,"max_threads":\d+,"requests_count":0}/, body.split(/\r?\n/).last)
|
||||||
|
|
||||||
|
# send real requests to server
|
||||||
|
3.times do
|
||||||
|
s = TCPSocket.new "127.0.0.1", tcp
|
||||||
|
s << "GET / HTTP/1.0\r\n\r\n"
|
||||||
|
body = s.read
|
||||||
|
s.close
|
||||||
|
end
|
||||||
|
|
||||||
|
s = TCPSocket.new "127.0.0.1", cntl
|
||||||
|
s << "GET /stats HTTP/1.0\r\n\r\n"
|
||||||
|
body = s.read
|
||||||
|
s.close
|
||||||
|
|
||||||
|
assert_match(/{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":\d+,"running":\d+,"pool_capacity":\d+,"max_threads":\d+,"requests_count":3}/, body.split(/\r?\n/).last)
|
||||||
|
ensure
|
||||||
|
cli.launcher.stop
|
||||||
|
t.join
|
||||||
|
end
|
||||||
|
|
||||||
def test_control_thread_backtraces
|
def test_control_thread_backtraces
|
||||||
skip UNIX_SKT_MSG unless UNIX_SKT_EXIST
|
skip UNIX_SKT_MSG unless UNIX_SKT_EXIST
|
||||||
url = "unix://#{@tmp_path}"
|
url = "unix://#{@tmp_path}"
|
||||||
|
|
|
@ -38,6 +38,14 @@ class WebServerTest < Minitest::Test
|
||||||
assert @tester.ran_test, "Handler didn't really run"
|
assert @tester.ran_test, "Handler didn't really run"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_requests_count
|
||||||
|
assert_equal @server.requests_count, 0
|
||||||
|
3.times do
|
||||||
|
hit(["http://127.0.0.1:#{@server.connected_port}/test"])
|
||||||
|
end
|
||||||
|
assert_equal @server.requests_count, 3
|
||||||
|
end
|
||||||
|
|
||||||
def test_trickle_attack
|
def test_trickle_attack
|
||||||
socket = do_test(VALID_REQUEST, 3)
|
socket = do_test(VALID_REQUEST, 3)
|
||||||
assert_match "hello", socket.read
|
assert_match "hello", socket.read
|
||||||
|
|
Loading…
Add table
Reference in a new issue