aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mauve/alert.rb15
-rw-r--r--lib/mauve/alert_changed.rb2
-rw-r--r--lib/mauve/alert_group.rb16
-rw-r--r--lib/mauve/configuration_builders/person.rb15
-rw-r--r--lib/mauve/notification.rb4
-rw-r--r--lib/mauve/notifiers.rb1
-rw-r--r--lib/mauve/notifiers/debug.rb2
-rw-r--r--lib/mauve/notifiers/sms_clockwork.rb72
l---------[-rw-r--r--]lib/mauve/notifiers/templates/email_subject.txt.erb23
l---------[-rw-r--r--]lib/mauve/notifiers/templates/sms.txt.erb23
-rw-r--r--lib/mauve/notifiers/templates/xmpp.html.erb6
-rw-r--r--lib/mauve/notifiers/templates/xmpp.txt.erb6
-rw-r--r--lib/mauve/person.rb123
-rw-r--r--lib/mauve/quick_update.rb166
-rw-r--r--lib/mauve/server.rb5
-rw-r--r--lib/mauve/version.rb2
16 files changed, 371 insertions, 110 deletions
diff --git a/lib/mauve/alert.rb b/lib/mauve/alert.rb
index a2033a5..24b9dae 100644
--- a/lib/mauve/alert.rb
+++ b/lib/mauve/alert.rb
@@ -824,7 +824,10 @@ module Mauve
#
alert.id = Alert.remove_html(alert.id.to_s)
- alert_db = first(:alert_id => alert.id, :source => update.source) ||
+ #
+ # Load the database alert, and all its properties, since we're updating.
+ #
+ alert_db = first(:alert_id => alert.id, :source => update.source, :fields => Alert.properties) ||
new(:alert_id => alert.id, :source => update.source)
##
@@ -850,6 +853,11 @@ module Mauve
alert_db.raised_at = nil
alert_db.will_raise_at = raise_time
end
+ else
+ #
+ # If no raise time has been set, then update the database to reflect this.
+ #
+ alert_db.raised_at = alert_db.will_raise_at = nil
end
if clear_time
@@ -863,6 +871,11 @@ module Mauve
alert_db.cleared_at = nil
alert_db.will_clear_at = clear_time
end
+ else
+ #
+ # If no clear time has been set, then update the database to reflect this.
+ #
+ alert_db.cleared_at = alert_db.will_clear_at = nil
end
#
diff --git a/lib/mauve/alert_changed.rb b/lib/mauve/alert_changed.rb
index 2b9dfe5..6925085 100644
--- a/lib/mauve/alert_changed.rb
+++ b/lib/mauve/alert_changed.rb
@@ -110,7 +110,7 @@ module Mauve
#
# Push this notifitcation onto the queue.
#
- Server.notification_push([alert, Time.now])
+ Server.notification_push([alert, self.remind_at])
end
#
diff --git a/lib/mauve/alert_group.rb b/lib/mauve/alert_group.rb
index fe78ad9..fe17516 100644
--- a/lib/mauve/alert_group.rb
+++ b/lib/mauve/alert_group.rb
@@ -236,15 +236,21 @@ module Mauve
# OK got the next reminder time.
#
unless remind_at.nil?
- this_reminder = AlertChanged.new(
- :level => level.to_s,
+ #
+ # Find the last reminder, if available for the same alert, update type, and person.
+ #
+ this_reminder = AlertChanged.first_or_new(
:alert_id => alert.id,
:person => self.name,
- :at => at,
:update_type => alert.update_type,
- :remind_at => remind_at,
- :was_relevant => true)
+ :remind_at.not => nil,
+ :remind_at.gt => at
+ )
+ this_reminder.level = level.to_s
+ this_reminder.at = at
+ this_reminder.remind_at = remind_at
+ this_reminder.was_relevant = true
this_reminder.save
end
diff --git a/lib/mauve/configuration_builders/person.rb b/lib/mauve/configuration_builders/person.rb
index f171d10..9cc09ab 100644
--- a/lib/mauve/configuration_builders/person.rb
+++ b/lib/mauve/configuration_builders/person.rb
@@ -51,10 +51,15 @@ module Mauve
def suppress_notifications_after(h)
raise ArgumentError.new("notification_threshold must be specified as e.g. (10 => 1.minute)") unless h.kind_of?(Hash)
- h.each do |k,v|
- raise ArgumentError.new("notification_threshold must be specified as e.g. (10 => 1.minute)") unless k.is_a?(Integer) and v.is_a?(Integer)
-
- @result.notification_thresholds[v] = Array.new(k)
+ h.each do |number_of_alerts,in_period|
+ raise ArgumentError.new("notification_threshold must be specified as e.g. (10 => 1.minute)") unless number_of_alerts.is_a?(Integer) and in_period.is_a?(Integer)
+
+ @result.suppress_notifications_after[in_period] = number_of_alerts
+ # History.all(
+ # :limit => number_of_alerts,
+ # :order => :created_at.desc,
+ # :type => "notification",
+ # :event.like => '% succeeded')
end
end
@@ -87,7 +92,7 @@ module Mauve
#
# Add a default notification threshold
#
- person.notification_thresholds[600] = Array.new(5) if person.notification_thresholds.empty?
+ person.suppress_notifications_after[600] = 5 if person.suppress_notifications_after.empty?
#
# Add a default notify clause
diff --git a/lib/mauve/notification.rb b/lib/mauve/notification.rb
index 745660a..c164afb 100644
--- a/lib/mauve/notification.rb
+++ b/lib/mauve/notification.rb
@@ -319,9 +319,7 @@ module Mauve
#
# A bit of alert de-bouncing.
#
- if already_sent_to.include?(person.username)
- logger.info("Already sent notification of #{alert} to #{person.username}")
- else
+ unless already_sent_to.include?(person.username)
person.send_alert(level, alert)
already_sent_to << person.username
end
diff --git a/lib/mauve/notifiers.rb b/lib/mauve/notifiers.rb
index 7276091..5a7acc0 100644
--- a/lib/mauve/notifiers.rb
+++ b/lib/mauve/notifiers.rb
@@ -1,6 +1,7 @@
require 'mauve/notifiers/email'
require 'mauve/notifiers/sms_default'
require 'mauve/notifiers/sms_aql'
+require 'mauve/notifiers/sms_clockwork'
require 'mauve/notifiers/xmpp'
module Mauve
diff --git a/lib/mauve/notifiers/debug.rb b/lib/mauve/notifiers/debug.rb
index a9afc52..b3e88e2 100644
--- a/lib/mauve/notifiers/debug.rb
+++ b/lib/mauve/notifiers/debug.rb
@@ -69,7 +69,7 @@ module Mauve
deliver_to_queue << [Time.now, self.class, destination, message] if deliver_to_queue
- if @disable_normal_delivery
+ if @disable_normal_delivery
true # pretend it happened OK if we're just testing
else
send_alert_without_debug(destination, alert, all_alerts, conditions)
diff --git a/lib/mauve/notifiers/sms_clockwork.rb b/lib/mauve/notifiers/sms_clockwork.rb
new file mode 100644
index 0000000..b4bd860
--- /dev/null
+++ b/lib/mauve/notifiers/sms_clockwork.rb
@@ -0,0 +1,72 @@
+require 'mauve/notifiers/debug'
+require 'cgi'
+
+module Mauve
+ module Notifiers
+ module Sms
+
+ require 'net/https'
+
+ class Clockwork
+ GATEWAY = "https://api.clockworksms.com/http/send.aspx"
+
+ attr_writer :apikey, :from
+ attr_reader :name
+
+ def initialize(name)
+ @name = name
+ end
+
+ def send_alert(destination, alert, all_alerts, conditions = {})
+ uri = URI.parse(GATEWAY)
+
+ opts_string = {
+ :key => @apikey,
+ :to => normalize_number(destination),
+ :content => prepare_message(destination, alert, all_alerts, conditions),
+ :from => @from,
+ }.map { |k,v| "#{k}=#{CGI::escape(v.to_s)}" }.join("&")
+
+ http = Net::HTTP.new(uri.host, uri.port)
+ if uri.port == 443
+ http.use_ssl = true
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ end
+ response, data = http.post(uri.path, opts_string, {
+ 'Content-Type' => 'application/x-www-form-urlencoded',
+ 'Content-Length' => opts_string.length.to_s
+ })
+
+ if response.kind_of?(Net::HTTPSuccess)
+ #
+ # Woo -- return true!
+ #
+ true
+ else
+ false
+ end
+ end
+
+ protected
+ def prepare_message(destination, alert, all_alerts, conditions={})
+ was_suppressed = conditions[:was_suppressed] || false
+ will_suppress = conditions[:will_suppress] || false
+
+ template_file = File.join(File.dirname(__FILE__),"templates","sms.txt.erb")
+
+ txt = if File.exists?(template_file)
+ ERB.new(File.read(template_file)).result(binding).chomp
+ else
+ logger.error("Could not find sms.txt.erb template")
+ alert.to_s
+ end
+ end
+
+ def normalize_number(n)
+ n.split("").select { |s| (?0..?9).include?(s[0]) }.join.gsub(/^0/, "44")
+ end
+ end
+ end
+ end
+end
+
diff --git a/lib/mauve/notifiers/templates/email_subject.txt.erb b/lib/mauve/notifiers/templates/email_subject.txt.erb
index 119c742..802c711 100644..120000
--- a/lib/mauve/notifiers/templates/email_subject.txt.erb
+++ b/lib/mauve/notifiers/templates/email_subject.txt.erb
@@ -1,22 +1 @@
-<%=alert.id %>: <%= alert.update_type.upcase %>: <%
-case alert.update_type
-when "cleared"
-%><%= alert.cleared_at.to_s_relative %><%
-when "acknowledged"
-%><%= alert.acknowledged_at.to_s_relative %> by <%= alert.acknowledged_by %> until <%= alert.will_unacknowledge_at.to_s_human %><%
-else
-%><%= alert.raised_at.to_s_relative %><%
-end
-%>: <%= alert.subject %>: <%= alert.summary %><%
-if alert.source != alert.subject
-%> -- from <%= alert.source %><%
-end
-%>. <%=WebInterface.url_for(alert)%><%
-if defined? was_suppressed and defined? will_suppress
- if was_suppressed and not will_suppress
-%> (Normal service has resumed.)<%
- elsif will_suppress and not was_suppressed
-%> (Further alerts suppressed until things calm down.)<%
- end
-end
-%>
+xmpp.txt.erb \ No newline at end of file
diff --git a/lib/mauve/notifiers/templates/sms.txt.erb b/lib/mauve/notifiers/templates/sms.txt.erb
index faec37d..802c711 100644..120000
--- a/lib/mauve/notifiers/templates/sms.txt.erb
+++ b/lib/mauve/notifiers/templates/sms.txt.erb
@@ -1,22 +1 @@
-<%= alert.update_type.upcase %>: <%
-case alert.update_type
-when "cleared"
-%><%= alert.cleared_at.to_s_relative %><%
-when "acknowledged"
-%><%= alert.acknowledged_at.to_s_relative %> by <%= alert.acknowledged_by %> until <%= alert.will_unacknowledge_at.to_s_human %><%
-else
-%><%= alert.raised_at.to_s_relative %><%
-end
-%>: <%= alert.subject %>: <%= alert.summary %><%
-if alert.source != alert.subject
-%> -- from <%= alert.source %><%
-end
-%>. <%=WebInterface.url_for(alert)%><%
-if defined? was_suppressed and defined? will_suppress
- if was_suppressed and not will_suppress
-%> (Normal service has resumed.)<%
- elsif will_suppress and not was_suppressed
-%> (Further alerts suppressed until things calm down.)<%
- end
-end
-%>
+xmpp.txt.erb \ No newline at end of file
diff --git a/lib/mauve/notifiers/templates/xmpp.html.erb b/lib/mauve/notifiers/templates/xmpp.html.erb
index 12354a2..7792bd9 100644
--- a/lib/mauve/notifiers/templates/xmpp.html.erb
+++ b/lib/mauve/notifiers/templates/xmpp.html.erb
@@ -1,5 +1,5 @@
<html xmlns="http://jabber.org/protocol/xhtml-im"><body xmlns="http://www.w3.org/1999/xhtml">
-<a href="<%=WebInterface.url_for(alert)%>"><%= alert.id%>: <%= alert.update_type.upcase %></a>: <%
+<a href="<%=WebInterface.url_for(alert)%>"><%= alert.id%>: <%= alert.update_type.upcase %></a> (<%= alert.level %>): <%
case alert.update_type
when "cleared"
%><%= alert.cleared_at.to_s_relative %><%
@@ -15,9 +15,9 @@ end
%>.<%
if defined? was_suppressed and defined? will_suppress
if was_suppressed and not will_suppress
-%><br /><em>Normal service has resumed.</em><%
+%><br /><em>Normal service for <%= alert.level %> alerts has resumed.</em><%
elsif will_suppress and not was_suppressed
-%><br /><em>Further alerts suppressed until things calm down.</em><%
+%><br /><em>Further <%= alert.level %> alerts suppressed until things calm down.</em><%
end
end
%></body></html>
diff --git a/lib/mauve/notifiers/templates/xmpp.txt.erb b/lib/mauve/notifiers/templates/xmpp.txt.erb
index f63c96c..c148f41 100644
--- a/lib/mauve/notifiers/templates/xmpp.txt.erb
+++ b/lib/mauve/notifiers/templates/xmpp.txt.erb
@@ -1,4 +1,4 @@
-<%=alert.id %>: <%= alert.update_type.upcase %>: <%
+<%=alert.id %>: <%= alert.update_type.upcase %> (<%= alert.level %>): <%
case alert.update_type
when "cleared"
%><%= alert.cleared_at.to_s_relative %><%
@@ -14,9 +14,9 @@ end
%>. <%=WebInterface.url_for(alert)%><%
if defined? was_suppressed and defined? will_suppress
if was_suppressed and not will_suppress
-%> (Normal service has resumed.)<%
+%> (Normal service for <%= alert.level %> alerts has resumed.)<%
elsif will_suppress and not was_suppressed
-%> (Further alerts suppressed until things calm down.)<%
+%> (Further <%= alert.level %> alerts suppressed until things calm down.)<%
end
end
%>
diff --git a/lib/mauve/person.rb b/lib/mauve/person.rb
index 979c0ab..1158cbf 100644
--- a/lib/mauve/person.rb
+++ b/lib/mauve/person.rb
@@ -6,13 +6,12 @@ module Mauve
class Person
attr_reader :username, :password, :urgent, :normal, :low, :email, :xmpp, :sms
- attr_reader :notification_thresholds, :last_pop3_login, :suppressed, :notifications
+ attr_reader :last_pop3_login, :suppressed, :notifications
attr_reader :notify_when_off_sick, :notify_when_on_holiday
# Set up a new Person
#
def initialize(username)
- @notification_thresholds = nil
@suppressed = false
#
# TODO fix up web login so pop3 can be used as a proxy.
@@ -107,34 +106,85 @@ module Mauve
# Works out if a notification should be suppressed. If no parameters are supplied, it will
#
+ # @param [Symbol] Level of notification that is being tested
# @param [Time] Theoretical time of notification
# @param [Time] Current time.
# @return [Boolean] If suppression is needed.
- def should_suppress?(with_notification_at = nil, now = Time.now)
+ def should_suppress?(level, with_notification_at = nil, now = Time.now)
- return self.notification_thresholds.any? do |period, previous_alert_times|
+ self.suppress_notifications_after.any? do |period, number|
#
- # This is going to work out if we would be suppressed if
- if with_notification_at.nil?
- first = previous_alert_times.first
- last = previous_alert_times.last
+ # When testing if the next alert will suppress, we know that if only
+ # one alert is needed to suppress, then this function should always
+ # return true.
+ #
+ return true if with_notification_at and number <= 1
+
+ #
+ # Here are the previous notifications set to this person in the last period.
+ #
+ previous_notifications = History.all(
+ :user => self.username, :type => "notification",
+ :created_at.gte => now - period, :created_at.lte => now,
+ :event.like => '% succeeded',
+ :order => :created_at.desc)
+
+ #
+ # Defintely not suppressed if no notifications have been found.
+ #
+ return false if previous_notifications.count == 0
+
+ #
+ # If we're suppressed already, we need to check the time of the last alert sent
+ #
+ if @suppressed
+
+ if with_notification_at.is_a?(Time)
+ latest = with_notification_at
+ else
+ latest = previous_notifications.first.created_at
+ end
+
+ #
+ # We should not suppress this alert if the last one was sent ages ago
+ #
+ if (now - latest) >= period
+ return false
+ end
+
else
- first = previous_alert_times[1]
- last = with_notification_at
+ #
+ # We do not suppress if we can't find a sufficient number of previous alerts
+ #
+ if previous_notifications.count < (with_notification_at.nil? ? number : number - 1)
+ return false
+ end
+
end
-
- (first.is_a?(Time) and (now - first) < period) or
- (last.is_a?(Time) and @suppressed and (now - last) < period)
+
+ #
+ # If we're at the lowest level, return true now.
+ #
+ return true if !AlertGroup::LEVELS.include?(level) or AlertGroup::LEVELS.index(level) == 0
+
+ #
+ # Suppress this notification if all the last N of the preceeding
+ # notifications were of a equal or higher level.
+ #
+ return previous_notifications.first(number).alerts.to_a.all? do |a|
+ AlertGroup::LEVELS.index(a.level) >= AlertGroup::LEVELS.index(level)
+ end
+
end
end
- # The notification thresholds for this user
#
- # @return [Hash]
- def notification_thresholds
- @notification_thresholds ||= { }
+ #
+ #
+ def suppress_notifications_after
+ @suppress_notifications_after ||= { }
end
-
+
# This class implements an instance_eval context to execute the blocks
# for running a notification block for each person.
#
@@ -203,10 +253,8 @@ module Mauve
#
# Log the result
- note = "#{@alert.update_type.capitalize} #{name} notification to #{@person.username} (#{destination}) " + (res ? "succeeded" : "failed" )
- logger.info note+" about #{@alert}."
- h = History.new(:alerts => [@alert], :type => "notification", :event => note, :user => @person.username)
- h.save
+ #
+ logger.info "#{@alert.update_type.capitalize} #{name} notification to #{@person.username} (#{destination}) " + (res ? "succeeded" : "failed" ) +" about #{@alert}."
return res
end
@@ -222,17 +270,17 @@ module Mauve
def send_alert(level, alert, now=Time.now)
was_suppressed = @suppressed
- @suppressed = self.should_suppress?
- will_suppress = self.should_suppress?(now)
+ @suppressed = self.should_suppress?(level)
+ will_suppress = self.should_suppress?(level, now)
logger.info "Starting to send notifications again for #{username}." if was_suppressed and not @suppressed
-
+
#
# We only suppress notifications if we were suppressed before we started,
# and are still suppressed.
#
if @suppressed or self.is_on_holiday?(now) or self.is_off_sick?(now)
- note = "#{alert.update_type.capitalize} notification to #{self.username} suppressed"
+ note = "#{alert.update_type.capitalize} #{level} notification to #{self.username} suppressed"
logger.info note + " about #{alert}."
History.create(:alerts => [alert], :type => "notification", :event => note, :user => self.username)
return true
@@ -253,24 +301,13 @@ module Mauve
:was_suppressed => was_suppressed, }
).instance_eval(&__send__(level))
end
+
+ res = [result].flatten.any?
+
+ note = "#{alert.update_type.capitalize} #{level} notification to #{self.username} " + (res ? "succeeded" : "failed" )
+ History.create(:alerts => [alert], :type => "notification", :event => note, :user => self.username)
- if [result].flatten.any?
- #
- # Remember that we've sent an alert
- #
- self.notification_thresholds.each do |period, previous_alert_times|
- #
- # Hmm.. not sure how to make this thread-safe.
- #
- self.notification_thresholds[period].push now
- self.notification_thresholds[period].shift
- end
-
-
- return true
- end
-
- return false
+ return res
end
#
diff --git a/lib/mauve/quick_update.rb b/lib/mauve/quick_update.rb
new file mode 100644
index 0000000..d5ecc8a
--- /dev/null
+++ b/lib/mauve/quick_update.rb
@@ -0,0 +1,166 @@
+# encoding: UTF-8
+require 'mauve/proto'
+require 'mauve/sender'
+
+module Mauve
+ #
+ # This class can be used in simple cases where all the program needs to do is
+ # send an update about a single alert.
+ #
+ # In its simplest form, this could be something like
+ #
+ # Mauve::QuickUpdate.new("foo").raise!
+ #
+ # sends a "raise" to the default mauve destination about alert ID "foo".
+ #
+ # It can be used to do set more details about the alert.
+ #
+ # update = Mauve::QuickUpdate.new("foo")
+ # update.summary = "Foo backups failed"
+ # update.detail = cmd_output
+ # update.raise!
+ #
+ # Another example might be a heartbeat.
+ #
+ # update = Mauve::QuickUpdate.new("heartbeat")
+ # update.summary = "Heartbeat for this.host.name not received"
+ # update.detail = "Maybe this host is down, or if not, cron has stopped running."
+ # update.raise_at = Time.now + 600
+ # update.clear_at = now
+ # update.suppress_until = Time.now + 900
+ # update.send
+ #
+ class QuickUpdate
+
+ def initialize(alert_id)
+ raise ArgumentError, "alert_id must be a String, or respond to to_s" unless alert_id.is_a?(String) or alert_id.respond_to?("to_s")
+
+ @verbose = false
+
+ @update = Mauve::Proto::AlertUpdate.new
+ @update.replace = false
+ @update.alert = []
+
+ @alert = Mauve::Proto::Alert.new
+ @alert.id = alert_id.to_s
+
+ @update << @alert
+ end
+
+ #
+ # Sets the replace flag for the whole update. Defaults to false.
+ #
+ def replace=(bool)
+ raise ArgumentError, "replace must either be true or false" unless bool.is_a?(TrueClass) or bool.is_a?(FalseClass)
+
+ @update.replace = bool
+ end
+
+ #
+ # Sets the verbose flag for the update process. Defaults to false.
+ #
+ def verbose=(bool)
+ raise ArgumentError, "verbose must either be true or false" unless bool.is_a?(TrueClass) or bool.is_a?(FalseClass)
+
+ @verbose = bool
+ end
+
+ #
+ # Sets the source of the alert. Defaults to the machine's hostname.
+ #
+ def source=(s)
+ raise ArgumentError, "source must be a String, or respond to to_s" unless s.is_a?(String) or s.respond_to?("to_s")
+
+ @update.source = s.to_s
+ end
+
+ #
+ # Sets the alert summary. Must be a string or something that can convert to a string.
+ #
+ def summary=(s)
+ raise ArgumentError, "summary must be a String, or respond to to_s" unless s.is_a?(String) or s.respond_to?("to_s")
+
+ @alert.summary = s.to_s
+ end
+
+ #
+ # Sets the alert detail. Must be a string or something that can convert to a string.
+ #
+ def detail=(s)
+ raise ArgumentError, "detail must be a String, or respond to to_s" unless s.is_a?(String) or s.respond_to?("to_s")
+
+ @alert.detail = s
+ end
+
+ #
+ # Sets the alert summary. Must be a string or something that can convert to a string.
+ #
+ def subject=(s)
+ raise ArgumentError, "subject must be a String, or respond to to_s" unless s.is_a?(String) or s.respond_to?("to_s")
+
+ @alert.subject = s
+ end
+
+ #
+ # Sets the raise time. Must be an Integer (epoch time) or a Time.
+ #
+ def raise_time=(t)
+ raise ArgumentError, "raise_time must be a Time or an Integer" unless t.is_a?(Time) or t.is_a?(Integer)
+ t = t.to_i if t.is_a?(Time)
+
+ @alert.raise_time = t
+ end
+
+ alias raise_at= raise_time=
+
+ #
+ # Sets the clear time. Must be an Integer (epoch time) or a Time.
+ #
+ def clear_time=(t)
+ clear ArgumentError, "clear_time must be a Time or an Integer" unless t.is_a?(Time) or t.is_a?(Integer)
+ t = t.to_i if t.is_a?(Time)
+
+ @alert.clear_time = t
+ end
+
+ alias clear_at= clear_time=
+
+ #
+ # Sets the time after which alerts will get sent. Must be an Integer (epoch time) or a Time.
+ #
+ def suppress_until=(t)
+ clear ArgumentError, "suppress_until must be a Time or an Integer" unless t.is_a?(Time) or t.is_a?(Integer)
+ t = t.to_i if t.is_a?(Time)
+
+ @alert.suppress_until = t
+ end
+
+ #
+ # Immediately send a raise message. The raise_time defaults to Time#now.
+ #
+ def raise!(t = Time.now)
+ self.raise_time = t
+ self.send
+ end
+
+ #
+ # Immediately send a clear message. The clear_time defaults to Time#now.
+ #
+ def clear!(t = Time.now)
+ self.clear_time = t
+ self.send
+ end
+
+ #
+ # This sends the alert. If destinations are left as nil, then the default
+ # as per Mauve::Sender are used.
+ #
+ def send(destinations = nil)
+ Mauve::Sender.new(destinations).send(@update, @verbose)
+ end
+
+ end
+
+end
+
+
diff --git a/lib/mauve/server.rb b/lib/mauve/server.rb
index bb514ce..8f8cec4 100644
--- a/lib/mauve/server.rb
+++ b/lib/mauve/server.rb
@@ -56,6 +56,11 @@ module Mauve
@bank_holidays = nil
#
+ # Turn off unwanted reverse DNS lookups across the board.
+ #
+ BasicSocket.do_not_reverse_lookup = true
+
+ #
# Set up a blank config.
#
Configuration.current = Configuration.new if Mauve::Configuration.current.nil?
diff --git a/lib/mauve/version.rb b/lib/mauve/version.rb
index 0014105..fa2d75a 100644
--- a/lib/mauve/version.rb
+++ b/lib/mauve/version.rb
@@ -5,6 +5,6 @@ module Mauve
#
# Current version
- VERSION="3.15.6"
+ VERSION="3.15.14"
end