Created
June 9, 2014 07:51
-
-
Save geoffgarside/4094103127003e95b63b to your computer and use it in GitHub Desktop.
Unbound Control Stats Collector
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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