aboutsummaryrefslogtreecommitdiff
path: root/lib/mauve/alert_group.rb
blob: adb990968d8da33701d45abc63c7a8021e2edb62 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# encoding: UTF-8
require 'mauve/alert'
require 'log4r'

module Mauve
  class AlertGroup < Struct.new(:name, :includes, :acknowledgement_time, :level, :notifications)
    def to_s
      "#<AlertGroup:#{name} (level #{level})>"
    end
    
    class << self
      def matches(alert)
        all.select { |alert_group| alert_group.matches_alert?(alert) }
      end

      # If there is any significant change to a set of alerts, the Alert
      # class sends the list here so that appropriate action can be taken
      # for each one.  We scan the list of alert groups to find out which
      # alerts match which groups, then send a notification to each group
      # object in turn.
      #
      def notify(alerts)
        alerts.each do |alert|
          groups = matches(alert)
          
          # 
          # Make sure we've got a matching group
          #
          logger.warn "no groups found for #{alert.id}" if groups.empty?

          #
          # Notify just the group that thinks this alert is the most urgent.
          #
          %w(urgent normal low).each do |lvl|
            this_group = groups.find{|grp| grp.level.to_s == lvl}
            next if this_group.nil?
            logger.info("notifying group #{this_group} of AlertID.#{alert.id} (matching #{lvl})")
            this_group.notify(alert)
            break
          end
        end
      end
 
      def logger
        Log4r::Logger.new self.to_s
      end

      def all
        Configuration.current.alert_groups
      end
      
      # Find all alerts that match 
      #
      # @deprecated Buggy method, use Alert.get_all().
      #
      # This method returns all the alerts in all the alert_groups.  Only
      # the first one should be returned thus making this useless. If you want
      # a list of all the alerts matching a level, use Alert.get_all().
      # 
      def all_alerts_by_level(level)
        Configuration.current.alert_groups.map do |alert_group|
          alert_group.level == level ? alert_group.current_alerts : []
        end.flatten.uniq
      end

    end
    
    def initialize(name)
      self.name = name
      self.level = :normal
      self.includes = Proc.new { true }
    end
  
    # The list of current raised alerts in this group.
    #
    def current_alerts
      Alert.all(:cleared_at => nil, :raised_at.not => nil).select { |a| matches_alert?(a) }
    end
    
    # Decides whether a given alert belongs in this group according to its
    # includes { } clause
    #
    # @param [Alert] alert An alert to test for belongness to group.
    # @return [Boolean] Success or failure.
    def matches_alert?(alert)
      result = alert.instance_eval(&self.includes)
      if true == result or
         true == result.instance_of?(MatchData)
        return true
      end
      return false
    end

    def logger ; self.class.logger ; end

    # Signals that a given alert (which is assumed to belong in this group)
    # has undergone a significant change.  We resend this to every notify list.
    #    
    def notify(alert)
      #
      # The notifications are specified in the config file.
      #
      notifications.each do |notification|
        notification.alert_changed(alert)
      end
    end

  end

end