flapjack 0.7.20 → 0.7.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +3 -1
  3. data/CHANGELOG.md +10 -0
  4. data/Gemfile +1 -0
  5. data/bin/flapjack +11 -0
  6. data/bin/simulate-failed-check +5 -5
  7. data/features/notification_rules.feature +77 -19
  8. data/features/steps/events_steps.rb +15 -3
  9. data/lib/flapjack/coordinator.rb +3 -3
  10. data/lib/flapjack/data/contact.rb +1 -1
  11. data/lib/flapjack/data/entity.rb +12 -1
  12. data/lib/flapjack/data/entity_check.rb +9 -2
  13. data/lib/flapjack/data/event.rb +4 -4
  14. data/lib/flapjack/data/notification.rb +27 -20
  15. data/lib/flapjack/data/notification_rule.rb +26 -24
  16. data/lib/flapjack/data/tag.rb +5 -0
  17. data/lib/flapjack/gateways/api.rb +1 -1
  18. data/lib/flapjack/gateways/api/contact_methods.rb +3 -3
  19. data/lib/flapjack/gateways/email.rb +73 -46
  20. data/lib/flapjack/gateways/email/alert.html.erb +13 -4
  21. data/lib/flapjack/gateways/email/alert.text.erb +2 -2
  22. data/lib/flapjack/gateways/jabber.rb +22 -16
  23. data/lib/flapjack/gateways/pagerduty.rb +7 -3
  24. data/lib/flapjack/gateways/web.rb +1 -1
  25. data/lib/flapjack/gateways/web/views/check.html.erb +2 -2
  26. data/lib/flapjack/gateways/web/views/contact.html.erb +3 -3
  27. data/lib/flapjack/logger.rb +67 -35
  28. data/lib/flapjack/notifier.rb +9 -3
  29. data/lib/flapjack/pikelet.rb +3 -1
  30. data/lib/flapjack/processor.rb +34 -10
  31. data/lib/flapjack/version.rb +1 -1
  32. data/spec/lib/flapjack/coordinator_spec.rb +17 -13
  33. data/spec/lib/flapjack/data/contact_spec.rb +4 -3
  34. data/spec/lib/flapjack/data/entity_check_spec.rb +10 -0
  35. data/spec/lib/flapjack/data/entity_spec.rb +60 -5
  36. data/spec/lib/flapjack/data/event_spec.rb +4 -4
  37. data/spec/lib/flapjack/data/notification_rule_spec.rb +9 -2
  38. data/spec/lib/flapjack/data/tag_spec.rb +0 -1
  39. data/spec/lib/flapjack/gateways/api/contact_methods_spec.rb +1 -1
  40. data/spec/lib/flapjack/gateways/email_spec.rb +2 -1
  41. data/spec/lib/flapjack/gateways/jabber_spec.rb +5 -3
  42. data/spec/lib/flapjack/gateways/pagerduty_spec.rb +3 -1
  43. data/spec/lib/flapjack/logger_spec.rb +5 -5
  44. data/spec/lib/flapjack/pikelet_spec.rb +4 -2
  45. data/spec/lib/flapjack/processor_spec.rb +16 -7
  46. data/tasks/benchmarks.rake +228 -0
  47. data/tasks/events.rake +11 -10
  48. data/tasks/support/flapjack_config_benchmark.yaml +58 -0
  49. metadata +6 -4
data/.gitignore CHANGED
@@ -26,4 +26,5 @@ flapjack-*.gem
26
26
  .rbenv-version
27
27
  .ruby-version
28
28
  .rvmrc
