class PingdomToGraphite::CLI
Public Instance Methods
advice()
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 78 def advice load_config! total_checks = @config["pingdom"]["checks"].count calls_per_check = 2 + (total_checks) puts "You have #{total_checks} monitored checks. Given a 48000/day API limit:" every_minutes = 5 begin daily_calls = 60*24 / every_minutes * calls_per_check puts "Every #{every_minutes} Minutes: #{daily_calls}/day - #{daily_calls < 48000 ? "WORKS" : "won't work"}" every_minutes += 5 end until (daily_calls < 48000) end
backfill(check_id)
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 164 def backfill(check_id) load_config! load_state! # Check the state file if @state.has_key?(check_id) && @state[check_id].has_key?("earliest_ts") earliest_ts = @state[check_id.to_s]["earliest_ts"] else error("You can't backfill a check you've never run an update on.") end load_probe_list! load_check_list! datapull = get_datapull chunk = 10 unless limit = options.limit limit = ask("You have #{datapull.effective_limit} API calls remaining. How many would you like to use?").to_i end created_ts = datapull.check(check_id).created # Keep within the API limits working_towards = (earliest_ts - created_ts) > 2678400 ? 31.days.ago.to_i : created_ts puts "Backfilling from #{Time.at(earliest_ts)} working towards #{Time.at(working_towards)}. Check began on #{Time.at(created_ts)}" # Break it into chunks additions = 0 (limit.to_i.div(chunk)+1).times do batch_count = pull_and_push(check_id, working_towards, earliest_ts, chunk) puts "#{batch_count} metrics pushed in this batch." if options.verbose additions += batch_count end puts "#{additions} metrics sent to graphite for check #{check_id}." end
init()
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 31 def init config_path = File.expand_path(options.config) if File.exists?(config_path) error("Config file already exists. (#{options.config})") else # Make sure we have a directory to put the config in unless File.directory?(File.dirname(config_path)) FileUtils.mkdir_p(File.dirname(config_path), :mode => 0700) end # A nice little defaults file. settings = { "pingdom" => { "username" => "YOUR_USERNAME", "password" => "YOUR_PASSWORD", "key" => "YOUR_API_KEY", "checks" => ["CHECK_ID_1","CHECK_ID_2"] }, "graphite" => { "host" => "YOUR_SERVER", "port" => "2003", "prefix" => "pingdom" } } File.open(File.expand_path(options.config),"w",0600) do |f| f.write(JSON.pretty_generate(settings)) end end end
init_checks(check_regex=nil)
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 66 def init_checks(check_regex=nil) @check_regex = check_regex load_config! load_check_list! @config["pingdom"]["checks"] = @checks.keys File.open(File.expand_path(options.config),"w",0600) do |f| f.write(JSON.pretty_generate(@config)) end puts "Added #{@checks.count} checks to #{options.config}" end
list()
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 92 def list load_check_list! @checks.each do |check_id, check| puts "#{check.name} (#{check.id}) - #{check.status}" end end
probes()
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 100 def probes load_probe_list! @probes.each do |probe_id, probe| puts "#{probe.countryiso} - #{probe.city}" end end
results(check_id)
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 118 def results(check_id) load_config! load_probe_list! start_time = (options.start_time) ? DateTime.parse(options.start_time).to_i : Time.now.to_i - 3600 end_time = (options.end_time) ? DateTime.parse(options.end_time).to_i : Time.now.to_i if start_time - end_time > 2764800 error("Date range must be less then 32 days.") end datapull = get_datapull datapull.results(check_id, start_time, end_time).each do |result| #<Pingdom::Result probeid: 33 time: 1343945109 status: "up" responsetime: 1103 statusdesc: "OK" statusdesclong: "OK"> puts "#{Time.at(result.time)}: #{result.status} - #{result.responsetime}ms (#{@probes[result.probeid].name})" end puts datapull.friendly_limit end
update()
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 136 def update load_config! load_state! load_probe_list! load_check_list! datapull = get_datapull @config["pingdom"]["checks"].each do |check_id| puts "Check #{check_id}: " if options.verbose # Check the state file check_state = @state.has_key?(check_id.to_s) ? @state[check_id.to_s] : Hash.new latest_ts = check_state.has_key?("latest_ts") ? check_state["latest_ts"] : 1.hour.ago.to_i # API limits to 2764800 seconds, so we'll use that (minutes 30 seconds) limit_ts = 2764770.seconds.ago.to_i latest_ts = (latest_ts.to_i < limit_ts) ? limit_ts : latest_ts new_records = pull_and_push(check_id, latest_ts) puts "#{new_records} metrics sent to graphite for check #{check_id}." end puts datapull.friendly_limit end
Private Instance Methods
error(message)
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 325 def error(message) STDERR.puts "ERROR: #{message}" exit 1 end
get_datapull()
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 197 def get_datapull if @datapull.nil? load_config! @datapull = PingdomToGraphite::DataPull.new(@config["pingdom"]["username"], @config["pingdom"]["password"], @config["pingdom"]["key"], log_level) end @datapull end
get_datapush()
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 205 def get_datapush load_config! datapush = PingdomToGraphite::DataPush.new(@config["graphite"]["host"], @config["graphite"]["port"]) end
load_check_list!()
click to toggle source
Store the check list in the object for reference (less api calls)
# File lib/pingdom-to-graphite/cli.rb, line 259 def load_check_list! load_config! datapull = get_datapull @checks = Hash.new datapull.checks.each do |check| # {"name"=>"Autocomplete", "id"=>259103, "type"=>"http", "lastresponsetime"=>203173, # "status"=>"up", "lasttesttime"=>1298102416} if @check_regex if check.name =~ /#{@check_regex}/ @checks[check.id] = check end else @checks[check.id] = check end end end
load_config!()
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 210 def load_config! if @config.nil? config_file = File.expand_path(options.config) unless File.exists?(config_file) error("Missing config file (#{options.config})") end @config = JSON::parse(File.read(config_file)); end end
load_probe_list!()
click to toggle source
Store the list in the object for reference (less api calls)
# File lib/pingdom-to-graphite/cli.rb, line 247 def load_probe_list! config_file = File.expand_path(options.config) datapull = get_datapull @probes = Hash.new datapull.probes.each do |probe| # {"city"=>"Manchester", "name"=>"Manchester, UK", "country"=>"United Kingdom", # "countryiso"=>"GB", "id"=>46, "ip"=>"212.84.74.156", "hostname"=>"s424.pingdom.com", "active"=>true} @probes[probe.id] = probe end end
load_state!()
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 222 def load_state! state_file = File.expand_path(options.state) if File.exists?(state_file) @state = JSON::parse(File.read(state_file)) else @state = Hash.new end end
log_level()
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 330 def log_level options.verbose ? Logger::DEBUG : Logger::ERROR end
parse_result(check_id, result)
click to toggle source
Take a pingdom check, and return an Array of metrics to be passed to graphite
# File lib/pingdom-to-graphite/cli.rb, line 277 def parse_result(check_id, result) results = Array.new prefix = "#{@config["graphite"]["prefix"]}.#{@checks[check_id.to_i].class}." prefix += @checks[check_id.to_i].name.gsub(/ /,"_").gsub(/\./,"") check_status = result.status.eql?("up") ? 1 : 0 check_time = Time.at(result.time).to_i check_city = @probes[result.probe_id].city.gsub(/ /,"_").gsub(/\./,"") results << GraphiteMetric::Plaintext.new("#{prefix}.status.#{@probes[result.probe_id].countryiso}.#{check_city}", check_status, check_time) results << GraphiteMetric::Plaintext.new("#{prefix}.responsetime.#{@probes[result.probe_id].countryiso}.#{check_city}", result.responsetime, check_time) results.each { |metric| puts metric } if options.verbose results end
pull_and_push(check_id, latest_ts = nil, earlist_ts = nil, limit = nil)
click to toggle source
# File lib/pingdom-to-graphite/cli.rb, line 290 def pull_and_push(check_id, latest_ts = nil, earlist_ts = nil, limit = nil) datapull = get_datapull datapush = get_datapush load_state! # Check the state file check_state = @state.has_key?(check_id.to_s) ? @state[check_id.to_s] : Hash.new latest_stored = check_state.has_key?("latest_ts") ? check_state["latest_ts"] : nil earliest_stored = check_state.has_key?("earliest_ts") ? check_state["earliest_ts"] : nil # Pull the data rec_count = 0 result_list = Array.new begin datapull.full_results(check_id, latest_ts, earlist_ts, limit).each do |result| result_list += parse_result(check_id, result) latest_stored = result.time if latest_stored.nil? || result.time > latest_stored earliest_stored = result.time if earliest_stored.nil? || result.time < earliest_stored rec_count += 1 end rescue Pingdom::Error => e error("Caught error from Pingdom: #{e}") end # Push to graphite begin datapush.to_graphite(result_list) unless result_list.empty? rescue Exception => e error("Failed to push to graphite: #{e}") end # Store the state @state[check_id] = Hash.new @state[check_id]["latest_ts"] = latest_stored @state[check_id]["earliest_ts"] = earliest_stored write_state! rec_count end
write_state!()
click to toggle source
Write the state to disk
# File lib/pingdom-to-graphite/cli.rb, line 232 def write_state! state_file = File.expand_path(options.state) # If the state dir doesn't exist create it first to prevent errors unless File.directory?(File.dirname(state_file)) FileUtils.mkdir_p(File.dirname(state_file), :mode => 0700) end File.open(state_file,"w",0600) do |f| f.write(JSON.generate(@state)) end end