flapjack 0.7.20 → 0.7.21

Sign up to get free protection for your applications and to get access to all the features.
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?