Skip to content

Instantly share code, notes, and snippets.

@oogali
Created August 27, 2012 03:19
Show Gist options
  • Select an option

  • Save oogali/3485260 to your computer and use it in GitHub Desktop.

Select an option

Save oogali/3485260 to your computer and use it in GitHub Desktop.
broom sweep (ping collector)
#!/usr/bin/env ruby
require 'rubygems'
require 'redis/connection/hiredis'
require 'redis'
require 'json'
require 'socket'
require 'getoptlong'
require 'uri'
require 'logger'
require 'daemons'
def usage
puts "Usage: #{__FILE__} [-dhr]"
puts 'Collect ICMP echo replies for historical data'
puts 'Example: sweep'
puts
puts 'Configuration settings:'
puts " -r, --redis=URI\t\tconnect to Redis instance, in URI format (e.g. redis://127.0.0.1:6379)"
puts " -h, --hostname=HOSTNAME\toverride system hostname using specified argument"
puts " -d, --debug\t\t\tenable logging of debug messages"
puts
exit 1
end
hostname = nil
redis_uri = nil
logfile = STDOUT
logging_level = Logger::INFO
# parse command line arguments
options = GetoptLong.new(
[ '--help', '-?', GetoptLong::NO_ARGUMENT ],
[ '--debug', '-d', GetoptLong::NO_ARGUMENT ],
[ '--hostname', '-h', GetoptLong::REQUIRED_ARGUMENT ],
[ '--log', '-l', GetoptLong::REQUIRED_ARGUMENT ],
[ '--redis', '-r', GetoptLong::REQUIRED_ARGUMENT ]
)
options.each do |opt, arg|
case opt
when '--debug'
logging_level = Logger::DEBUG
when '--hostname'
hostname = arg
when '--log'
logfile = arg
when '--redis'
redis_uri = URI.parse arg
else
usage
end
end
# open logger
logger = Logger.new logfile
logger.level = Logger::INFO
logger.info 'Starting...'
hostname ||= Socket.gethostname
uri ||= URI.parse(ENV['REDIS_URL'] || 'redis://127.0.0.1:6379')
redis = nil
# connect to redis datastore
attempts = 0
begin
logger.info "Connecting to Redis (#{uri.to_s})"
redis = Redis.new(
:host => uri.host,
:port => uri.port || 6379,
:password => uri.password,
:db => uri.path
)
rescue => err
attempts += 1
logger.err "Could not connect to Redis @ #{uri.to_s}: #{err.to_s}"
if attempts % 5
logger.warn 'Sleeping for 300 seconds before next Redis connection attempt'
sleep 300
end
logger.warn "Retrying connection to Redis, attempt ##{attempts}"
retry
end
logger.info "Connected to Redis (#{redis.inspect.to_s})"
# create default configuration hash
config = {
:targets => %w[ 127.0.0.1 ],
:count => 5,
:interval => 900,
:splay => 60
}
# background this app
Daemons.daemonize
loop do
# store timestamp of last config grab
redis.hset 'broom::sweep/checkin', 'hostname}', Time.now.to_i
# get current configuration for this host
logger.info 'Refreshing configuration from store...'
config.merge! JSON.parse(redis.hget('broom::config', hostname)) rescue {}
config[:targets].each do |target|
logger.debug "Getting latency for #{target}"
capture = Time.now.to_i
# ping target, collect replies, store info in a hash
ping = %x[ping -c #{config[:count].to_i} #{target}]
replies = ping.each_line.inject({ :hostname => hostname, :ip => nil, :ttl => nil, :latency => [] }) do |response, line|
m = line.match /.*from\s+(\S+):.*ttl=(\d+)\s+time=(\S+)/
if m
response[:ip] = m[1]
response[:ttl] = m[2].to_i
response[:latency].push m[3].to_f
end
response
end
logger.debug "Storing serialized latency data for #{target}"
# store latency information
attempts = 0
begin
redis.hset "broom::sweep/#{hostname}/#{ping[:ip]}", capture, replies.to_json
rescue => err
attempts += 1
if attempts < 5
logger.err "Store failed (#{target}), retrying, attempt ##{attempts}..."
retry
else
logger.err "Store of data failed, giving up on [ #{capture} --> #{replies.to_json} ]"
end
end
end
# sleep for a random interval
wake_timeout = config[:interval].to_i + rand(config[:splay].to_i)
logger.info "Collection complete...sleeping for #{wake_timeout} seconds"
sleep wake_timeout
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment