flapjack 0.7.1 → 0.7.2

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 (45) hide show
  1. data/CHANGELOG.md +29 -0
  2. data/README.md +1 -4
  3. data/bin/flapjack +24 -2
  4. data/bin/flapjack-nagios-receiver +4 -2
  5. data/bin/receive-events +191 -0
  6. data/bin/simulate-failed-check +144 -0
  7. data/features/notification_rules.feature +63 -2
  8. data/features/steps/events_steps.rb +15 -3
  9. data/flapjack.gemspec +1 -1
  10. data/lib/flapjack/data/contact.rb +15 -9
  11. data/lib/flapjack/data/entity.rb +19 -1
  12. data/lib/flapjack/data/entity_check.rb +12 -0
  13. data/lib/flapjack/data/event.rb +10 -2
  14. data/lib/flapjack/data/notification.rb +12 -8
  15. data/lib/flapjack/data/notification_rule.rb +3 -1
  16. data/lib/flapjack/executive.rb +71 -17
  17. data/lib/flapjack/gateways/api.rb +5 -2
  18. data/lib/flapjack/gateways/jabber.rb +26 -17
  19. data/lib/flapjack/gateways/web.rb +54 -9
  20. data/lib/flapjack/gateways/web/public/css/bootstrap-responsive.min.css +9 -0
  21. data/lib/flapjack/gateways/web/public/css/bootstrap.min.css +9 -0
  22. data/lib/flapjack/gateways/web/public/css/flapjack.css +51 -0
  23. data/lib/flapjack/gateways/web/public/img/flapjack_white_bg_400_353.jpeg +0 -0
  24. data/lib/flapjack/gateways/web/public/img/glyphicons-halflings-white.png +0 -0
  25. data/lib/flapjack/gateways/web/public/img/glyphicons-halflings.png +0 -0
  26. data/lib/flapjack/gateways/web/public/js/bootstrap.min.js +6 -0
  27. data/lib/flapjack/gateways/web/views/_foot.haml +8 -0
  28. data/lib/flapjack/gateways/web/views/_head.haml +10 -0
  29. data/lib/flapjack/gateways/web/views/_nav.haml +9 -3
  30. data/lib/flapjack/gateways/web/views/check.haml +140 -138
  31. data/lib/flapjack/gateways/web/views/checks.haml +49 -0
  32. data/lib/flapjack/gateways/web/views/contact.haml +78 -37
  33. data/lib/flapjack/gateways/web/views/contacts.haml +23 -17
  34. data/lib/flapjack/gateways/web/views/entities.haml +28 -0
  35. data/lib/flapjack/gateways/web/views/entity.haml +44 -0
  36. data/lib/flapjack/gateways/web/views/index.haml +27 -44
  37. data/lib/flapjack/gateways/web/views/self_stats.haml +65 -22
  38. data/lib/flapjack/version.rb +1 -1
  39. data/spec/lib/flapjack/executive_spec.rb +6 -2
  40. data/spec/lib/flapjack/gateways/api_spec.rb +15 -0
  41. data/spec/lib/flapjack/gateways/web/views/contact.haml_spec.rb +2 -1
  42. data/spec/lib/flapjack/gateways/web/views/index.haml_spec.rb +3 -2
  43. data/spec/lib/flapjack/gateways/web_spec.rb +23 -9
  44. data/tmp/create_events_failure.rb +6 -4
  45. metadata +23 -12
