lib/sensu-plugins-puma/puma_ctl.rb
require 'json'
require 'socket'
require 'yaml'
class PumaCtl
class UnknownCommand < StandardError; end
attr_reader :state_file
def initialize(state_file: '/tmp/puma.state', control_auth_token: nil, control_url: nil)
@state_file = state_file
@control_auth_token = control_auth_token
@control_url = control_url
end
def control_auth_token
@control_auth_token ||= puma_options[:control_auth_token]
end
def control_url
@control_url ||= puma_options[:control_url]
end
def puma_options
@puma_options ||= begin
return nil unless File.exist?(state_file)
state = load_puma_state(state_file)
if state.key?('config')
# state is < v3.0.0
opts = state['config']['options']
{ control_url: opts[:control_url], control_auth_token: opts[:control_auth_token] }
else
# state is >= v3.0.0
{ control_url: state['control_url'], control_auth_token: state['control_auth_token'] }
end
end
end
def gc_stats
send_socket_command('gc-stats')
end
def stats
send_socket_command('stats')
end
private
def control_socket
type = nil
args = []
case control_url
when /^unix:\/\//
type = :unix
args = [control_url.gsub('unix://', '')]
when /^tcp:\/\//
type = :tcp
args = control_url.gsub('tcp://', '').split(':')
else
return nil
end
Socket.send(type, *args) do |socket|
yield socket
end
end
def load_puma_state(path)
raw = File.read(path)
sanitized = raw.gsub(/!ruby\/object:.*$/, '')
YAML.load(sanitized)
end
def send_socket_command(cmd)
out = control_socket do |socket|
socket.print("GET /#{cmd}?token=#{control_auth_token} HTTP/1.0\r\n\r\n")
result = socket.read
raise UnknownCommand, cmd if result =~ /^HTTP\/1.0 404/
result
end
JSON.parse(out.split("\r\n").last)
end
end