flapjack 0.7.29 → 0.7.30

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/CHANGELOG.md +8 -0
  2. data/bin/flapjack-nagios-receiver +20 -15
  3. data/bin/flapjack-populator +30 -13
  4. data/bin/flapper +1 -1
  5. data/bin/receive-events +13 -10
  6. data/bin/simulate-failed-check +13 -3
  7. data/dist/etc/init.d/flapjack +5 -42
  8. data/dist/etc/init.d/flapjack-nagios-receiver +3 -17
  9. data/dist/etc/init.d/flapper +3 -12
  10. data/etc/flapjack_config.yaml.example +81 -52
  11. data/features/cli.feature +30 -13
  12. data/features/cli_flapjack-nagios-receiver.feature +66 -0
  13. data/features/cli_flapjack-populator.feature +80 -0
  14. data/features/cli_flapper.feature +45 -0
  15. data/features/cli_receive-events.feature +27 -0
  16. data/features/cli_simulate-failed-check.feature +31 -0
  17. data/features/events.feature +3 -6
  18. data/features/packaging-lintian.feature +2 -2
  19. data/features/rollup.feature +2 -4
  20. data/features/steps/cli_steps.rb +25 -7
  21. data/features/steps/packaging-lintian_steps.rb +12 -6
  22. data/features/support/daemons.rb +11 -1
  23. data/features/support/env.rb +16 -4
  24. data/lib/flapjack/coordinator.rb +1 -1
  25. data/lib/flapjack/filters/delays.rb +1 -1
  26. data/lib/flapjack/gateways/email/alert.html.erb +1 -1
  27. data/lib/flapjack/gateways/email/alert.text.erb +1 -1
  28. data/lib/flapjack/gateways/email/rollup.html.erb +1 -1
  29. data/lib/flapjack/gateways/email/rollup.text.erb +1 -1
  30. data/lib/flapjack/gateways/web/views/check.html.erb +1 -1
  31. data/lib/flapjack/gateways/web/views/contact.html.erb +37 -32
  32. data/lib/flapjack/gateways/web.rb +7 -7
  33. data/lib/flapjack/logger.rb +25 -45
  34. data/lib/flapjack/version.rb +1 -1
  35. data/spec/lib/flapjack/coordinator_spec.rb +9 -7
  36. data/spec/lib/flapjack/logger_spec.rb +19 -13
  37. data/tasks/benchmarks.rake +1 -1
  38. data/tasks/support/flapjack_config_benchmark.yaml +1 -29
  39. metadata +97 -47
  40. checksums.yaml +0 -7
  41. data/bin/flapjack-netsaint-parser +0 -432
  42. data/dist/puppet/flapjack/files/.stub +0 -0
  43. data/dist/puppet/flapjack/manifests/common.pp +0 -61
  44. data/dist/puppet/flapjack/manifests/notifier.pp +0 -13
  45. data/dist/puppet/flapjack/manifests/worker.pp +0 -13
  46. data/dist/puppet/flapjack/templates/.stub +0 -0
  47. data/dist/puppet/ruby/manifests/dev.pp +0 -5
  48. data/dist/puppet/ruby/manifests/rubygems.pp +0 -14
  49. data/dist/puppet/sqlite3/manifests/dev.pp +0 -5
@@ -30,7 +30,8 @@
30
30
  <th>Summary Threshold</th>
31
31
  </tr>
32
32
  <% @contact.media.each_pair do |mk, mv| %>
33
- <% alerting[mk] = @contact.alerting_checks_for_media(mk) %>
33
+ <% alerting_checks = @contact.alerting_checks_for_media(mk) %>
34
+ <% alerting[mk] = alerting_checks unless (alerting_checks.nil? || alerting_checks.empty?) %>
34
35
  <tr>
35
36
  <% if 'pagerduty'.eql?(mk) %>
36
37
  <td>PagerDuty</td>
@@ -53,18 +54,20 @@
53
54
  <% end %>
54
55
  </td>
55
56
  <td>
56
- <% if alerting[mk].length >= @contact.media_rollup_thresholds[mk].to_i %>
57
- Yes -
58
- <% else %>
57
+ <% rollup_threshold = @contact.media_rollup_thresholds[mk] %>
58
+ <% num_alerting = alerting[mk].nil? ? 0 : alerting[mk].length %>
59
+ <% if rollup_threshold.nil? || (num_alerting < rollup_threshold.to_i) %>
59
60
  No -
61
+ <% else %>
62
+ Yes -
60
63
  <% end %>
61
- <%= alerting[mk].length %> alerting
64
+ <%= num_alerting %> alerting
62
65
  </td>
63
66
  <td>
64
- <% if @contact.media_rollup_thresholds[mk] %>
65
- <%= h @contact.media_rollup_thresholds[mk] %>
66
- <% else %>
67
+ <% if rollup_threshold.nil? %>
67
68
  -
69
+ <% else %>
70
+ <%= h rollup_threshold %>
68
71
  <% end %>
69
72
  </td>
70
73
  <% end %>
@@ -74,32 +77,34 @@
74
77
  <% end %>
75
78
 
76
79
  <h3>Alerting Checks</h3>
77
- <p>These failing checks are currently alerting because they are not acknowledged, not in scheduled maintenance, and currently allowed by this contact's notification rules.</p>
80
+ <p>Alerting checks are any that are failing, not acknowledged, not in scheduled maintenance, and currently allowed by this contact's notification rules.</p>
78
81
 
79
- <table class="table table-bordered table-hover table-condensed">
80
- <tr>
81
- <th>Media</th>
82
- <th>Alerting Checks</th>
83
- </tr>
84
- <% alerting.each_pair do |media, checks| %>
85
- <% if checks.length > 0 %>
86
- <tr>
87
- <td><%= h media.capitalize %></td>
88
- <td>
89
- <% checks.each do |entity_check| %>
90
- <% entity, check = entity_check.split(':', 2) %>
91
- <% check_link = "<a href=\"/check?entity=#{u(entity)}&amp;check=#{u(check)}\" title=\"check status\">" +
92
- h(check) + "</a>"%>
93
- <a href="/entity/<%= u(entity) %>" title="entity status"><%= h entity %></a> ::
94
- <%= check_link %> <br />
95
- <% end %>
96
- </td>
97
- </tr>
98
- <% else %>
99
- <tr><td colspan="2">No alerting checks, yay!</td></tr>
82
+ <% if alerting.empty? %>
83
+ <p><em>There are no currently alerting checks.</em></p>
84
+ <% else %>
85
+ <table class="table table-bordered table-hover table-condensed">
86
+ <tr>
87
+ <th>Media</th>
88
+ <th>Alerting Checks</th>
89
+ </tr>
90
+ <% alerting.each_pair do |media, checks| %>
91
+ <% if checks.length > 0 %>
92
+ <tr>
93
+ <td><%= h media.capitalize %></td>
94
+ <td>
95
+ <% checks.each do |entity_check| %>
96
+ <% entity, check = entity_check.split(':', 2) %>
97
+ <% check_link = "<a href=\"/check?entity=#{u(entity)}&amp;check=#{u(check)}\" title=\"check status\">" +
98
+ h(check) + "</a>"%>
99
+ <a href="/entity/<%= u(entity) %>" title="entity status"><%= h entity %></a> ::
100
+ <%= check_link %> <br />
101
+ <% end %>
102
+ </td>
103
+ </tr>
104
+ <% end %>
100
105
  <% end %>
101
- <% end %>
102
- </table>
106
+ </table>
107
+ <% end %>
103
108
 
104
109
  <h3>All Entities and Checks</h3>
105
110
  <% if !@entities_and_checks || @entities_and_checks.empty? %>
@@ -347,16 +347,16 @@ module Flapjack
347
347
  }.max_by {|n| n[1] || 0}
348
348
 
349
349
  lc = entity_check.last_change
350
- last_change = lc ? ChronicDuration.output(Time.now.to_i - lc.to_i,
351
- :format => :short, :keep_zero => true, :units => 2) : 'never'
350
+ last_change = lc ? (ChronicDuration.output(Time.now.to_i - lc.to_i,
351
+ :format => :short, :keep_zero => true, :units => 2) || '0s') : 'never'
352
352
 
353
353
  lu = entity_check.last_update
354
- last_update = lu ? ChronicDuration.output(Time.now.to_i - lu.to_i,
355
- :format => :short, :keep_zero => true, :units => 2) : 'never'
354
+ last_update = lu ? (ChronicDuration.output(Time.now.to_i - lu.to_i,
355
+ :format => :short, :keep_zero => true, :units => 2) || '0s') : 'never'
356
356
 
357
357
  ln = latest_notif[1]
358
- last_notified = ln ? ChronicDuration.output(Time.now.to_i - ln.to_i,
359
- :format => :short, :keep_zero => true, :units => 2) + ", #{latest_notif[0]}" : 'never'
358
+ last_notified = ln ? (ChronicDuration.output(Time.now.to_i - ln.to_i,
359
+ :format => :short, :keep_zero => true, :units => 2) || '0s') + ", #{latest_notif[0]}" : 'never'
360
360
 