@@ -0,0 +1,49 @@
1
+ !!! 5
2
+ - nav = render_haml('_nav.haml', self)
3
+ - head = render_haml('_head.haml', self)
4
+ - foot = render_haml('_foot.haml', self)
5
+ %html
6
+ %head
7
+ %title Flapjack - #{@adjective.capitalize} Checks
8
+ = head
9
+ %body
10
+ %div#wrap
11
+ %div{:class => "container"}
12
+ %div{:class => "page-header"}
13
+ = nav
14
+ %h2 #{@adjective.capitalize} Checks
15
+ %p #{@count_failing_checks} failing out of #{@count_all_checks}
16
+ %table{:class => "table table-bordered table-hover table-condensed"}
17
+ %tr
18
+ %th Entity
19
+ %th Check
20
+ %th State
21
+ %th Last State Change
22
+ %th Last Update
23
+ %th Last Notification
24
+ - @states.each do |entity, check, status, changed, updated, in_unscheduled_outage, in_scheduled_outage, notified_kind, notified|
25
+ - colour_class = status
26
+ - case status
27
+ - when 'critical', 'unknown'
28
+ - colour_class = 'error'
29
+ - when 'ok', 'up'
30
+ - colour_class = 'success'
31
+ %tr{:class => colour_class}
32
+ %td= entity
33
+ %td
34
+ - link = "/check?entity=" + CGI.escape(entity) + "&check=" + CGI.escape(check)
35
+ %a(title='check detail' href=link) #{check}
36
+ %td{:class => status}
37
+ = status.upcase
38
+ = " (Acknowledged)" if in_unscheduled_outage
39
+ = " (Scheduled Maintenance)" if in_scheduled_outage
40
+ %td= relative_time_ago(Time.at(changed.to_i)) + ' ago'
41
+ %td= (Time.now.to_i - updated.to_i).to_s + ' seconds ago'
42
+ - if notified && (notified > 0)
43
+ - last_notified = relative_time_ago(Time.at(notified.to_i)) + " ago, #{notified_kind}"
44
+ - else
45
+ - last_notified = 'never'
46
+ %td= last_notified
47
+ %div#push
48
+ %div#footer
49
+ = foot
@@ -1,44 +1,85 @@
1
1
  !!! 5
2
2
  - nav = render_haml('_nav.haml', self)
3
- - css = render_haml('_css.haml', self)
3
+ - head = render_haml('_head.haml', self)
4
+ - foot = render_haml('_foot.haml', self)
4
5
  %html
5
6
  %head
6
- %title Flapjack - Contact: #{@contact.name}
7
- = css
7
+ %title Flapjack - #{@contact.name} (contact)
8
+ = head
8
9
  %body
9
- %div#wrapper
10
- = nav
11
- %h1= @contact.name
12
- - if @contact.media && !@contact.media.empty?
13
- %ul
14
- - @contact.media.each_pair do |mk, mv|
15
- - if 'pagerduty'.eql?(mk)
16
- %li= "PagerDuty: "
17
- %ul
18
- - @pagerduty_credentials.each_pair do |pk, pv|
19
- - if 'password'.eql?(pk)
20
- %li= "#{pk}: ..."
21
- - else
22
- %li= "#{pk}: #{pv}"
23
- - else
24
- %li= "#{mk.capitalize}: #{mv}"
25
- - else
26
- %p No media
27
- - if @entities_and_checks && !@entities_and_checks.empty?
28
- %table
29
- %tr
30
- %th Entity name
31
- %th Checks
32
- - @entities_and_checks.each do |ec|
33
- - entity = ec[:entity]
34
- - checks = ec[:checks]
10
+ %div#wrap
11
+ %div{:class => "container"}
12
+ %div{:class => "page-header"}
13
+ = nav
14
+ %h2= @contact.name
15
+ %h3= "Contact Media"
16
+ - if @contact.media && !@contact.media.empty?
17
+ %table{:class => "table table-bordered table-hover table-condensed"}
35
18
  %tr
36
- %td
37
- %p= entity.name
38
- %td
39
- - checks.each do |check|
40
- - link = "/check?entity=#{CGI.escape(entity.name)}&check=#{CGI.escape(check)}"
41
- %p
19
+ %th Media
20
+ %th Address
21
+ %th Interval
22
+ - @contact.media.each_pair do |mk, mv|
23
+ %tr
24
+ - if 'pagerduty'.eql?(mk)
25
+ %td PagerDuty
26
+ %td
27
+ - @pagerduty_credentials.each_pair do |pk, pv|
28
+ - if 'password'.eql?(pk)
29
+ %p= "#{pk}: ..."
30
+ - else
31
+ %p= "#{pk}: #{pv}"
32
+ %td -
33
+ - else
34
+ %td #{mk.capitalize}
35
+ %td #{mv}
36
+ %td
37
+ - if interval = @contact.media_intervals[mk]
38
+ #{@contact.media_intervals[mk]} seconds
39
+ - else
40
+ no custom interval
41
+ - else
42
+ %p No media
43
+ %h3= "Entities and Checks"
44
+ - if @entities_and_checks && !@entities_and_checks.empty?
45
+ %table{:class => "table table-bordered table-hover table-condensed"}
46
+ %tr
47
+ %th Entity
48
+ %th Checks
49
+ - @entities_and_checks.each do |ec|
50
+ - entity = ec[:entity]
51
+ - checks = ec[:checks]
52
+ %tr
53
+ %td
54
+ - link = "/entity/#{CGI.escape(entity.name)}"
55
+ %a(title='entity status' href=link) #{entity.name}
56
+ %td
57
+ - checks.each do |check|
58
+ - link = "/check?entity=#{CGI.escape(entity.name)}&check=#{CGI.escape(check)}"
42
59
  %a(title='check status' href=link) #{check}
