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.
- data/CHANGELOG.md +29 -0
- data/README.md +1 -4
- data/bin/flapjack +24 -2
- data/bin/flapjack-nagios-receiver +4 -2
- data/bin/receive-events +191 -0
- data/bin/simulate-failed-check +144 -0
- data/features/notification_rules.feature +63 -2
- data/features/steps/events_steps.rb +15 -3
- data/flapjack.gemspec +1 -1
- data/lib/flapjack/data/contact.rb +15 -9
- data/lib/flapjack/data/entity.rb +19 -1
- data/lib/flapjack/data/entity_check.rb +12 -0
- data/lib/flapjack/data/event.rb +10 -2
- data/lib/flapjack/data/notification.rb +12 -8
- data/lib/flapjack/data/notification_rule.rb +3 -1
- data/lib/flapjack/executive.rb +71 -17
- data/lib/flapjack/gateways/api.rb +5 -2
- data/lib/flapjack/gateways/jabber.rb +26 -17
- data/lib/flapjack/gateways/web.rb +54 -9
- data/lib/flapjack/gateways/web/public/css/bootstrap-responsive.min.css +9 -0
- data/lib/flapjack/gateways/web/public/css/bootstrap.min.css +9 -0
- data/lib/flapjack/gateways/web/public/css/flapjack.css +51 -0
- data/lib/flapjack/gateways/web/public/img/flapjack_white_bg_400_353.jpeg +0 -0
- data/lib/flapjack/gateways/web/public/img/glyphicons-halflings-white.png +0 -0
- data/lib/flapjack/gateways/web/public/img/glyphicons-halflings.png +0 -0
- data/lib/flapjack/gateways/web/public/js/bootstrap.min.js +6 -0
- data/lib/flapjack/gateways/web/views/_foot.haml +8 -0
- data/lib/flapjack/gateways/web/views/_head.haml +10 -0
- data/lib/flapjack/gateways/web/views/_nav.haml +9 -3
- data/lib/flapjack/gateways/web/views/check.haml +140 -138
- data/lib/flapjack/gateways/web/views/checks.haml +49 -0
- data/lib/flapjack/gateways/web/views/contact.haml +78 -37
- data/lib/flapjack/gateways/web/views/contacts.haml +23 -17
- data/lib/flapjack/gateways/web/views/entities.haml +28 -0
- data/lib/flapjack/gateways/web/views/entity.haml +44 -0
- data/lib/flapjack/gateways/web/views/index.haml +27 -44
- data/lib/flapjack/gateways/web/views/self_stats.haml +65 -22
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/executive_spec.rb +6 -2
- data/spec/lib/flapjack/gateways/api_spec.rb +15 -0
- data/spec/lib/flapjack/gateways/web/views/contact.haml_spec.rb +2 -1
- data/spec/lib/flapjack/gateways/web/views/index.haml_spec.rb +3 -2
- data/spec/lib/flapjack/gateways/web_spec.rb +23 -9
- data/tmp/create_events_failure.rb +6 -4
- 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
|
-
-
|
3
|
+
- head = render_haml('_head.haml', self)
|
4
|
+
- foot = render_haml('_foot.haml', self)
|
4
5
|
%html
|
5
6
|
%head
|
6
|
-
%title Flapjack -
|
7
|
-
=
|
7
|
+
%title Flapjack - #{@contact.name} (contact)
|
8
|
+
= head
|
8
9
|
%body
|
9
|
-
%div#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
%
|
37
|
-
|
38
|
-
%
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
44
|
-
|
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
|
-
-
|
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
|
-
=
|
8
|
+
= head
|
8
9
|
%body
|
9
|
-
%div#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
%
|
20
|
-
|
21
|
-
|
22
|
-
%
|
23
|
-
|
24
|
-
|
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
|
-
-
|
3
|
+
- head = render_haml('_head.haml', self)
|
4
|
+
- foot = render_haml('_foot.haml', self)
|
4
5
|
%html
|
5
6
|
%head
|
6
|
-
%title Flapjack
|
7
|
-
=
|
7
|
+
%title Flapjack - Summary
|
8
|
+
= head
|
8
9
|
%body
|
9
|
-
%div#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
=
|
19
|
-
|
20
|
-
|
21
|
-
%
|
22
|
-
=
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
-
|
3
|
+
- head = render_haml('_head.haml', self)
|
4
|
+
- foot = render_haml('_foot.haml', self)
|
4
5
|
%html
|
5
6
|
%head
|
6
|
-
%title Flapjack -
|
7
|
-
=
|
7
|
+
%title Flapjack - Internal Statistics
|
8
|
+
= head
|
8
9
|
%body
|
9
|
-
%div#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|