server/lib/minicron/alert.rb
require Minicron::REQUIRE_PATH + 'alert/email'
require Minicron::REQUIRE_PATH + 'alert/sms'
require Minicron::REQUIRE_PATH + 'alert/pagerduty'
require Minicron::REQUIRE_PATH + 'alert/aws_sns'
require Minicron::REQUIRE_PATH + 'alert/slack'
require Minicron::REQUIRE_PATH + 'hub/models/alert'
require Minicron::REQUIRE_PATH + 'hub/models/job'
module Minicron
# Allows the sending of alerts via multiple mediums
module Alert
# Send an alert using all enabled mediums
#
# @option options [String] kind 'fail' or 'miss'
# @option options [Integer] job_id used by the #send method
# @option options [Integer, nil] execution_id only used by 'fail' alerts
# @option options [Integer, nil] schedule_id only applies to 'miss' alerts
# @option options [Time] expected_at only applies to 'miss' alerts
def self.send_all(options = {})
Minicron.config['alerts'].each do |medium, value|
# Add the alert medium into the options hash so that it can be passed to sent?
options[:medium] = medium
# Check if the medium is enabled and alert hasn't already been sent
next unless value['enabled'] && !sent?(options)
send(
kind: options[:kind],
schedule_id: options[:schedule_id],
execution_id: options[:execution_id],
job_id: options[:job_id],
expected_at: options[:expected_at],
medium: options[:medium]
)
end
end
# Send an individual alert
#
# @option options [String] kind 'fail' or 'miss'
# @option options [Integer] job_id used to look up the job name for the alert message
# @option options [Integer, nil] execution_id only used by 'fail' alerts
# @option options [Integer, nil] schedule_id only applies to 'miss' alerts
# @option options [Time] expected_at when the schedule was expected to execute
# @option options [String] medium the medium to send the alert via
def self.send(options = {})
# Look up the job for this schedule
options[:job] = Minicron::Hub::Model::Job.find(options[:job_id])
# Switch the medium that the alert will be sent via
case options[:medium]
when 'email'
send_email(options)
when 'sms'
send_sms(options)
when 'pagerduty'
send_pagerduty(options)
when 'aws_sns'
send_aws_sns(options)
when 'slack'
send_slack(options)
else
raise Minicron::ArgumentError, "The medium '#{options[:medium]}' is not supported!"
end
# Store that we sent the alert
Minicron::Hub::Model::Alert.create(
user_id: options[:user_id],
job_id: options[:job_id],
execution_id: options[:execution_id],
schedule_id: options[:schedule_id],
kind: options[:kind],
expected_at: options[:expected_at],
medium: options[:medium],
sent_at: Time.now.utc
)
end
# Send an email alert, this has the same options as #send
def self.send_email(options = {})
email = Minicron::Alert::Email.new
email.send(
Minicron.config['alerts']['email']['from'],
Minicron.config['alerts']['email']['to'],
"minicron alert for job '#{options[:job].name}'!",
email.get_message(options)
)
end
# Send an sms alert, this has the same options as #send
def self.send_sms(options = {})
sms = Minicron::Alert::SMS.new
sms.send(
Minicron.config['alerts']['sms']['from'],
Minicron.config['alerts']['sms']['to'],
sms.get_message(options)
)
end
# Send a pagerduty alert, this has the same options as #send
def self.send_pagerduty(options = {})
pagerduty = Minicron::Alert::PagerDuty.new
pagerduty.send(
options[:kind] == 'fail' ? 'Job failed!' : 'Job missed!',
pagerduty.get_message(options)
)
end
# Send an aws sns alert, this has the same options as #send
def self.send_aws_sns(options = {})
sns = Minicron::Alert::AwsSns.new
sns.send(
"minicron alert for job '#{options[:job].name}'!",
sns.get_message(options)
)
end
# Send a slack alert, this has the same options as #send
def self.send_slack(options = {})
slack = Minicron::Alert::Slack.new
slack.send(
slack.get_message(options)
)
end
# Queries the database to determine if an alert for this kind has already
# been sent
#
# @option options [String] kind 'fail' or 'miss'
# @option options [Integer, nil] execution_id only used by 'fail' alerts
# @option options [Integer, nil] schedule_id only applies to 'miss' alerts
# @option options [Time] expected_at when the schedule was expected to execute
# @option options [String] medium the medium to send the alert via
def self.sent?(options = {})
Minicron::Hub::Model::Alert.exists?(
kind: options[:kind],
execution_id: options[:execution_id],
schedule_id: options[:schedule_id],
job_id: options[:job_id],
expected_at: options[:expected_at],
medium: options[:medium]
)
end
end
end