flapjack 0.7.1 → 0.7.2

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