diff --git a/lib/stats_socket.rb b/lib/stats_socket.rb new file mode 100644 index 00000000000..c2d11ef2920 --- /dev/null +++ b/lib/stats_socket.rb @@ -0,0 +1,63 @@ +require 'socket' + +class StatsSocket + + def initialize(socket_path) + @socket_path = socket_path + @server = nil + end + + def start + @server = UNIXServer.new(@socket_path) + @accept_thread = new_accept_thread + end + + def stop + @server.close if @server + @server = nil + end + + protected + + def new_accept_thread + server = @server + Thread.new do + done = false + while !done + done = !accept_connection(server) + end + end + end + + def accept_connection(server) + socket = nil + begin + socket = server.accept + rescue IOError + # socket was shut down or something catastrophic like that happened + return false + end + + line = socket.readline + socket.write get_response(line.strip) + socket.close + true + rescue IOError + # nothing to do here, case its normal on shutdown + rescue => e + Rails.logger.warn("Failed to handle connection in stats socket #{e}") + end + + def get_response(command) + result = + case command + when "gc_stat" + GC.stat.to_json + else + "[\"UNKNOWN COMMAND\"]" + end + + result << "\n" + end + +end diff --git a/spec/components/stats_socket_spec.rb b/spec/components/stats_socket_spec.rb new file mode 100644 index 00000000000..9352a6da531 --- /dev/null +++ b/spec/components/stats_socket_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' +require_dependency 'stats_socket' + +describe StatsSocket do + let :socket_path do + "#{Dir.tmpdir}/#{SecureRandom.hex}" + end + + let :stats_socket do + StatsSocket.new(socket_path) + end + + before do + stats_socket.start + end + + after do + stats_socket.stop + end + + it "can respond to various stats commands" do + line = nil + + # ensure this works more than once :) + 2.times do + socket = UNIXSocket.new(socket_path) + socket.send "gc_stat\n", 0 + line = socket.readline + socket.close + end + + parsed = JSON.parse(line) + + expect(parsed.keys.sort).to eq(GC.stat.keys.map(&:to_s).sort) + end + +end