43
- - else
44
- %p No entities
60
+ - else
61
+ %p No entities
62
+ %h3= "Notification Rules"
63
+ - rules = @contact.notification_rules
64
+ - if rules && rules.length > 0
65
+ %table{:class => "table table-bordered table-hover table-condensed"}
66
+ %tr
67
+ %th ID
68
+ %th Entities
69
+ %th Entity Tags
70
+ %th Warning Media
71
+ %th Critical Media
72
+ %th Time Restrictions
73
+ - rules.each do |r|
74
+ %tr
75
+ %td #{r.id}
76
+ %td #{r.entities.join(', ')}
77
+ %td #{r.entity_tags ? r.entity_tags.join(', ') : ''}
78
+ %td #{r.warning_media.join(', ')}
79
+ %td #{r.critical_media.join(', ')}
80
+ %td #{r.time_restrictions}
81
+ - else
82
+ %p No notification rules
83
+ %div#push
84
+ %div#footer
85
+ = foot
@@ -1,24 +1,30 @@
1
1
  !!! 5
2
2
  - nav = render_haml('_nav.haml', self)
3
- - css = render_haml('_css.haml', self)
3
+ - head = render_haml('_head.haml', self)
4
+ - foot = render_haml('_foot.haml', self)
4
5
  %html
5
6
  %head
6
7
  %title Flapjack - Contacts
7
- = css
8
+ = head
8
9
  %body
9
- %div#wrapper
10
- = nav
11
- %h1 Contacts
12
- - if @contacts && !@contacts.empty?
13
- %table
14
- %tr
15
- %th Name
16
- %th Email
17
- - @contacts.sort_by {|c| [c.last_name, c.first_name] }.each do |contact|
10
+ %div#wrap
11
+ %div{:class => "container"}
12
+ %div{:class => "page-header"}
13
+ = nav
14
+ %h2 Contacts
15
+ - if @contacts && !@contacts.empty?
16
+ %table{:class => "table table-bordered table-hover table-condensed"}
18
17
  %tr
19
- %td
20
- - link = "/contacts/#{contact.id}"
21
- %a(title='contact details' href=link) #{contact.name}
22
- %td= contact.email
23
- - else
24
- %p No contacts
18
+ %th Name
19
+ %th Email
20
+ - @contacts.sort_by {|c| [c.last_name, c.first_name] }.each do |contact|
21
+ %tr
22
+ %td
23
+ - link = "/contacts/#{contact.id}"
24
+ %a(title='contact details' href=link) #{contact.name}
25
+ %td= contact.email
26
+ - else
27
+ %p No contacts
28
+ %div#push
29
+ %div#footer
30
+ = foot
@@ -0,0 +1,28 @@
1
+ !!! 5
2
+ - nav = render_haml('_nav.haml', self)
3
+ - head = render_haml('_head.haml', self)
4
+ - foot = render_haml('_foot.haml', self)
5
+ %html
6
+ %head
7
+ %title Flapjack - #{@adjective.capitalize} Entities
8
+ = head
9
+ %body
10
+ %div#wrap
11
+ %div{:class => "container"}
12
+ %div{:class => "page-header"}
13
+ = nav
14
+ %h2 #{@adjective.capitalize} Entities
15
+ %p #{@count_failing_entities} failing out of #{@count_all_entities}
16
+ %table{:class => "table table-bordered table-hover table-condensed"}
17
+ - if @entities.length > 0
18
+ - @entities.each do |entity|
19
+ %tr
20
+ %td
21
+ - link = "/entity/#{CGI.escape(entity)}"
22
+ %a{:href => link}
23
+ #{entity}
24
+ - else
25
+ %p No check output has been processed yet, so there's no entities we can show you here.
26
+ %div#push
27
+ %div#footer
28
+ = foot
@@ -0,0 +1,44 @@
1
+ !!! 5
2
+ - nav = render_haml('_nav.haml', self)
3
+ - head = render_haml('_head.haml', self)
4
+ - foot = render_haml('_foot.haml', self)
5
+ %html
6
+ %head
7
+ %title Flapjack - #{@entity} (entity)
8
+ = head
9
+ %body
10
+ %div#wrap
11
+ %div{:class => "container"}
12
+ %div{:class => "page-header"}
13
+ = nav
14
+ %h2 #{@entity}
15
+ - if @states.length > 0
16
+ %table{:class => "table table-bordered table-hover table-condensed"}
17
+ %tr
18
+ %th Check
19
+ %th State
20
+ %th Last State Change
21
+ %th Last Update
22
+ %th Last Notification
23
+ - @states.each do |entity, check, status, changed, updated, in_unscheduled_outage, in_scheduled_outage, notified_kind, notified|
24
+ %tr
25
+ %td
26
+ - link = "/check?entity=" + CGI.escape(entity) + "&check=" + CGI.escape(check)
27
+ %a(title='check detail' href=link) #{check}
28
+ %td{:class => status}
29
+ = status.upcase
30
+ = " (Acknowledged)" if in_unscheduled_outage
31
+ = " (Scheduled Maintenance)" if in_scheduled_outage
32
+ %td= relative_time_ago(Time.at(changed.to_i)) + ' ago'
33
+ %td= (Time.now.to_i - updated.to_i).to_s + ' seconds ago'
34
+ - if notified && (notified > 0)
35
+ - last_notified = relative_time_ago(Time.at(notified.to_i)) + " ago, #{notified_kind}"
36
+ - else
37
+ - last_notified = 'never'
38
+ %td= last_notified
39
+ - else
40
+ %div#foo
41
+ %p This entity has no check output associated with it
42
+ %div#push
43
+ %div#footer
44
+ = foot
@@ -1,49 +1,32 @@
1
1
  !!! 5
2
2
  - nav = render_haml('_nav.haml', self)
3
- - css = render_haml('_css.haml', self)
3
+ - head = render_haml('_head.haml', self)
4
+ - foot = render_haml('_foot.haml', self)
4
5
  %html
5
6
  %head
6
- %title Flapjack
7
- = css
7
+ %title Flapjack - Summary
8
+ = head
8
9
  %body
9
- %div#wrapper
10
- = nav
11
- %h1 Flapjack Status
12
- %h4
13
- Events queued:
14
- = @events_queued
15
- %h4
16
- All checks:
17
- %a(title='all checks' href='/')
18
- = @count_all_checks
19
- %h4
20
- Failing checks:
21
- %a(title='failing checks' href='/failing')
22
- = @count_failing_checks
23
- %h3
24
- All Checks
25
- %table
26
- %tr
27
- %th Entity
28
- %th Check
29
- %th State
30
- %th Last State Change
31
- %th Last Update
32
- %th Last Notification
33
- - @states.each do |entity, check, status, changed, updated, in_unscheduled_outage, in_scheduled_outage, notified_kind, notified|
34
- %tr
35
- %td= entity
36
- %td
37
- - link = "/check?entity=" + CGI.escape(entity) + "&check=" + CGI.escape(check)
38
- %a(title='check detail' href=link) #{check}
39
- %td{:class => status}
40
- = status.upcase
41
- = " (Acknowledged)" if in_unscheduled_outage
42
- = " (Scheduled Maintenance)" if in_scheduled_outage
43
- %td= relative_time_ago(Time.at(changed.to_i)) + ' ago'
44
- %td= (Time.now.to_i - updated.to_i).to_s + ' seconds ago'
45
- - if notified && (notified > 0)
46
- - last_notified = relative_time_ago(Time.at(notified.to_i)) + " ago, #{notified_kind}"
47
- - else
48
- - last_notified = 'never'
49
- %td= last_notified
10
+ %div#wrap
11
+ %div{:class => "container"}
12
+ %div{:class => "page-header"}
13
+ = nav
14
+ %h2 Summary
15
+ %h4
16
+ %a(title='failing entities' href='/entities_failing')
17
+ #{@count_failing_entities}
18
+ out of
19
+ %a(title='all entities' href='/entities_all')
20
+ #{@count_all_entities}
21
+ entities have failing checks
22
+ %h4
23
+ %a(title='failing checks' href='/checks_failing')
24
+ #{@count_failing_checks}
25
+ out of
26
+ %a(title='all checks' href='/checks_all')
27
+ #{@count_all_checks}
28
+ checks are failing
29
+ %img{:src => '/img/flapjack_white_bg_400_353.jpeg', :height => 353, :width => 400}
30
+ %div#push
31
+ %div#footer
32
+ = foot
@@ -1,27 +1,70 @@
1
1
  !!! 5
2
2
  - nav = render_haml('_nav.haml', self)
3
- - css = render_haml('_css.haml', self)
3
+ - head = render_haml('_head.haml', self)
4
+ - foot = render_haml('_foot.haml', self)
4
5
  %html
5
6
  %head
6
- %title Flapjack - Self Stats
7
- = css
7
+ %title Flapjack - Internal Statistics
8
+ = head
8
9
  %body
9
- %div#wrapper
10
- = nav
11
- %h1 Flapjack Self Status
12
- %h4
13
- Events queued:
14
- = @events_queued
15
- %h4
16
- Number of failing services:
17
- = @count
18
- %p Events processed (all time): #{@event_counters['all']} (ok: #{@event_counters['ok']}, failure: #{@event_counters['failure']}, action: #{@event_counters['action']})
19
- %p Events processed (this instance): #{@event_counters_instance['all']} (ok: #{@event_counters_instance['ok']}, failure: #{@event_counters_instance['failure']}, action: #{@event_counters_instance['action']})
20
- %p Average rate (this instance): #{@event_rate_all} events per second
21
- %p Total keys in redis: #{@keys.length}
22
- %p Uptime: #{@uptime_string}
23
- %p Boot time: #{@boot_time}
24
- %p Current time: #{Time.now}
25
- %p Executive Instances: #{@executive_instances.inspect}
26
- %p
27
- %a{:href => 'self_stats.json'} Instrument as JSON
10
+ %div#wrap
11
+ %div{:class => "container"}
12
+ %div{:class => "page-header"}
13
+ = nav
14
+ %h2 Internal Statistics
15
+ %table{:class => "table table-bordered table-hover table-condensed"}
16
+ %tr
17
+ %td Events queued:
18
+ %td= @events_queued
19
+ %tr
20
+ %td Number of entities:
21
+ %td= @count_all_entities
22
+ %tr
23
+ %td Number of failing entities:
24
+ %td= @count_failing_entities
25
+ %tr
26
+ %td Number of checks:
27
+ %td= @count_all_checks
28
+ %tr
29
+ %td Number of failing checks:
30
+ %td= @count_failing_checks
31
+ %tr
32
+ %td Events processed (all time)
33
+ %td #{@event_counters['all']} (ok: #{@event_counters['ok']}, failure: #{@event_counters['failure']}, action: #{@event_counters['action']})
34
+ %tr
35
+ %td Events processed (this instance)
36
+ %td #{@event_counters_instance['all']} (ok: #{@event_counters_instance['ok']}, failure: #{@event_counters_instance['failure']}, action: #{@event_counters_instance['action']})
37
+ %tr
38
+ %td Average rate (this instance)
39
+ %td #{@event_rate_all} events per second
40
+ %tr
41
+ %td Total keys in redis
42
+ %td #{@keys.length}
43
+ %tr
44
+ %td Uptime
45
+ %td= @uptime_string
46
+ %tr
47
+ %td Boot time
48
+ %td= @boot_time
49
+ %tr
50
+ %td Current time
51
+ %td= Time.now
52
+ %h4
53
+ Executive Instances:
54
+ %table{:class => "table table-bordered table-hover"}
55
+ %tr
56
+ %th Hostname
57
+ %th PID
58
+ %th Started
59
+ - @executive_instances.each do |i|
60
+ - hostname, pid = i[0].split(':')
61
+ - started = "#{relative_time_ago(Time.at(i[1].to_i))} ago"
62
+ %tr
63
+ %td= hostname
64
+ %td= pid
65
+ %td= started
66
+ %p
67
+ %a{:href => 'self_stats.json'} Instrument as JSON
68
+ %div#push
69
+ %div#footer
70
+ = foot