Skip to content

Instantly share code, notes, and snippets.

@geoffgarside
Created June 9, 2014 07:51
Show Gist options
  • Save geoffgarside/4094103127003e95b63b to your computer and use it in GitHub Desktop.
Save geoffgarside/4094103127003e95b63b to your computer and use it in GitHub Desktop.
Unbound Control Stats Collector
#!/usr/bin/env ruby
#
# Unbound Stats Collector
# sends unbound-control stats output to a batsd/statsd server
#
#
# source 'https://rubygems.org'
# gem 'statsd-ruby'
#
require 'rubygems'
require 'optparse' # GETOPT
require 'statsd'
require 'socket'
def whereis(binary)
PATH.each do |path|
bin = File.join(path, binary)
return bin if File.exists?(bin) && File.executable?(bin)
end
nil
end
PATH = ENV['PATH'].split(':')
options = { :host => '127.0.0.1', :port => 8125,
:binary => whereis('unbound-control'),
:verbose => false, :debug => false ,
:namespace => 'unbound-control' }
OptionParser.new do |opts|
opts.banner = "Usage: example.rb [options]"
opts.on('-h', '--host NAME', 'Stats Server') do |v|
options[:host] = v
end
opts.on('-p', '--port NUMBER', 'Stats Server port') do |v|
options[:port] = v.to_i
end
opts.on('-b', '--binary PATH', 'Path to unbound-control. Useful for cron(8).') do |v|
options[:binary] = v
end
opts.on('-n', '--namespace STRING', 'Statsd stat key namespace') do |v|
options[:namespace] = v
end
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
options[:verbose] = v
end
opts.on("-d", "--[no-]debug", "Run with debugging") do |v|
options[:debug] = v
end
end.parse!
if options[:debug]
puts options.inspect
end
unbound = options[:binary]
if unbound.nil?
puts "Unable to find unbound-control in #{ENV['PATH']}"
exit(1)
end
stats_cmd = "#{unbound} stats"
hostname = Socket.gethostname
statsd = Statsd.new(options[:host], options[:port])
statsd.namespace = options[:namespace]
reader, writer = IO.pipe
if options[:verbose]
puts "Starting Unbound Stats Collector"
end
send_thread = Thread.new do
puts "Starting Send Thread" if options[:verbose]
statsd.batch do |batch|
while line = reader.gets
break if line == ''
# Ignore historgram & threadX lines
next if line =~ /^(histogram|thread[0-9]+)\./
# mixin hostname
# split line by '=' into 2
key, value = line.split('=', 2)
hkey = "#{hostname}.#{key}"
case key
when /^total\.num\./, /^num\.query\./, /^num\.answer\./
puts "COUNT #{hkey} -> #{value}" if options[:verbose]
puts "COUNT #{key} -> #{value}" if options[:verbose]
batch.count hkey, value.to_i
batch.count key, value.to_i
when /^time\.up/
puts "GAUGE #{hkey} = #{value}" if options[:verbose]
batch.gauge hkey, value.to_f
when /^mem\.cache\./
puts "GAUGE #{hkey} = #{value}" if options[:verbose]
batch.gauge hkey, value.to_i
end
end
end
end
read_thread = Thread.new do
puts "Starting Read Thread" if options[:verbose]
IO.popen(stats_cmd) do |io|
io.each do |line|
puts "READ #{line}" if options[:debug]
writer.write(line)
end
end
writer.close
end
read_thread.join
send_thread.join
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment