From 86d885d2a3fa53543a3ebe4ffdc3784a2c72cec8 Mon Sep 17 00:00:00 2001 From: Noah Gibbs Date: Thu, 4 May 2017 15:17:59 -0700 Subject: [PATCH] Add /gc URL to status server to do a major GC. Add a /gc-status URL to get GC.stats as JSON. --- lib/puma/app/status.rb | 8 ++++++ lib/puma/control_cli.rb | 4 +-- test/test_cli.rb | 54 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/lib/puma/app/status.rb b/lib/puma/app/status.rb index f769536d6d..6f68c6b83e 100644 --- a/lib/puma/app/status.rb +++ b/lib/puma/app/status.rb @@ -55,6 +55,14 @@ def call(env) return rack_response(200, OK_STATUS) end + when /\/gc$/ + GC.start + return rack_response(200, OK_STATUS) + + when /\/gc-stats$/ + json = "{" + GC.stat.map { |k, v| "\"#{k}\": #{v}" }.join(",") + "}" + return rack_response(200, json) + when /\/stats$/ return rack_response(200, @cli.stats) else diff --git a/lib/puma/control_cli.rb b/lib/puma/control_cli.rb index acac7044e7..fb731b2d5b 100644 --- a/lib/puma/control_cli.rb +++ b/lib/puma/control_cli.rb @@ -9,7 +9,7 @@ module Puma class ControlCLI - COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory} + COMMANDS = %w{halt restart phased-restart start stats status stop reload-worker-directory gc gc-stats} def initialize(argv, stdout=STDOUT, stderr=STDERR) @state = nil @@ -169,7 +169,7 @@ def send_request end message "Command #{@command} sent success" - message response.last if @command == "stats" + message response.last if @command == "stats" || @command == "gc-stats" end @server.close diff --git a/test/test_cli.rb b/test/test_cli.rb index 891b5b9b7e..fe1729b804 100644 --- a/test/test_cli.rb +++ b/test/test_cli.rb @@ -145,6 +145,60 @@ def test_control_stop t.join end + def test_control_gc_stats + url = "unix://#{@tmp_path}" + + cli = Puma::CLI.new ["-b", "unix://#{@tmp_path2}", + "--control", url, + "--control-token", "", + "test/rackup/lobster.ru"], @events + + t = Thread.new { cli.run } + t.abort_on_exception = true + + wait_booted + + s = UNIXSocket.new @tmp_path + s << "GET /gc-stats HTTP/1.0\r\n\r\n" + body = s.read + s.close + + lines = body.split("\r\n") + json_line = lines.detect { |l| l[0] == "{" } + pairs = json_line.scan(/\"[^\"]+\": [^,]+/) + gc_stats = {} + pairs.each do |p| + p =~ /\"([^\"]+)\": ([^,]+)/ || raise("Can't parse #{p.inspect}!") + gc_stats[$1] = $2 + end + gc_count_before = gc_stats["count"].to_i + + s = UNIXSocket.new @tmp_path + s << "GET /gc HTTP/1.0\r\n\r\n" + body = s.read # Ignored + s.close + + s = UNIXSocket.new @tmp_path + s << "GET /gc-stats HTTP/1.0\r\n\r\n" + body = s.read + s.close + lines = body.split("\r\n") + json_line = lines.detect { |l| l[0] == "{" } + pairs = json_line.scan(/\"[^\"]+\": [^,]+/) + gc_stats = {} + pairs.each do |p| + p =~ /\"([^\"]+)\": ([^,]+)/ || raise("Can't parse #{p.inspect}!") + gc_stats[$1] = $2 + end + gc_count_after = gc_stats["count"].to_i + + # Hitting the /gc route should increment the count by 1 + assert_equal gc_count_before + 1, gc_count_after + + cli.launcher.stop + t.join + end + def test_tmp_control url = "tcp://127.0.0.1:8232" cli = Puma::CLI.new ["--state", @tmp_path, "--control", "auto"]