1
0
Fork 0
mirror of https://github.com/puma/puma.git synced 2022-11-09 13:48:40 -05:00

Change Puma.stats to return a hash instead of a JSON string (#2086)

Having access to the hash allows to produce stats in other ways (such as StatsD) without having to parse JSON of data that is available in memory. An example of this workaround is fa6ba1f507/lib/puma/plugin/statsd.rb (L112-L114)
This commit is contained in:
Bart 2019-12-17 00:38:48 -05:00 committed by Nate Berkopec
parent fe44f8c7fc
commit 1bec245b63
6 changed files with 41 additions and 18 deletions

View file

@ -3,6 +3,7 @@
* Features * Features
* Add pumactl `thread-backtraces` command to print thread backtraces (#2053) * Add pumactl `thread-backtraces` command to print thread backtraces (#2053)
* 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)
* Bugfixes * Bugfixes
* Your bugfix goes here (#Github Number) * Your bugfix goes here (#Github Number)

View file

@ -54,7 +54,7 @@ module Puma
rack_response(200, GC.stat.to_json) rack_response(200, GC.stat.to_json)
when /\/stats$/ when /\/stats$/
rack_response(200, @cli.stats) rack_response(200, @cli.stats.to_json)
when /\/thread-backtraces$/ when /\/thread-backtraces$/
backtraces = [] backtraces = []

View file

@ -73,7 +73,7 @@ module Puma
@first_term_sent = nil @first_term_sent = nil
@started_at = Time.now @started_at = Time.now
@last_checkin = Time.now @last_checkin = Time.now
@last_status = '{}' @last_status = {}
@term = false @term = false
end end
@ -94,7 +94,11 @@ module Puma
def ping!(status) def ping!(status)
@last_checkin = Time.now @last_checkin = Time.now
@last_status = status captures = status.match(/{ "backlog":(?<backlog>\d*), "running":(?<running>\d*), "pool_capacity":(?<pool_capacity>\d*), "max_threads": (?<max_threads>\d*) }/)
@last_status = captures.names.inject({}) do |hash, key|
hash[key.to_sym] = captures[key].to_i
hash
end
end end
def ping_timeout?(which) def ping_timeout?(which)
@ -352,9 +356,26 @@ module Puma
# the master process. # the master process.
def stats def stats
old_worker_count = @workers.count { |w| w.phase != @phase } old_worker_count = @workers.count { |w| w.phase != @phase }
booted_worker_count = @workers.count { |w| w.booted? } worker_status = @workers.map do |w|
worker_status = '[' + @workers.map { |w| %Q!{ "started_at": "#{w.started_at.utc.iso8601}", "pid": #{w.pid}, "index": #{w.index}, "phase": #{w.phase}, "booted": #{w.booted?}, "last_checkin": "#{w.last_checkin.utc.iso8601}", "last_status": #{w.last_status} }!}.join(",") + ']' {
%Q!{ "started_at": "#{@started_at.utc.iso8601}", "workers": #{@workers.size}, "phase": #{@phase}, "booted_workers": #{booted_worker_count}, "old_workers": #{old_worker_count}, "worker_status": #{worker_status} }! started_at: w.started_at.utc.iso8601,
pid: w.pid,
index: w.index,
phase: w.phase,
booted: w.booted?,
last_checkin: w.last_checkin.utc.iso8601,
last_status: w.last_status,
}
end
{
started_at: @started_at.utc.iso8601,
workers: @workers.size,
phase: @phase,
booted_workers: worker_status.count { |w| w[:booted] },
old_workers: old_worker_count,
worker_status: worker_status,
}
end end
def preload? def preload?

View file

@ -14,11 +14,13 @@ module Puma
# that this inherits from. # that this inherits from.
class Single < Runner class Single < Runner
def stats def stats
b = @server.backlog || 0 {
r = @server.running || 0 started_at: @started_at.utc.iso8601,
t = @server.pool_capacity || 0 backlog: @server.backlog || 0,
m = @server.max_threads || 0 running: @server.running || 0,
%Q!{ "started_at": "#{@started_at.utc.iso8601}", "backlog": #{b}, "running": #{r}, "pool_capacity": #{t}, "max_threads": #{m} }! pool_capacity: @server.pool_capacity || 0,
max_threads: @server.max_threads || 0,
}
end end
def restart def restart

View file

@ -24,7 +24,7 @@ class TestAppStatus < Minitest::Test
end end
def stats def stats
"{}" {}
end end
end end

View file

@ -57,8 +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}/, 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 }/, Puma.stats)
ensure ensure
cli.launcher.stop cli.launcher.stop
@ -92,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}/
assert_match(expected_stats, body.split(/\r?\n/).last) assert_match(expected_stats, body.split(/\r?\n/).last)
assert_match(expected_stats, Puma.stats) assert_equal([:started_at, :backlog, :running, :pool_capacity, :max_threads], Puma.stats.keys)
ensure ensure
cli.launcher.stop cli.launcher.stop
@ -137,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\}\},\{"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)
ensure ensure
if UNIX_SKT_EXIST && HAS_FORK if UNIX_SKT_EXIST && HAS_FORK
cli.launcher.stop cli.launcher.stop
@ -172,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}/, body.split("\r\n").last)
ensure ensure
if UNIX_SKT_EXIST if UNIX_SKT_EXIST
cli.launcher.stop cli.launcher.stop