Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
delete, update, and add sentries works, pulling sentries configs via …
…json with http auth works, sentry.survey! works
- Loading branch information
Jonathan Hoyt
authored and
Jonathan Hoyt
committed
Dec 23, 2008
1 parent
a2cdd69
commit f6cd51a
Showing
13 changed files
with
327 additions
and
9 deletions.
There are no files selected for viewing
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,13 @@ | ||
class Event < ActiveRecord::Base | ||
belongs_to :recordable, :polymorphic => true | ||
end | ||
|
||
def has(word) | ||
self.message =~ /#{word}/ ? true : false | ||
end | ||
alias :have :has | ||
|
||
def message | ||
self.data | ||
end | ||
|
||
end |
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
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
# Loop. | ||
# Do any survey that either doesn't have a last_surveyed_at, or is past last_surveyed_at + survey_interval. And is not currently ignored. | ||
# Record last_surveyed_at | ||
# Notify if haven't notified too recently | ||
# Record last_notified_at | ||
# | ||
# Later: Partition groups of surveys into separate threads to get it done faster. | ||
require 'fileutils' | ||
|
||
def loggit!(msg) | ||
File.open("log/watcher.log", 'a') do |log| | ||
log << "[#{Time.now.strftime("%D %T")}] #{msg}\n" | ||
end | ||
msg | ||
end | ||
def store_pid(pid) | ||
File.open("log/watcher.pid", 'w'){|f| f.write("#{pid}\n")} | ||
end | ||
def delete_pidfile | ||
FileUtils.rm("log/watcher.pid") | ||
end | ||
|
||
def watch! | ||
# This will naturally migrate different surveys to need run slightly apart from one another. | ||
while(sleep(1)) | ||
Sentry.find(:all).each do |sentry| | ||
begin | ||
if (sentry.last_surveyed_at.nil? || Time.now > sentry.last_surveyed_at.to_time + sentry.survey_interval) | ||
begin | ||
success = sentry.survey! | ||
if success | ||
loggit! "SUCCESS #{sentry.device.name} / #{sentry.goggle.name}" | ||
sentry.last_notified_at = nil | ||
else !success | ||
loggit! "FAILURE #{sentry.device.name} / #{sentry.goggle.name}" | ||
if sentry.last_notified_at.nil? || (sentry.notifications_to_send > 1 && Time.now > sentry.last_notified_at.to_time + sentry.maximum_notify_frequency) | ||
if sentry.notify! | ||
sentry.last_notified_at = Time.now | ||
loggit! " -> NOTIFIED" | ||
else | ||
loggit! " -> Could Not Notify" | ||
end | ||
end | ||
end | ||
rescue => e | ||
STDERR << loggit!("ERROR - (#{sentry.device.name} / #{sentry.goggle.name}): #{e}") | ||
if sentry.last_notified_at.nil? || (sentry.notifications_to_send > 1 && Time.now > sentry.last_notified_at.to_time + sentry.maximum_notify_frequency) | ||
loggit! " -> NOTIFIED of ERROR" | ||
sentry.last_notified_at = Time.now if sentry.notify!("Sentry #{sentry.device.name} / #{sentry.goggle.name} errored: #{e}") | ||
end | ||
ensure | ||
sentry.last_surveyed_at = Time.now | ||
sentry.save | ||
end | ||
end | ||
rescue => e | ||
STDERR << loggit!("ERROR - Was going to cause exit on Sentry #{sentry.device.name}! Error: #{e}") | ||
sentry.notify!("Sentry #{sentry.device.name} Exit-causing error: #{e}", 'dcparker@gmail.com') | ||
end | ||
end | ||
end | ||
end | ||
|
||
watch! | ||
|
||
# | ||
# def start_daemon! | ||
# if File.exists?("log/watcher.pid") | ||
# pid = IO.read("log/watcher.pid").chomp.to_i | ||
# puts "Already running on process #{pid}!" | ||
# else | ||
# fork do | ||
# Process.setsid | ||
# exit if fork | ||
# at_exit { | ||
# delete_pidfile | ||
# loggit!('Daemon Stopped') | ||
# } | ||
# File.umask 0000 | ||
# STDIN.reopen "/dev/null" | ||
# trap("TERM") { exit } | ||
# trap("INT") { exit } | ||
# store_pid(Process.pid) | ||
# puts "Started Watcher Daemon on process #{Process.pid}." | ||
# STDOUT.reopen "/dev/null", "a" | ||
# STDERR.reopen "/dev/null" | ||
# loggit!('Daemon Starting...') | ||
# STDERR.reopen(File.open("log/watcher_errors.log", 'a')) | ||
# Merb::Config[:environment] = 'production' unless ARGV[1] == 'development' || Merb::Config[:environment] | ||
# ::Merb::BootLoader.initialize_merb | ||
# loggit!(' -> Started') | ||
# begin | ||
# watch! | ||
# rescue => e | ||
# STDERR << loggit!("Program error OUTSIDE loop! > #{e}") | ||
# email = Merb::Mailer.new(:to => 'dcparker@gmail.com', | ||
# :from => "imonit@sabretechllc.com", | ||
# :subject => "iMonit Daemon Stopped on ERROR", | ||
# :text => "Program error OUTSIDE loop! > #{e}") | ||
# email.deliver! | ||
# end | ||
# end | ||
# end | ||
# end | ||
# | ||
# def stop_daemon! | ||
# begin | ||
# pid = IO.read("log/watcher.pid").chomp.to_i | ||
# Process.kill("INT", pid) | ||
# loggit! "Daemon Stopped Manually :)" | ||
# puts "Stopped Watcher Daemon on process #{pid}" | ||
# rescue => k | ||
# puts "Failed to kill! #{k}" | ||
# ensure | ||
# exit | ||
# end | ||
# end | ||
# | ||
# case ARGV[0] | ||
# when 'start' | ||
# start_daemon! | ||
# when 'stop' | ||
# stop_daemon! | ||
# when 'log' | ||
# puts IO.read("log/watcher.log") | ||
# else | ||
# puts "Usage: ruby lib/daemon.rb start|stop|log" | ||
# end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
require 'statuslang/lang' | ||
module StatusLang | ||
def self.run(sentry_id,code) | ||
Lang.new(sentry_id).instance_eval(code) | ||
end | ||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
require 'statuslang/ruby_lang_extensions' | ||
module StatusLang | ||
class Lang | ||
def initialize(sentry_id) | ||
@sentry_id = sentry_id | ||
end | ||
|
||
def last(amount=nil) | ||
if amount | ||
if amount.is_a?(Duration) | ||
options[:after] = amount.ago | ||
elsif amount.is_a?(Integer) | ||
options[:limit] = amount | ||
else | ||
raise ArgumentError, "amount must be a Duration or an Integer!" | ||
end | ||
end | ||
self | ||
end | ||
|
||
def posts | ||
if @options[:after] | ||
Event.find(:all, :conditions => {:recordable_type => "Sentry", :recordable_id => @sentry_id, :created_at.gte => @options[:after]}) | ||
elsif @options[:limit] | ||
Event.find(:all, :conditions => {:recordable_type => "Sentry", :recordable_id => @sentry_id}, :limit => @options[:limit]) | ||
end | ||
end | ||
def post | ||
Event.find(:last, :conditions => {:recordable_type => "Sentry", :recordable_id => @sentry_id}) | ||
end | ||
def all_posts | ||
posts.all | ||
end | ||
def any_post | ||
posts.any | ||
end | ||
|
||
private | ||
def options | ||
@options ||= {} | ||
end | ||
end | ||
end |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
require 'simple_mapper' | ||
require 'net/http' | ||
require 'lib/nethttp_magic' | ||
|
||
module StatusLang | ||
# Post is a String class that is also a SimpleMapper persistence class reading from StatusPing.com. | ||
# The reason it is also a string is so that it can be treated as a simple string of the Message content itself if desired. | ||
# | ||
# To use, first set the options (which will be set per-feed) | ||
# StatusLang::Post.options(:feed_key => feed_key, :feed_secret => feed_secret) | ||
# then call just like any SimpleMapper model: Post.get(..query-params..). | ||
class Message < String | ||
include SimpleMapper::Persistence | ||
set_format :json | ||
set_entity_name 'message' | ||
add_connection_adapter(:http) do | ||
set_base_url 'http://statusping.com/messages' | ||
end | ||
has :properties | ||
property :feed | ||
property :created_by | ||
property :content | ||
property :created_at | ||
uses :callbacks | ||
add_callback('initialize_request') do |request,cboptions| | ||
# Add HTTP Basic Auth to the request | ||
# the nonce can technically be anything, but to be best secure we want it pretty randomly generated. | ||
nonce = Digest::SHA1.hexdigest("--#{rand(1234)}--#{Time.now.to_s}--#{rand(12345)}--") | ||
sequence = Time.now.to_f | ||
request.add_query_param(:nonce => nonce) | ||
request.basic_auth options[:feed_key], Digest::SHA1.hexdigest("#{nonce}#{options[:feed_secret]}") | ||
[request,cboptions] | ||
end | ||
def self.options(options=nil) | ||
Thread.current['statusping_options'] = options if options | ||
Thread.current['statusping_options'] ||= {} | ||
end | ||
|
||
# Sets the data into the object. This is provided as a default method, but your model can overwrite it any | ||
# way you want. For example, you could set the data to some other object type, or to a Marshalled storage. | ||
# The type of data you receive will depend on the format and parser you use. Of course you could make up | ||
# your own spin-off of one of those, too. | ||
def data=(data) | ||
raise TypeError, "data must be a hash" unless data.is_a?(Hash) | ||
data.each {|k,v| instance_variable_set("@#{k}", v)} | ||
self.replace(@content) | ||
end | ||
alias :update_data :data= | ||
|
||
|
||
# The following is for StatusLang. | ||
|
||
attr_accessor :any_all | ||
|
||
def has(word) | ||
self =~ /#{word}/ ? true : false | ||
end | ||
alias :have :has | ||
end | ||
end |
Oops, something went wrong.