361
361
  [(entity_check.state || '-'),
362
362
  (summary || '-'),
@@ -377,7 +377,7 @@ module Flapjack
377
377
  instance_id = i.match(/executive_instance:(.*)/)[1]
378
378
  boot_time = redis.hget(i, 'boot_time').to_i
379
379
  uptime = Time.now.to_i - boot_time
380
- uptime_string = ChronicDuration.output(uptime, :format => :short, :keep_zero => true, :units => 2)
380
+ uptime_string = (ChronicDuration.output(uptime, :format => :short, :keep_zero => true, :units => 2) || '0s')
381
381
  event_counters = redis.hgetall("event_counters:#{instance_id}")
382
382
  event_rates = event_counters.inject({}) do |er, ec|
383
383
  er[ec[0]] = uptime && uptime > 0 ? (ec[1].to_f / uptime).round : nil
@@ -2,12 +2,7 @@
2
2
 
3
3
  require 'logger'
4
4
  require 'syslog'
5
-
6
- begin
7
- # Ruby 2.0+
8
- require 'syslog/logger'
9
- rescue LoadError
10
- end
5
+ require 'monitor'
11
6
 
12
7
  module Flapjack
13
8
 
@@ -34,21 +29,9 @@ module Flapjack
34
29
  "#{t} [#{severity}] :: #{name} :: #{msg}\n"
35
30
  end
36
31
 
37
- @syslog_formatter = proc do |severity, datetime, progname, msg|
38
- t = datetime.iso8601
39
- l = SEVERITY_LABELS[severity]
40
- "#{t} [#{l}] :: #{name} :: #{msg}\n"
41
- end
42
-
43
32
  @logger = ::Logger.new(STDOUT)
44
33
  @logger.formatter = @formatter
45
34
 
46
- if Syslog.const_defined?('Logger', false)
47
- # Ruby 2.0+
48
- @sys_logger = Syslog.const_get('Logger', false).new('flapjack')
49
- @sys_logger.formatter = @syslog_formatter
50
- end
51
-
52
35
  configure(config)
53
36
  end
54
37
 
@@ -75,53 +58,50 @@ module Flapjack
75
58
  @logger.error(err) if err
76
59
 
77
60
  @logger.level = @level
78
- if @sys_logger
79
- @sys_logger.level = @level
80
- end
61
+ @use_syslog = config.has_key?('syslog_errors') && config['syslog_errors']
81
62
  end
82
63
 
83
64
  def close
84
65
  raise "Already closed" if @logger.nil?
85
66
  @logger.close
86
67
  @logger = nil
87
- if @sys_logger
88
- @sys_logger.close
89
- @sys_logger = nil
90
- end
91
68
  end
92
69
 
93
- def add(severity, message = nil, progname = nil, &block)
94
- raise "Cannot log with a closed logger" if @logger.nil?
95
- @logger.add(severity, message, progname, &block)
96
- return if severity < @level
97
-
98
- progname ||= 'flapjack'
99
- if message.nil?
100
- if block_given?
101
- message = yield
102
- else
103
- message = progname
104
- progname = 'flapjack'
105
- end
106
- end
107
-
108
- if @sys_logger
109
- @sys_logger.add(severity, message, progname, &block)
110
- else
70
+ def self.syslog_add(severity, message, name)
71
+ @lock ||= Monitor.new
72
+ @lock.synchronize do
111
73
  level = SYSLOG_LEVELS[severity]
112
74
  t = Time.now.iso8601
113
75
  l = SEVERITY_LABELS[severity]
114
76
  begin
115
77
  Syslog.open('flapjack', (Syslog::Constants::LOG_PID | Syslog::Constants::LOG_CONS),
116
78
  Syslog::Constants::LOG_USER)
117
- Syslog.mask = Syslog::LOG_UPTO(level)
118
- Syslog.log(level, "#{t} [#{l}] :: #{@name} :: %s", message)
79
+ Syslog.mask = Syslog::LOG_UPTO(::Syslog::Constants::LOG_ERR)
80
+ Syslog.log(level, "#{t} [#{l}] :: #{name} :: %s", message)
119
81
  ensure
120
82
  Syslog.close
121
83
  end
122
84
  end
123
85
  end
124
86
 
87
+ def add(severity, message = nil, progname = nil, &block)
88
+ raise "Cannot log with a closed logger" if @logger.nil?
89
+ @logger.add(severity, message, progname, &block)
90
+ if severity >= @level
91
+ progname ||= 'flapjack'
92
+ if message.nil?
93
+ if block_given?
94
+ message = yield
95
+ else
96
+ message = progname
97
+ progname = 'flapjack'
98
+ end
99
+ end
100
+ end
101
+
102
+ Flapjack::Logger.syslog_add(severity, message, @name) if @use_syslog
103
+ end
104
+
125
105
  LEVELS.each do |level|
126
106
  define_method(level) {|progname, &block|
127
107
  add(::Logger.const_get(level.upcase), nil, progname, &block)
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  module Flapjack
4
- VERSION = "0.7.29"
4
+ VERSION = "0.7.30"
5
5
  end
@@ -17,7 +17,7 @@ describe Flapjack::Coordinator do
17
17
  cfg = {'processor' => {'enabled' => true}}
18
18
  EM.should_receive(:synchrony).and_yield
19
19
  config.should_receive(:for_redis).and_return({})
20
- config.should_receive(:all).and_return(cfg)
20
+ config.should_receive(:all).twice.and_return(cfg)
21
21
 
22
22
  processor = double('processor')
23
23
  processor.should_receive(:start)
@@ -51,7 +51,7 @@ describe Flapjack::Coordinator do
51
51
  cfg = {'processor' => {'enabled' => true}}
52
52
  EM.should_receive(:synchrony).and_yield
53
53
  config.should_receive(:for_redis).and_return({})
54
- config.should_receive(:all).and_return(cfg)
54
+ config.should_receive(:all).twice.and_return(cfg)
55
55
 
56
56
  processor = double('processor')
57
57
  processor.should_receive(:start).and_raise(RuntimeError)
@@ -82,7 +82,7 @@ describe Flapjack::Coordinator do
82
82
  cfg = {'executive' => {'enabled' => true}}
83
83
  EM.should_receive(:synchrony).and_yield
84
84
  config.should_receive(:for_redis).and_return({})
85
- config.should_receive(:all).and_return(cfg)
85
+ config.should_receive(:all).twice.and_return(cfg)
86
86
 
87
87
  processor = double('processor')
88
88
  processor.should_receive(:start)
@@ -125,7 +125,7 @@ describe Flapjack::Coordinator do
125
125
  }
126
126
  EM.should_receive(:synchrony).and_yield
127
127
  config.should_receive(:for_redis).and_return({})
128
- config.should_receive(:all).and_return(cfg)
128
+ config.should_receive(:all).twice.and_return(cfg)
129
129
 
130
130
  processor = double('processor')
131
131
  processor.should_receive(:start)
@@ -163,6 +163,7 @@ describe Flapjack::Coordinator do
163
163
  Kernel.should_receive(:trap).with('QUIT').and_yield
164
164
  Kernel.should_receive(:trap).with('HUP').and_yield
165
165
 
166
+ config.should_receive(:all).and_return({})
166
167
  config.should_receive(:for_redis).and_return({})
167
168
  fc = Flapjack::Coordinator.new(config)
168
169
  fc.should_receive(:stop).exactly(3).times
@@ -181,6 +182,7 @@ describe Flapjack::Coordinator do
181
182
  Kernel.should_not_receive(:trap).with('QUIT')
182
183
  Kernel.should_not_receive(:trap).with('HUP')
183
184
 
185
+ config.should_receive(:all).and_return({})
184
186
  config.should_receive(:for_redis).and_return({})
185
187
  fc = Flapjack::Coordinator.new(config)
186
188
  fc.should_receive(:stop).twice
@@ -197,7 +199,7 @@ describe Flapjack::Coordinator do
197
199
  new_config = double('new_config')
198
200
  filename = double('filename')
199
201
 
200
- config.should_receive(:all).and_return(old_cfg)
202
+ config.should_receive(:all).twice.and_return(old_cfg)
201
203
  config.should_receive(:filename).and_return(filename)
202
204
 
203
205
  Flapjack::Configuration.should_receive(:new).and_return(new_config)
@@ -240,7 +242,7 @@ describe Flapjack::Coordinator do
240
242
  new_config = double('new_config')
241
243
  filename = double('filename')
242
244
 
243
- config.should_receive(:all).and_return(old_cfg)
245
+ config.should_receive(:all).twice.and_return(old_cfg)
244
246
  config.should_receive(:filename).and_return(filename)
245
247
 
246
248
  Flapjack::Configuration.should_receive(:new).and_return(new_config)
@@ -270,7 +272,7 @@ describe Flapjack::Coordinator do
270
272
  new_config = double('new_config')
271
273
  filename = double('filename')
272
274
 
273
- config.should_receive(:all).and_return(old_cfg)
275
+ config.should_receive(:all).twice.and_return(old_cfg)
274
276
  config.should_receive(:filename).and_return(filename)
275
277
 
276
278
  Flapjack::Configuration.should_receive(:new).and_return(new_config)
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'flapjack/logger'
2
3
 
3
4
  describe Flapjack::Logger do
4
5
 
@@ -13,19 +14,24 @@ describe Flapjack::Logger do
13
14
  logger.should_receive(:add).with(2, nil, "Yowza!")
14
15
  ::Logger.should_receive(:new).with(STDOUT).and_return(logger)
15
16
 
16
- if Syslog.const_defined?('Logger', false)
17
- sys_logger.should_receive(:formatter=).with(an_instance_of(Proc))
18
- sys_logger.should_receive(:level=).with(Logger::DEBUG)
19
- sys_logger.should_receive(:add).with(Logger::WARN, 'Yowza!', 'flapjack')
20
- Syslog.const_get('Logger', false).should_receive(:new).with('flapjack').and_return(sys_logger)
21
- else
22
- Syslog.should_receive(:open).with('flapjack',
23
- (Syslog::Constants::LOG_PID | Syslog::Constants::LOG_CONS),
24
- Syslog::Constants::LOG_USER).and_return(syslog)
25
- Syslog.should_receive(:mask=).with(Syslog::LOG_UPTO(Syslog::Constants::LOG_WARNING))
26
- Syslog.should_receive(:log).with(Syslog::Constants::LOG_WARNING, /\[WARN\] :: spec :: %s/, "Yowza!")
27
- Syslog.should_receive(:close)
28
- end
17
+ Syslog.should_receive(:open).with('flapjack',
18
+ (Syslog::Constants::LOG_PID | Syslog::Constants::LOG_CONS),
19
+ Syslog::Constants::LOG_USER).and_return(syslog)
20
+ Syslog.should_receive(:mask=).with(Syslog::LOG_UPTO(Syslog::Constants::LOG_ERR))
21
+ Syslog.should_receive(:log).with(Syslog::Constants::LOG_WARNING, /\[WARN\] :: spec :: %s/, "Yowza!")
22
+ Syslog.should_receive(:close)
23
+
24
+ flogger = Flapjack::Logger.new('spec', 'level' => 'debug', 'syslog_errors' => 'true')
25
+ flogger.warn "Yowza!"
26
+ end
27
+
28
+ it 'defaults to not logging via syslog' do
29
+ logger.should_receive(:formatter=).with(an_instance_of(Proc))
30
+ logger.should_receive(:level=).and_return(Logger::DEBUG)
31
+ logger.should_receive(:add).with(2, nil, "Yowza!")
32
+ ::Logger.should_receive(:new).with(STDOUT).and_return(logger)
33
+
34
+ Syslog.should_not_receive(:open)
29
35
 
30
36
  flogger = Flapjack::Logger.new('spec', 'level' => 'debug')
31
37
  flogger.warn "Yowza!"
@@ -14,7 +14,7 @@ namespace :benchmarks do
14
14
  require 'flapjack/data/entity_check'
15
15
  require 'flapjack/version'
16
16
 
17
- FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'test'
17
+ FLAPJACK_ENV = 'test'
18
18
  config_file = File.join('tasks', 'support', 'flapjack_config_benchmark.yaml')
19
19
 
20
20
  config = Flapjack::Configuration.new
@@ -27,32 +27,4 @@ test:
27
27
  default_contact_timezone: Australia/Broken_Hill
28
28
  logger:
29
29
  level: WARN
30
- development:
31
- pid_file: tmp/pids/flapjack_development.pid
32
- log_file: log/flapjack_development.log
33
- daemonize: no
34
- redis:
35
- host: 127.0.0.1
36
- port: 6379
37
- db: 13
38
- processor:
39
- enabled: yes
40
- queue: events
41
- notifier_queue: notifications
42
- archive_events: true
43
- events_archive_maxage: 10800
44
- new_check_scheduled_maintenance_duration: 1 month
45
- exit_on_queue_empty: true
46
- logger:
47
- level: INFO
48
- notifier:
49
- enabled: yes
50
- queue: notifications
51
- email_queue: email_notifications
52
- sms_queue: sms_notifications
53
- jabber_queue: jabber_notifications
54
- pagerduty_queue: pagerduty_notifications
55
- notification_log_file: log/notification_test.log
56
- default_contact_timezone: Australia/Broken_Hill
57
- logger:
58
- level: INFO
30
+