29
+ artifacts/*
29
30
 
data/.travis.yml CHANGED
@@ -2,6 +2,8 @@ language: ruby
2
2
  rvm:
3
3
  - "1.9.3"
4
4
  - "2.0.0"
5
+ env:
6
+ - ENTITIES=10 INTERVAL=120
5
7
  gemfile:
6
8
  - Gemfile
7
9
  services:
@@ -11,4 +13,4 @@ before_script:
11
13
  before_install:
12
14
  - git submodule update --init --recursive
13
15
  - gem install bundler
14
- script: bundle exec rspec spec && bundle exec cucumber features
16
+ script: bundle exec rspec spec && bundle exec cucumber features && bundle exec rake benchmarks:run
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  ## Flapjack Changelog
2
2
 
3
+ # 0.7.21 - 2013-08-08
4
+ - Feature: make eneity search scopable by tags gh-89 (@jessereynolds)
5
+ - Feature: add benchmark rake task gh-259 (@jessereynolds)
6
+ - Feature: make tags more general in notification rules gh-269 (@jessereynolds)
7
+ - Feature: ephemeral tag generation on events gh-268 (@jessereynolds)
8
+ - Bug: fix syslog output levels gh-260 (@ali-graham)
9
+ - Bug: Ruby 2 shutdown error gh-261 (@ali-graham)
10
+ - Bug: Email and SMS problem and recovery notifications failing (@jessereynolds)
11
+ - Bug: Links to contacts from the check detail page are broken (@jessereynolds)
12
+
3
13
  # 0.7.20 - 2013-07-17
4
14
  - Bug: flapjack-nagios-receiver failing after json library change gh-257 (@jessereynolds)
5
15
  - Bug: email gateway partial conversion to erb sending haml source code gh-256 (@ali-graham)
data/Gemfile CHANGED
@@ -21,4 +21,5 @@ group :test do
21
21
  gem 'fuubar-cucumber'
22
22
  gem 'simplecov', :require => false
23
23
  gem 'json_spec'
24
+ gem 'perftools.rb'
24
25
  end
data/bin/flapjack CHANGED
@@ -6,6 +6,17 @@ unless $:.include?(File.dirname(__FILE__) + '/../lib/')
6
6
  end
7
7
 
8
8
  require 'dante'
9
+
10
+ module Dante
11
+ class Runner
12
+
13
+ def start
14
+ # skip signal traps
15
+ @startup_command.call(self.options) if @startup_command
16
+ end
17
+ end
18
+ end
19
+
9
20
  require 'optparse'
10
21
  require 'ostruct'
11
22
 
@@ -12,6 +12,7 @@ require 'eventmachine'
12
12
  require 'json'
13
13
 
14
14
  require 'flapjack/configuration'
15
+ require 'flapjack/data/event'
15
16
 
16
17
  def pike(message)
17
18
  puts "piking out: #{message}"
@@ -20,7 +21,7 @@ end
20
21
 
21
22
  def send_event(event, opts)
22
23
  redis = opts[:redis]
23
- redis.lpush 'events', event.to_json
24
+ Flapjack::Data::Event.add(event, :redis => redis)
24
25
  end
25
26
 
26
27
  def fail(opts)
@@ -31,8 +32,7 @@ def fail(opts)
31
32
  event = {
32
33
  'entity' => opts[:entity] || 'foo-app-01',
33
34
  'check' => opts[:check] || 'HTTP',
34
- 'type' => 'service',
35
- 'timestamp' => Time.now.to_i
35
+ 'type' => 'service'
36
36
  }
37
37
  failure = event.merge('state' => state, 'summary' => 'Simulated check output (test by operator)')
38
38
  recovery = event.merge('state' => 'ok', 'summary' => 'Simulated check output (test by operator)')
@@ -47,14 +47,14 @@ def fail(opts)
47
47
  puts "#{Time.now}: stopping"
48
48
  if recover
49
49
  puts "#{Time.now}: sending recovery event for #{key}"
50
- send_event(recovery, :redis => redis)
50
+ send_event(recovery.merge('time' => Time.now.to_i), :redis => redis)
51
51
  end
52
52
  EM.stop
53
53
  end
54
54
 
55
55
  EM.add_periodic_timer(10) do
56
56
  puts "#{Time.now}: sending failure event (#{state}) for #{key}"
57
- send_event(failure, :redis => redis)
57
+ send_event(failure.merge('time' => Time.now.to_i), :redis => redis)
58
58
  end
59
59
 
60
60
  }
@@ -7,13 +7,15 @@ Feature: Notification rules on a per contact basis
7
7
  | 1 | Malak | Al-Musawi | malak@example.com | +61400000001 | Asia/Baghdad |
8
8
  | 2 | Imani | Farooq | imani@example.com | +61400000002 | Europe/Moscow |
9
9
  | 3 | Vera | Дурейко | vera@example.com | +61400000003 | Europe/Paris |
10
+ | 4 | Lucia | Moretti | lucia@example.com | +61400000004 | Europe/Rome |
10
11
 
11
12
  And the following entities exist:
12
- | id | name | contacts |
13
- | 1 | foo | 1 |
14
- | 2 | bar | 1,2,3 |
15
- | 3 | baz | 1,3 |
16
- | 4 | buf | 1,2,3 |
13
+ | id | name | contacts |
14
+ | 1 | foo | 1 |
15
+ | 2 | bar | 1,2,3 |
16
+ | 3 | baz | 1,3 |
17
+ | 4 | buf | 1,2,3 |
18
+ | 5 | foo-app-01.xyz | 4 |
17
19
 
18
20
  And user 1 has the following notification intervals:
19
21
  | email | sms |
@@ -27,25 +29,35 @@ Feature: Notification rules on a per contact basis
27
29
  | email | sms |
28
30
  | 15 | 60 |
29
31
 
32
+ And user 4 has the following notification intervals:
33
+ | email | sms |
34
+ | 15 | 60 |
35
+
30
36
  And user 1 has the following notification rules:
31
- | entities | entity_tags | warning_media | critical_media | warning_blackhole | critical_blackhole | time_restrictions |
32
- | | | email | sms,email | true | true | |
33
- | foo | | email | sms,email | | | 8-18 weekdays |
34
- | bar | | | sms,email | true | | |
35
- | baz | | email | sms,email | | | |
37
+ | entities | tags | warning_media | critical_media | warning_blackhole | critical_blackhole | time_restrictions |
38
+ | | | email | sms,email | true | true | |
39
+ | foo | | email | sms,email | | | 8-18 weekdays |
40
+ | bar | | | sms,email | true | | |
41
+ | baz | | email | sms,email | | | |
36
42
 
37
43
  And user 2 has the following notification rules:
38
- | entities | entity_tags | warning_media | critical_media | warning_blackhole | critical_blackhole | time_restrictions |
39
- | | | email | email | | | |
40
- | | | sms | sms | | | |
41
- | bar | | email | email,sms | | | |
44
+ | entities | tags | warning_media | critical_media | warning_blackhole | critical_blackhole | time_restrictions |
45
+ | | | email | email | | | |
46
+ | | | sms | sms | | | |
47
+ | bar | | email | email,sms | | | |
42
48
 
43
49
  And user 3 has the following notification rules:
44
- | entities | entity_tags | warning_media | critical_media | warning_blackhole | critical_blackhole | time_restrictions |
45
- | | | email | email | | | |
46
- | baz | | sms | sms | | | |
47
- | buf | | email | email | | | |
48
- | buf | | sms | sms | | | |
50
+ | entities | tags | warning_media | critical_media | warning_blackhole | critical_blackhole | time_restrictions |
51
+ | | | email | email | | | |
52
+ | baz | | sms | sms | | | |
53
+ | buf | | email | email | | | |
54
+ | buf | | sms | sms | | | |
55
+
56
+ And user 4 has the following notification rules:
57
+ | entities | tags | warning_media | critical_media | warning_blackhole | critical_blackhole | time_restrictions |
58
+ | | | | | | | |
59
+ | | xyz, disk, util | sms | sms | | | |
60
+ | | xyz, ping | sms,email | sms,email | | | 8-18 weekdays |
49
61
 
50
62
  @time_restrictions @time
51
63
  Scenario: Alerts only during specified time restrictions
@@ -310,3 +322,49 @@ Feature: Notification rules on a per contact basis
310
322
  @time
311
323
  Scenario: A blackhole rule on an entity should override another matching general rule
312
324
 
325
+ @time
326
+ Scenario: Notify when tags in a rule match the event's tags
327
+ Given the check is check 'Disk / Util' on entity 'foo-app-01.xyz'
328
+ And the check is in an ok state
329
+ When a critical event is received
330
+ And 1 minute passes
331
+ And a critical event is received
332
+ Then 1 sms alert should be queued for +61400000004
333
+
334
+ @time
335
+ Scenario: Don't notify when tags in a rule don't match the event's tags
336
+ Given the check is check 'Memory Util' on entity 'foo-app-01.xyz'
337
+ And the check is in an ok state
338
+ When a critical event is received
339
+ And 1 minute passes
340
+ And a critical event is received
341
+ Then no sms alerts should be queued for +61400000004
342
+
343
+ @time
344
+ Scenario: Only notify during specified time periods in tag matched rules
345
+ Given the timezone is Europe/Rome
346
+ And the time is February 1 2013 6:59
347
+ And the check is check 'ping' on entity 'foo-app-01.xyz'
348
+ And the check is in an ok state
349
+ And a critical event is received
350
+ Then no sms alerts should be queued for +61400000004
351
+ And the time is February 1 2013 7:01
352
+ And a critical event is received
353
+ Then no sms alerts should be queued for +61400000004
354
+ And the time is February 1 2013 8:01
355
+ And a critical event is received
356
+ Then 1 sms alert should be queued for +61400000004
357
+ When the time is February 1 2013 12:00
358
+ Then all alert dropping keys for user 1 should have expired
359
+ When a critical event is received
360
+ Then 2 sms alerts should be queued for +61400000004
361
+ When the time is February 1 2013 17:59
362
+ Then all alert dropping keys for user 1 should have expired
363
+ When a critical event is received
364
+ Then 3 sms alerts should be queued for +61400000004
365
+ When the time is February 1 2013 18:01
366
+ Then all alert dropping keys for user 1 should have expired
367
+ When a critical event is received
368
+ Then 3 sms alerts should be queued for +61400000004
369
+
370
+
@@ -289,6 +289,15 @@ Then /^show me the (\w+ )*log$/ do |adjective|
289
289
  puts @logger.messages.join("\n")
290
290
  end
291
291
 
292
+ Then /^dump notification rules for user (\d+)$/ do |contact|
293
+ rule_ids = @redis.smembers("contact_notification_rules:#{contact}")
294
+ puts "There #{(rule_ids.length == 1) ? 'is' : 'are'} #{rule_ids.length} notification rule#{(rule_ids.length == 1) ? '' : 's'} for user #{contact}:"
295
+ rule_ids.each {|rule_id|
296
+ rule = Flapjack::Data::NotificationRule.find_by_id(rule_id, :redis => @redis)
297
+ puts rule.to_json
298
+ }
299
+ end
300
+
292
301
  # added for notification rules:
293
302
  Given /^the following entities exist:$/ do |entities|
294
303
  entities.hashes.each do |entity|
@@ -335,7 +344,7 @@ Given /^user (\d+) has the following notification rules:$/ do |contact_id, rules
335
344
  end
336
345
  rules.hashes.each do |rule|
337
346
  entities = rule['entities'].split(',').map { |x| x.strip }
338
- entity_tags = rule['entity_tags'].split(',').map { |x| x.strip }
347
+ tags = rule['tags'].split(',').map { |x| x.strip }
339
348
  warning_media = rule['warning_media'].split(',').map { |x| x.strip }
340
349
  critical_media = rule['critical_media'].split(',').map { |x| x.strip }
341
350
  warning_blackhole = (rule['warning_blackhole'].downcase == 'true')
@@ -352,13 +361,16 @@ Given /^user (\d+) has the following notification rules:$/ do |contact_id, rules
352
361
  end
353
362
  rule_data = {:contact_id => contact_id,
354
363
  :entities => entities,
355
- :entity_tags => entity_tags,
364
+ :tags => tags,
356
365
  :warning_media => warning_media,
357
366
  :critical_media => critical_media,
358
367
  :warning_blackhole => warning_blackhole,
359
368
  :critical_blackhole => critical_blackhole,
360
369
  :time_restrictions => time_restrictions}
361
- Flapjack::Data::NotificationRule.add(rule_data, :redis => @redis)
370
+ created_rule = Flapjack::Data::NotificationRule.add(rule_data, :redis => @redis)
371
+ unless created_rule.is_a?(Flapjack::Data::NotificationRule)
372
+ raise "Error creating notification rule with data: #{rule_data}, errors: #{created_rule.join(', ')}"
373
+ end
362
374
  end
363
375
  end
364
376
 
@@ -28,8 +28,8 @@ module Flapjack
28
28
  @boot_time = Time.now
29
29
 
30
30
  EM.synchrony do
31
- add_pikelets(pikelets(@config.all))
32
31
  setup_signals if options[:signals]
32
+ add_pikelets(pikelets(@config.all))
33
33
  end
34
34
  end
35
35
 
@@ -124,7 +124,7 @@ module Flapjack
124
124
  start_piks = []
125
125
  pikelets_data.each_pair do |type, cfg|
126
126
  next unless pikelet = Flapjack::Pikelet.create(type,
127
- :config => cfg, :redis_config => @redis_options, :boot_time => @boot_time)
127
+ :config => cfg, :redis_config => @redis_options, :boot_time => @boot_time, :coordinator => self)
128
128
  start_piks << pikelet
129
129
  @pikelets << pikelet
130
130
  end
@@ -132,7 +132,7 @@ module Flapjack
132
132
  start_piks.each {|pik| pik.start }
133
133
  rescue Exception => e
134
134
  trace = e.backtrace.join("\n")
135
- @logger.fatal "#{e.message}\n#{trace}"
135
+ @logger.fatal "#{e.class.name}\n#{e.message}\n#{trace}"
136
136
  stop
137
137
  end
138
138
  end
@@ -175,7 +175,7 @@ module Flapjack
175
175
  if rules.all? {|r| r.is_specific? } # also true if empty
176
176
  rule = self.add_notification_rule({
177
177
  :entities => [],
178
- :entity_tags => [],
178
+ :tags => Flapjack::Data::TagSet.new([]),
179
179
  :time_restrictions => [],
180
180
  :warning_media => ['email', 'sms', 'jabber', 'pagerduty'],
181
181
  :critical_media => ['email', 'sms', 'jabber', 'pagerduty'],
@@ -95,6 +95,17 @@ module Flapjack
95
95
  }.sort
96
96
  end
97
97
 
98
+ def self.find_all_with_tags(tags, options = {})
99
+ raise "Redis connection not set" unless redis = options[:redis]
100
+ tags_prefixed = tags.collect {|tag|
101
+ "#{TAG_PREFIX}:#{tag}"
102
+ }
103
+ logger.debug "tags_prefixed: #{tags_prefixed.inspect}" if logger = options[:logger]
104
+ Flapjack::Data::Tag.find_intersection(tags_prefixed, :redis => redis).collect {|entity_id|
105
+ Flapjack::Data::Entity.find_by_id(entity_id, :redis => redis).name
106
+ }.compact
107
+ end
108
+
98
109
  def self.find_all_with_checks(options)
99
110
  raise "Redis connection not set" unless redis = options[:redis]
100
111
  redis.zrange("current_entities", 0, -1)
@@ -119,7 +130,7 @@ module Flapjack
119
130
  end
120
131
 
121
132
  def check_list
122
- @redis.zrange("current_checks:#{@name}", 0, -1)
133
+ @redis.zrange("current_checks:#{@name}", 0, -1)
123
134
  end
124
135
 
125
136
  def check_count
@@ -92,14 +92,14 @@ module Flapjack
92
92
  memo[entity] ||= []
93
93
  memo[entity] << check
94
94
  end
95
- memo
95
+ memo
96
96
  end
97
97
  end
98
98
 
99
99
  def self.count_all_failing(options = {})
100
100
  raise "Redis connection not set" unless redis = options[:redis]
101
101
  redis.zrange("failed_checks", 0, -1).count do |key|
102
- entity, check = key.split(':', 2)
102
+ entity, check = key.split(':', 2)
103
103
  !!redis.zscore("current_checks:#{entity}", check)
104
104
  end
105
105
  end
@@ -515,6 +515,13 @@ module Flapjack
515
515
  }.compact
516
516
  end
517
517
 
518
+ def tags
519
+ entity, check = @key.split(":", 2)
520
+ ta = Flapjack::Data::TagSet.new([])
521
+ ta += entity.split('.', 2).map {|x| x.downcase}
522
+ ta += check.split(' ').map {|x| x.downcase}
523
+ end
524
+
518
525
  private
519
526
 
520
527
  def initialize(entity, check, options = {})
@@ -6,7 +6,7 @@ module Flapjack
6
6
  module Data
7
7
  class Event
8
8
 
9
- attr_accessor :counter, :previous_state, :previous_state_duration
9
+ attr_accessor :counter, :previous_state, :previous_state_duration, :tags
10
10
 
11
11
  attr_reader :check, :summary, :details, :acknowledgement_id
12
12
 
@@ -65,14 +65,14 @@ module Flapjack
65
65
  raise "Redis connection not set" unless redis = opts[:redis]
66
66
 
67
67
  evt['time'] = Time.now.to_i if evt['time'].nil?
68
- redis.rpush('events', ::Oj.dump(evt))
68
+ redis.lpush('events', ::Oj.dump(evt))
69
69
  end
70
70
 
71
71
  # Provide a count of the number of events on the queue to be processed.
72
- def self.pending_count(opts = {})
72
+ def self.pending_count(queue, opts = {})
73
73
  raise "Redis connection not set" unless redis = opts[:redis]
74
74
 
75
- redis.llen('events')
75
+ redis.llen(queue)
76
76
  end
77
77
 
78
78
  def self.create_acknowledgement(entity_name, check, opts = {})
@@ -48,6 +48,7 @@ module Flapjack
48
48
 
49
49
  last_state = opts[:last_state] || {}
50
50
 
51
+ tag_data = event.tags.is_a?(Set) ? event.tags.to_a : nil
51
52
  notif = {'event_id' => event.id,
52
53
  'state' => event.state,
53
54
  'summary' => event.summary,
@@ -58,7 +59,8 @@ module Flapjack
58
59
  'duration' => event.duration || nil,
59
60
  'type' => opts[:type] || type_for_event(event),
60
61
  'severity' => opts[:severity],
61
- 'count' => event.counter }
62
+ 'count' => event.counter,
63
+ 'tags' => tag_data }
62
64
 
63
65
  redis.rpush(queue, Oj.dump(notif))
64
66
  end
@@ -96,7 +98,8 @@ module Flapjack
96
98
  'time' => @event_time,
97
99
  'duration' => @event_duration,
98
100
  'notification_type' => @type,
99
- 'event_count' => @event_count
101
+ 'event_count' => @event_count,
102
+ 'tags' => @tags
100
103
  }
101
104
  end
102
105
 
@@ -111,35 +114,39 @@ module Flapjack
111
114
  rules = contact.notification_rules
112
115
  media = contact.media
113
116
 
114
- logger.debug "considering messages for contact id #{contact_id} #{@event_id} #{@event_state} (media) #{media.inspect}"
117
+ logger.debug "Notification#messages: creating messages for contact: #{contact_id} " +
118
+ "event_id: \"#{@event_id}\" state: #{@event_state} event_tags: #{@tags.to_json} media: #{media.inspect}"
115
119
  rlen = rules.length
116
- logger.debug "found #{rlen} rule#{(rlen == 1) ? '' : 's'} for contact"
120
+ logger.debug "found #{rlen} rule#{(rlen == 1) ? '' : 's'} for contact #{contact_id}"
117
121
 
118
122
  media_to_use = if rules.empty?
119
123
  media
120
124
  else
121
125
  # matchers are rules of the contact that have matched the current event
122
- # for time and entity
126
+ # for time, entity and tags
123
127
  matchers = rules.select do |rule|
124
- rule.match_entity?(@event_id) &&
128
+ logger.debug("considering rule with entities: #{rule.entities} and tags: #{rule.tags.to_json}")
129
+ (rule.match_entity?(@event_id) || rule.match_tags?(@tags) || ! rule.is_specific?) &&
125
130
  rule_occurring_now?(rule, :contact => contact, :default_timezone => default_timezone)
126
131
  end
127
132
 
128
- logger.debug "#{matchers.length} matchers remain for this contact:"
133
+ logger.debug "#{matchers.length} matchers remain for this contact after time, entity and tags are matched:"
129
134
  matchers.each do |matcher|
130
135
  logger.debug "matcher: #{matcher.to_json}"
131
136
  end
132
137
 
133
- # delete any matchers for all entities if there are more specific matchers
138
+ # delete any general matchers if there are more specific matchers left
134
139
  if matchers.any? {|matcher| matcher.is_specific? }
135
140
 
136
- logger.debug("general removal: found #{matchers.length} entity specific matchers")
137
141
  num_matchers = matchers.length
138
142
 
139
143
  matchers.reject! {|matcher| !matcher.is_specific? }
140
144
 
141
145
  if num_matchers != matchers.length
142
146
  logger.debug("notification: removal of general matchers when entity specific matchers are present: number of matchers changed from #{num_matchers} to #{matchers.length} for contact id: #{contact_id}")
147
+ matchers.each do |matcher|
148
+ logger.debug "matcher: #{matcher.to_json}"
149
+ end
143
150
  end
144
151
  end
145
152
 
@@ -179,19 +186,19 @@ module Flapjack
179
186
 
180
187
  # created from parsed JSON, so opts keys are in strings
181
188
  def initialize(opts = {})
182
- @event_id = opts['event_id']
183
- @event_state = opts['state']
184
- @event_summary = opts['summary']
185
- @event_details = opts['details']
186
- @event_time = opts['time']
187
- @event_duration = opts['duration']
188
- @event_count = opts['count']
189
-
189
+ @event_id = opts['event_id']
190
+ @event_state = opts['state']
191
+ @event_summary = opts['summary']
192
+ @event_details = opts['details']
193
+ @event_time = opts['time']
194
+ @event_duration = opts['duration']
195
+ @event_count = opts['count']
190
196
  @last_event_state = opts['last_state']
191
197
  @last_event_summary = opts['last_summary']
192
-
193
- @type = opts['type']
194
- @severity = opts['severity']
198
+ @type = opts['type']
199
+ @severity = opts['severity']
200
+ tags = opts['tags']
201
+ @tags = tags.is_a?(Array) ? Flapjack::Data::TagSet.new(tags) : nil
195
202
  end
196
203
 
197
204
  # # time restrictions match?