flapjack 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +17 -7
- data/bin/flapjack-nagios-receiver +1 -1
- data/etc/flapjack_config.yaml.example +5 -22
- data/lib/flapjack/data/contact.rb +5 -1
- data/lib/flapjack/data/event.rb +20 -7
- data/lib/flapjack/executive.rb +6 -1
- data/lib/flapjack/gateways/api.rb +5 -1
- data/lib/flapjack/pikelet.rb +10 -0
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/gateways/api_spec.rb +89 -3
- metadata +8 -2
data/README.md
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
[id_travis_link]: https://secure.travis-ci.org/#!/flpjck/flapjack
|
6
6
|
[id_travis_img]: https://secure.travis-ci.org/flpjck/flapjack.png
|
7
7
|
|
8
|
+
[flapjack-project.com](http://flapjack-project.com/)
|
9
|
+
|
8
10
|
Flapjack is a highly scalable and distributed monitoring notification system.
|
9
11
|
|
10
12
|
Flapjack provides a scalable method for dealing with events representing changes in system state (OK -> WARNING -> CRITICAL transitions) and alerting appropriate people as necessary.
|
@@ -16,17 +18,13 @@ Flapjack's `executive` component picks up the events and processes them -- decid
|
|
16
18
|
Additional check engines can be supported by adding additional receiver processes similar to the nagios receiver.
|
17
19
|
|
18
20
|
|
19
|
-
## Using
|
20
|
-
|
21
|
-
### Quickstart
|
22
|
-
|
23
|
-
TODO numbered list for simplest possible Flapjack run.
|
21
|
+
## Using
|
24
22
|
|
25
|
-
For more information, including full specification of the configuration file and the data import formats, please refer to the [
|
23
|
+
For more information, including full specification of the configuration file and the data import formats, please refer to the [USING](https://github.com/flpjck/flapjack/wiki/USING) section of the Flapjack wiki
|
26
24
|
|
27
25
|
## Developing Flapjack
|
28
26
|
|
29
|
-
Information on developing more Flapjack components or contributing to core Flapjack development can be found in the [
|
27
|
+
Information on developing more Flapjack components or contributing to core Flapjack development can be found in the [DEVELOPING](https://github.com/flpjck/flapjack/wiki/DEVELOPING) section of the Flapjack wiki
|
30
28
|
|
31
29
|
## Documentation Submodule
|
32
30
|
|
@@ -43,4 +41,16 @@ If you make changes to the documentation locally, here's how to publish them:
|
|
43
41
|
* git add, commit and push from inside the doc subdir
|
44
42
|
* Add, commit and push the doc dir from the root (this updates the pointer in the main git repo to the correct ref in the doc repo, we think...)
|
45
43
|
|
44
|
+
## More on the wiki
|
45
|
+
|
46
|
+
https://github.com/flpjck/flapjack/wiki has even more goodies:
|
47
|
+
|
48
|
+
- [Using Flapjack](https://github.com/flpjck/flapjack/wiki/USING)
|
49
|
+
- [Developing Flapjack](https://github.com/flpjck/flapjack/wiki/DEVELOPING)
|
50
|
+
- [Redis Data Structure](https://github.com/flpjck/flapjack/wiki/DATA_STRUCTURES)
|
51
|
+
- [API](https://github.com/flpjck/flapjack/wiki/API)
|
52
|
+
- [Importing](https://github.com/flpjck/flapjack/wiki/IMPORTING)
|
53
|
+
- [Debugging Flapjack](https://github.com/flpjck/flapjack/wiki/DEBUGGING)
|
54
|
+
- [Flapjack Glossary](https://github.com/flpjck/flapjack/wiki/GLOSSARY)
|
55
|
+
|
46
56
|
|
@@ -51,7 +51,7 @@ def process_input(opts)
|
|
51
51
|
'summary' => check_output,
|
52
52
|
'timestamp' => timestamp,
|
53
53
|
}.to_json
|
54
|
-
redis.
|
54
|
+
redis.lpush 'events', event
|
55
55
|
end
|
56
56
|
rescue Redis::CannotConnectError
|
57
57
|
puts "Error, unable to to connect to the redis server (#{$!})"
|
@@ -1,26 +1,5 @@
|
|
1
1
|
---
|
2
2
|
|
3
|
-
quickstart:
|
4
|
-
redis:
|
5
|
-
host: 127.0.0.1
|
6
|
-
port: 6379
|
7
|
-
db: 6
|
8
|
-
executive:
|
9
|
-
enabled: yes
|
10
|
-
email_queue: email_notifications
|
11
|
-
notification_log_file: log/flapjack-notification.log
|
12
|
-
gateways:
|
13
|
-
email:
|
14
|
-
enabled: yes
|
15
|
-
queue: email_notifications
|
16
|
-
smtp_config:
|
17
|
-
address: "localhost"
|
18
|
-
domain: 'localhost.localdomain'
|
19
|
-
port: 25
|
20
|
-
web:
|
21
|
-
enabled: yes
|
22
|
-
port: 5080
|
23
|
-
|
24
3
|
development:
|
25
4
|
pid_file: tmp/pids/flapjack.pid
|
26
5
|
log_file: log/flapjack.log
|
@@ -34,7 +13,11 @@ development:
|
|
34
13
|
email_queue: email_notifications
|
35
14
|
sms_queue: sms_notifications
|
36
15
|
jabber_queue: jabber_notifications
|
37
|
-
|
16
|
+
pagerduty_queue: pagerduty_notifications
|
17
|
+
notification_log_file: log/notification.log
|
18
|
+
default_contact_timezone: Australia/Broken_Hill
|
19
|
+
archive_events: true
|
20
|
+
events_archive_maxage: 10800
|
38
21
|
logger:
|
39
22
|
level: INFO
|
40
23
|
gateways:
|
@@ -276,6 +276,8 @@ module Flapjack
|
|
276
276
|
|
277
277
|
# return the timezone of the contact, or the system default if none is set
|
278
278
|
def timezone(opts = {})
|
279
|
+
logger = opts[:logger]
|
280
|
+
|
279
281
|
tz_string = @redis.get("contact_tz:#{self.id}")
|
280
282
|
tz = opts[:default] if (tz_string.nil? || tz_string.empty?)
|
281
283
|
|
@@ -283,7 +285,9 @@ module Flapjack
|
|
283
285
|
begin
|
284
286
|
tz = ActiveSupport::TimeZone.new(tz_string)
|
285
287
|
rescue ArgumentError
|
286
|
-
logger
|
288
|
+
if logger
|
289
|
+
logger.warn("Invalid timezone string set for contact #{self.id} or TZ (#{tz_string}), using 'UTC'!")
|
290
|
+
end
|
287
291
|
tz = ActiveSupport::TimeZone.new('UTC')
|
288
292
|
end
|
289
293
|
end
|
data/lib/flapjack/data/event.rb
CHANGED
@@ -21,17 +21,30 @@ module Flapjack
|
|
21
21
|
def self.next(opts={})
|
22
22
|
raise "Redis connection not set" unless redis = opts[:redis]
|
23
23
|
|
24
|
-
defaults = { :block => true
|
24
|
+
defaults = { :block => true,
|
25
|
+
:archive_events => false,
|
26
|
+
:events_archive_maxage => (3 * 60 * 60) }
|
25
27
|
options = defaults.merge(opts)
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
29
|
+
if options[:archive_events]
|
30
|
+
dest = "events_archive:#{Time.now.utc.strftime "%Y%m%d%H"}"
|
31
|
+
if options[:block]
|
32
|
+
raw = redis.brpoplpush('events', dest, 0)
|
33
|
+
else
|
34
|
+
raw = redis.rpoplpush('events', dest)
|
35
|
+
return unless raw
|
36
|
+
end
|
37
|
+
redis.expire(dest, options[:events_archive_maxage])
|
38
|
+
else
|
39
|
+
if options[:block]
|
40
|
+
raw = redis.brpop('events', 0)[1]
|
41
|
+
else
|
42
|
+
raw = redis.rpop('events')
|
43
|
+
return unless raw
|
44
|
+
end
|
30
45
|
end
|
46
|
+
return self.new( ::JSON.parse( raw ) )
|
31
47
|
|
32
|
-
# In testing, we take care that there are no events on the queue.
|
33
|
-
return unless raw = redis.lpop('events')
|
34
|
-
self.new( ::JSON.parse(raw) )
|
35
48
|
end
|
36
49
|
|
37
50
|
# creates, or modifies, an event object and adds it to the events list in redis
|
data/lib/flapjack/executive.rb
CHANGED
@@ -57,6 +57,9 @@ module Flapjack
|
|
57
57
|
end
|
58
58
|
@default_contact_timezone = tz
|
59
59
|
|
60
|
+
@archive_events = @config['archive_events'] || false
|
61
|
+
@events_archive_maxage = @config['events_archive_maxage']
|
62
|
+
|
60
63
|
# FIXME: Put loading filters into separate method
|
61
64
|
# FIXME: should we make the filters more configurable by the end user?
|
62
65
|
options = { :log => opts[:logger], :persistence => @redis }
|
@@ -100,7 +103,9 @@ module Flapjack
|
|
100
103
|
|
101
104
|
until @should_quit
|
102
105
|
@logger.debug("Waiting for event...")
|
103
|
-
event = Flapjack::Data::Event.next(:redis => @redis
|
106
|
+
event = Flapjack::Data::Event.next(:redis => @redis,
|
107
|
+
:archive_events => @archive_events,
|
108
|
+
:events_archive_maxage => @events_archive_maxage)
|
104
109
|
process_event(event) unless event.nil?
|
105
110
|
end
|
106
111
|
|
@@ -100,7 +100,7 @@ module Flapjack
|
|
100
100
|
entity.check_list.to_json
|
101
101
|
end
|
102
102
|
|
103
|
-
get %r{/status/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(
|
103
|
+
get %r{/status/([a-zA-Z0-9][a-zA-Z0-9\.\-]*[a-zA-Z0-9])(?:/(.+))?} do
|
104
104
|
content_type :json
|
105
105
|
|
106
106
|
entity_name = params[:captures][0]
|
@@ -119,6 +119,10 @@ module Flapjack
|
|
119
119
|
entity_check_status(entity, c)
|
120
120
|
}
|
121
121
|
end
|
122
|
+
if ret.nil?
|
123
|
+
status 404
|
124
|
+
return
|
125
|
+
end
|
122
126
|
ret.to_json
|
123
127
|
end
|
124
128
|
|
data/lib/flapjack/pikelet.rb
CHANGED
@@ -26,6 +26,16 @@ require 'flapjack/gateways/email'
|
|
26
26
|
require 'flapjack/gateways/sms_messagenet'
|
27
27
|
require 'flapjack/gateways/web'
|
28
28
|
require 'flapjack/logger'
|
29
|
+
require 'thin/version'
|
30
|
+
|
31
|
+
|
32
|
+
module Thin
|
33
|
+
# disable Thin's loading of daemons
|
34
|
+
# workaround for https://github.com/flpjck/flapjack/issues/133
|
35
|
+
def self.win?
|
36
|
+
true
|
37
|
+
end
|
38
|
+
end
|
29
39
|
|
30
40
|
module Flapjack
|
31
41
|
|
data/lib/flapjack/version.rb
CHANGED
@@ -74,14 +74,100 @@ describe 'Flapjack::Gateways::API', :sinatra => true, :logger => true, :json =>
|
|
74
74
|
end
|
75
75
|
|
76
76
|
it "returns a list of checks for an entity" do
|
77
|
-
check_list
|
78
|
-
entity.should_receive(:check_list).and_return(check_list)
|
77
|
+
entity.should_receive(:check_list).and_return([check])
|
79
78
|
Flapjack::Data::Entity.should_receive(:find_by_name).
|
80
79
|
with(entity_name, :redis => redis).and_return(entity)
|
81
80
|
|
82
81
|
get "/checks/#{entity_name_esc}"
|
83
82
|
last_response.should be_ok
|
84
|
-
last_response.body.should ==
|
83
|
+
last_response.body.should == [check].to_json
|
84
|
+
end
|
85
|
+
|
86
|
+
it "returns the status for all checks on an entity" do
|
87
|
+
entity.should_receive(:check_list).and_return([check])
|
88
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
89
|
+
with(entity_name, :redis => redis).and_return(entity)
|
90
|
+
|
91
|
+
now = Time.now.to_i
|
92
|
+
|
93
|
+
entity_check.should_receive(:state).and_return('OK')
|
94
|
+
entity_check.should_receive(:in_unscheduled_maintenance?).and_return(false)
|
95
|
+
entity_check.should_receive(:in_scheduled_maintenance?).and_return(false)
|
96
|
+
entity_check.should_receive(:last_update).and_return(now - 30)
|
97
|
+
entity_check.should_receive(:last_problem_notification).and_return(now - 60)
|
98
|
+
entity_check.should_receive(:last_recovery_notification).and_return(now - 30)
|
99
|
+
entity_check.should_receive(:last_acknowledgement_notification).and_return(now - 45)
|
100
|
+
Flapjack::Data::EntityCheck.should_receive(:for_entity).
|
101
|
+
with(entity, check, :redis => redis).and_return(entity_check)
|
102
|
+
|
103
|
+
get "/status/#{entity_name_esc}"
|
104
|
+
last_response.should be_ok
|
105
|
+
last_response.body.should == [{'name' => check,
|
106
|
+
'state' => 'OK',
|
107
|
+
'in_unscheduled_maintenance' => false,
|
108
|
+
'in_scheduled_maintenance' => false,
|
109
|
+
'last_update' => (now - 30),
|
110
|
+
'last_problem_notification' => (now - 60),
|
111
|
+
'last_recovery_notification' => (now - 30),
|
112
|
+
'last_acknowledgement_notification' => (now - 45)
|
113
|
+
}].to_json
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should not show the status for an entity that's not found" do
|
117
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
118
|
+
with(entity_name, :redis => redis).and_return(nil)
|
119
|
+
|
120
|
+
get "/status/#{entity_name_esc}"
|
121
|
+
last_response.should be_not_found
|
122
|
+
end
|
123
|
+
|
124
|
+
it "returns the status for a check (with non-word characters) on an entity" do
|
125
|
+
nw_check = "HTTP Port 443"
|
126
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
127
|
+
with(entity_name, :redis => redis).and_return(entity)
|
128
|
+
|
129
|
+
now = Time.now.to_i
|
130
|
+
|
131
|
+
entity_check.should_receive(:state).and_return('OK')
|
132
|
+
entity_check.should_receive(:in_unscheduled_maintenance?).and_return(false)
|
133
|
+
entity_check.should_receive(:in_scheduled_maintenance?).and_return(false)
|
134
|
+
entity_check.should_receive(:last_update).and_return(now - 30)
|
135
|
+
entity_check.should_receive(:last_problem_notification).and_return(now - 60)
|
136
|
+
entity_check.should_receive(:last_recovery_notification).and_return(now - 30)
|
137
|
+
entity_check.should_receive(:last_acknowledgement_notification).and_return(now - 45)
|
138
|
+
Flapjack::Data::EntityCheck.should_receive(:for_entity).
|
139
|
+
with(entity, nw_check, :redis => redis).and_return(entity_check)
|
140
|
+
|
141
|
+
get "/status/#{entity_name_esc}/#{URI.escape(nw_check)}"
|
142
|
+
last_response.should be_ok
|
143
|
+
last_response.body.should == {'name' => nw_check,
|
144
|
+
'state' => 'OK',
|
145
|
+
'in_unscheduled_maintenance' => false,
|
146
|
+
'in_scheduled_maintenance' => false,
|
147
|
+
'last_update' => (now - 30),
|
148
|
+
'last_problem_notification' => (now - 60),
|
149
|
+
'last_recovery_notification' => (now - 30),
|
150
|
+
'last_acknowledgement_notification' => (now - 45)
|
151
|
+
}.to_json
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should not show the status for a check on an entity that's not found" do
|
155
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
156
|
+
with(entity_name, :redis => redis).and_return(nil)
|
157
|
+
|
158
|
+
get "/status/#{entity_name_esc}/#{check}"
|
159
|
+
last_response.should be_not_found
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should not show the status for a check that's not found on an entity" do
|
163
|
+
Flapjack::Data::Entity.should_receive(:find_by_name).
|
164
|
+
with(entity_name, :redis => redis).and_return(entity)
|
165
|
+
|
166
|
+
Flapjack::Data::EntityCheck.should_receive(:for_entity).
|
167
|
+
with(entity, check, :redis => redis).and_return(nil)
|
168
|
+
|
169
|
+
get "/status/#{entity_name_esc}/#{check}"
|
170
|
+
last_response.should be_not_found
|
85
171
|
end
|
86
172
|
|
87
173
|
it "returns a list of scheduled maintenance periods for an entity" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flapjack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-04-
|
14
|
+
date: 2013-04-24 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: dante
|
@@ -534,12 +534,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
534
534
|
- - ! '>='
|
535
535
|
- !ruby/object:Gem::Version
|
536
536
|
version: '0'
|
537
|
+
segments:
|
538
|
+
- 0
|
539
|
+
hash: 308146534625742434
|
537
540
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
538
541
|
none: false
|
539
542
|
requirements:
|
540
543
|
- - ! '>='
|
541
544
|
- !ruby/object:Gem::Version
|
542
545
|
version: '0'
|
546
|
+
segments:
|
547
|
+
- 0
|
548
|
+
hash: 308146534625742434
|
543
549
|
requirements: []
|
544
550
|
rubyforge_project:
|
545
551
|
rubygems_version: 1.8.23
|