sensu 0.6.8 → 0.6.9

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,4 @@ pkg/*
3
3
  \#*
4
4
  dump.rdb
5
5
  .DS_Store
6
+ *.png
data/README.org CHANGED
@@ -1,61 +1,28 @@
1
1
  * Welcome to Sensu
2
- Sensu is a monitoring system framework, handling the remote execution of checks.
2
+ Sensu is a monitoring system framework.
3
3
 
4
- Checks can utilize user created plugins, returning an exit status code and outputting to STDOUT.
5
-
6
- Check results are handled by user created handlers.
4
+ [[https://github.com/sonian/sensu/raw/master/sensu-logo.png]]
7
5
 
8
- Documentation can be found [[https://github.com/sonian/sensu/wiki][here]].
6
+ Checks can utilize user created plugins, returning an exit status code and outputting to STDOUT.
9
7
 
8
+ Check results are handled by user created handlers, receiving JSON formatted event data from STDIN.
9
+ * Documentation
10
+ Documentation can be found [[https://github.com/sonian/sensu/wiki][HERE]].
10
11
  * License
11
12
  Sensu is released under the [[https://github.com/sonian/sensu/blob/master/MIT-LICENSE.txt][MIT license]].
12
-
13
13
  * Contributing
14
14
  - [[http://help.github.com/fork-a-repo/][Fork]] [[https://github.com/sonian/sensu][Sensu]]
15
15
  - Use a [[https://github.com/dchelimsky/rspec/wiki/Topic-Branches][topic branch]]
16
16
  - Create a [[http://help.github.com/send-pull-requests/][pull request]]
17
17
 
18
18
  Keep it simple.
19
-
20
- ** Readme Driven Development
21
- *** A Client Will
22
- - Have a set of attributes to describe it, including its responsibilities
23
- - Send keep-alives to a server
24
- - Subscribe to a queue bound to a set of fanout exchanges, determined by its responsibilities
25
- - Substitute tokens in check commands with their matching client attribute
26
- - Report when it does not have a client attribute for token substitution
27
- - Receive checks from subscriptions, execute them, and publish the results to a queue with its client name
28
- - Not allow overlapping check executions of the same name
29
- - Report when it is unaware of a check it received from a subscription
30
-
31
- *** A Server Will
32
- - Subscribe to a queue for check results, another for keep-alives
33
- - Pull keep-alives, storing client details
34
- - Publish checks on defined intervals to their associated fanout exchanges
35
- - Pull check results, storing the latest events for clients, a good result will flush a previous event for that client
36
- - Create an event when it stops receiving keep-alives from a client, a new keep-alive for the client will clear the event
37
- - Trigger a event handler, either the default handler or one specified for the check, providing it with a JSON event file
38
-
39
- *** An API Will
40
- - List all current events
41
- - List all clients and their attributes
42
- - Show a client and its attributes
43
- - Remove a client and resolve associated events
44
-
45
- *** A Plugin Will
46
- - Output to STDOUT
47
- - Return a valid exit status code
48
-
49
- *** A Handler Will
50
- - Accept a command line argument "-f", for an event file path
51
- - Parse the JSON event file
52
- - Handle the event as it wishes
53
-
54
19
  ** Testing
55
20
  *** Requirements
56
- - RabbitMQ (default configuration)
57
- - Redis (default configuration)
58
-
59
- *** MiniTest
60
-
21
+ - RabbitMQ
22
+ - Redis
23
+ *** Running
24
+ : bundle install
61
25
  : rake test
26
+ * Contributors
27
+ - Sean Porter ([[https://twitter.com/#!/portertech][@portertech]])
28
+ - Justin Kolberg ([[https://twitter.com/#!/amdprophet][@amdprophet]])
data/lib/sensu.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sensu
2
- VERSION = "0.6.8"
2
+ VERSION = "0.6.9"
3
3
  end
data/lib/sensu/api.rb CHANGED
File without changes
data/lib/sensu/client.rb CHANGED
@@ -8,7 +8,7 @@ module Sensu
8
8
  client.setup_amqp
9
9
  client.setup_keepalives
10
10
  client.setup_subscriptions
11
- client.monitor_queues
11
+ client.setup_queue_monitor
12
12
 
13
13
  Signal.trap('INT') do
14
14
  EM.stop
@@ -90,7 +90,7 @@ module Sensu
90
90
  end
91
91
  end
92
92
 
93
- def monitor_queues
93
+ def setup_queue_monitor
94
94
  EM.add_periodic_timer(5) do
95
95
  unless @check_queue.subscribed?
96
96
  @check_queue.delete
data/lib/sensu/server.rb CHANGED
@@ -19,7 +19,7 @@ module Sensu
19
19
  server.setup_publisher
20
20
  server.setup_keepalive_monitor
21
21
  end
22
- server.monitor_queues
22
+ server.setup_queue_monitor
23
23
 
24
24
  Signal.trap('INT') do
25
25
  EM.stop
@@ -83,29 +83,68 @@ module Sensu
83
83
  unless client_json.nil?
84
84
  client = JSON.parse(client_json)
85
85
  check = result['check']
86
- check.merge!(@settings['checks'][check['name']]) if @settings['checks'].has_key?(check['name'])
86
+ if @settings['checks'][check['name']]
87
+ check.merge!(@settings['checks'][check['name']])
88
+ end
87
89
  check['handler'] ||= 'default'
88
90
  event = {'client' => client, 'check' => check, 'occurrences' => 1}
89
91
  if check['type'] == 'metric'
90
92
  handle_event(event)
91
93
  else
92
- @redis.hget('events:' + client['name'], check['name']).callback do |event_json|
93
- previous_event = event_json ? JSON.parse(event_json) : nil
94
- if previous_event && check['status'] == 0
95
- @redis.hdel('events:' + client['name'], check['name'])
96
- event['action'] = 'resolve'
97
- handle_event(event)
98
- elsif check['status'] > 0
99
- if previous_event && check['status'] == previous_event['status']
100
- event['occurrences'] = previous_event['occurrences'] += 1
94
+ history_key = 'history:' + client['name'] + ':' + check['name']
95
+ @redis.rpush(history_key, check['status']).callback do
96
+ @redis.lrange(history_key, -21, -1).callback do |history|
97
+ total_state_change = 0
98
+ unless history.count < 21
99
+ state_changes = 0
100
+ change_weight = 0.8
101
+ history.each do |status|
102
+ previous_status ||= status
103
+ unless status == previous_status
104
+ state_changes += change_weight
105
+ end
106
+ change_weight += 0.02
107
+ previous_status = status
108
+ end
109
+ total_state_change = (state_changes.fdiv(20) * 100).to_i
110
+ @redis.lpop(history_key)
101
111
  end
102
- @redis.hset('events:' + client['name'], check['name'], {
103
- 'status' => check['status'],
104
- 'output' => check['output'],
105
- 'occurrences' => event['occurrences']
106
- }.to_json).callback do
107
- event['action'] = 'create'
108
- handle_event(event)
112
+ high_flap_threshold = check['high_flap_threshold'] || 50
113
+ low_flap_threshold = check['low_flap_threshold'] || 40
114
+ @redis.hget('events:' + client['name'], check['name']).callback do |event_json|
115
+ previous_event = event_json ? JSON.parse(event_json) : false
116
+ flapping = previous_event ? previous_event['flapping'] : false
117
+ check['flapping'] = case
118
+ when total_state_change >= high_flap_threshold
119
+ true
120
+ when flapping && total_state_change <= low_flap_threshold
121
+ false
122
+ else
123
+ flapping
124
+ end
125
+ if previous_event && check['status'] == 0
126
+ unless check['flapping']
127
+ @redis.hdel('events:' + client['name'], check['name']).callback do
128
+ event['action'] = 'resolve'
129
+ handle_event(event)
130
+ end
131
+ else
132
+ @redis.hset('events:' + client['name'], check['name'], previous_event.merge({'flapping' => true}).to_json)
133
+ end
134
+ elsif check['status'] != 0
135
+ if previous_event && check['status'] == previous_event['status']
136
+ event['occurrences'] = previous_event['occurrences'] += 1
137
+ end
138
+ @redis.hset('events:' + client['name'], check['name'], {
139
+ 'status' => check['status'],
140
+ 'output' => check['output'],
141
+ 'flapping' => check['flapping'],
142
+ 'occurrences' => event['occurrences']
143
+ }.to_json).callback do
144
+ event['action'] = 'create'
145
+ handle_event(event)
146
+ end
147
+ end
109
148
  end
110
149
  end
111
150
  end
@@ -153,17 +192,17 @@ module Sensu
153
192
  when time_since_last_check >= 180
154
193
  result['check']['status'] = 2
155
194
  result['check']['output'] = 'No keep-alive sent from host in over 180 seconds'
156
- @result_queue.publish(result.to_json)
195
+ process_result(result)
157
196
  when time_since_last_check >= 120
158
197
  result['check']['status'] = 1
159
198
  result['check']['output'] = 'No keep-alive sent from host in over 120 seconds'
160
- @result_queue.publish(result.to_json)
199
+ process_result(result)
161
200
  else
162
201
  @redis.hexists('events:' + client_id, 'keepalive').callback do |exists|
163
202
  if exists == 1
164
203
  result['check']['status'] = 0
165
204
  result['check']['output'] = 'Keep-alive sent from host'
166
- @result_queue.publish(result.to_json)
205
+ process_result(result)
167
206
  end
168
207
  end
169
208
  end
@@ -173,7 +212,7 @@ module Sensu
173
212
  end
174
213
  end
175
214
 
176
- def monitor_queues
215
+ def setup_queue_monitor
177
216
  EM.add_periodic_timer(5) do
178
217
  unless @keepalive_queue.subscribed?
179
218
  setup_keepalives
metadata CHANGED
@@ -1,193 +1,149 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: sensu
3
- version: !ruby/object:Gem::Version
4
- hash: 23
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 6
9
- - 8
10
- version: 0.6.8
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.9
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Sean Porter
14
9
  - Justin Kolberg
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
-
19
- date: 2011-10-07 00:00:00 -07:00
20
- default_executable:
21
- dependencies:
22
- - !ruby/object:Gem::Dependency
13
+ date: 2011-10-13 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
23
16
  name: amqp
24
- prerelease: false
25
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: &70143497848320 !ruby/object:Gem::Requirement
26
18
  none: false
27
- requirements:
28
- - - "="
29
- - !ruby/object:Gem::Version
30
- hash: 11
31
- segments:
32
- - 0
33
- - 7
34
- - 4
19
+ requirements:
20
+ - - =
21
+ - !ruby/object:Gem::Version
35
22
  version: 0.7.4
36
23
  type: :runtime
37
- version_requirements: *id001
38
- - !ruby/object:Gem::Dependency
39
- name: json
40
24
  prerelease: false
41
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: *70143497848320
26
+ - !ruby/object:Gem::Dependency
27
+ name: json
28
+ requirement: &70143497846580 !ruby/object:Gem::Requirement
42
29
  none: false
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- hash: 3
47
- segments:
48
- - 0
49
- version: "0"
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
50
34
  type: :runtime
51
- version_requirements: *id002
52
- - !ruby/object:Gem::Dependency
53
- name: uuidtools
54
35
  prerelease: false
55
- requirement: &id003 !ruby/object:Gem::Requirement
36
+ version_requirements: *70143497846580
37
+ - !ruby/object:Gem::Dependency
38
+ name: uuidtools
39
+ requirement: &70143497845280 !ruby/object:Gem::Requirement
56
40
  none: false
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- hash: 3
61
- segments:
62
- - 0
63
- version: "0"
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
64
45
  type: :runtime
65
- version_requirements: *id003
66
- - !ruby/object:Gem::Dependency
67
- name: em-syslog
68
46
  prerelease: false
69
- requirement: &id004 !ruby/object:Gem::Requirement
47
+ version_requirements: *70143497845280
48
+ - !ruby/object:Gem::Dependency
49
+ name: em-syslog
50
+ requirement: &70143497844500 !ruby/object:Gem::Requirement
70
51
  none: false
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- hash: 3
75
- segments:
76
- - 0
77
- version: "0"
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
78
56
  type: :runtime
79
- version_requirements: *id004
80
- - !ruby/object:Gem::Dependency
81
- name: em-hiredis
82
57
  prerelease: false
83
- requirement: &id005 !ruby/object:Gem::Requirement
58
+ version_requirements: *70143497844500
59
+ - !ruby/object:Gem::Dependency
60
+ name: em-hiredis
61
+ requirement: &70143497843400 !ruby/object:Gem::Requirement
84
62
  none: false
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
90
- - 0
91
- version: "0"
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
92
67
  type: :runtime
93
- version_requirements: *id005
94
- - !ruby/object:Gem::Dependency
95
- name: async_sinatra
96
68
  prerelease: false
97
- requirement: &id006 !ruby/object:Gem::Requirement
69
+ version_requirements: *70143497843400
70
+ - !ruby/object:Gem::Dependency
71
+ name: async_sinatra
72
+ requirement: &70143497842460 !ruby/object:Gem::Requirement
98
73
  none: false
99
- requirements:
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- hash: 3
103
- segments:
104
- - 0
105
- version: "0"
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
106
78
  type: :runtime
107
- version_requirements: *id006
108
- - !ruby/object:Gem::Dependency
109
- name: thin
110
79
  prerelease: false
111
- requirement: &id007 !ruby/object:Gem::Requirement
80
+ version_requirements: *70143497842460
81
+ - !ruby/object:Gem::Dependency
82
+ name: thin
83
+ requirement: &70143497841880 !ruby/object:Gem::Requirement
112
84
  none: false
113
- requirements:
114
- - - ">="
115
- - !ruby/object:Gem::Version
116
- hash: 3
117
- segments:
118
- - 0
119
- version: "0"
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
120
89
  type: :runtime
121
- version_requirements: *id007
122
- - !ruby/object:Gem::Dependency
123
- name: rake
124
90
  prerelease: false
125
- requirement: &id008 !ruby/object:Gem::Requirement
91
+ version_requirements: *70143497841880
92
+ - !ruby/object:Gem::Dependency
93
+ name: rake
94
+ requirement: &70143497841300 !ruby/object:Gem::Requirement
126
95
  none: false
127
- requirements:
128
- - - ">="
129
- - !ruby/object:Gem::Version
130
- hash: 3
131
- segments:
132
- - 0
133
- version: "0"
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
134
100
  type: :development
135
- version_requirements: *id008
136
- - !ruby/object:Gem::Dependency
137
- name: minitest
138
101
  prerelease: false
139
- requirement: &id009 !ruby/object:Gem::Requirement
102
+ version_requirements: *70143497841300
103
+ - !ruby/object:Gem::Dependency
104
+ name: minitest
105
+ requirement: &70143497840860 !ruby/object:Gem::Requirement
140
106
  none: false
141
- requirements:
142
- - - ">="
143
- - !ruby/object:Gem::Version
144
- hash: 3
145
- segments:
146
- - 0
147
- version: "0"
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
148
111
  type: :development
149
- version_requirements: *id009
150
- - !ruby/object:Gem::Dependency
151
- name: em-ventually
152
112
  prerelease: false
153
- requirement: &id010 !ruby/object:Gem::Requirement
113
+ version_requirements: *70143497840860
114
+ - !ruby/object:Gem::Dependency
115
+ name: em-ventually
116
+ requirement: &70143497840360 !ruby/object:Gem::Requirement
154
117
  none: false
155
- requirements:
156
- - - ">="
157
- - !ruby/object:Gem::Version
158
- hash: 3
159
- segments:
160
- - 0
161
- version: "0"
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
162
122
  type: :development
163
- version_requirements: *id010
164
- - !ruby/object:Gem::Dependency
165
- name: rest-client
166
123
  prerelease: false
167
- requirement: &id011 !ruby/object:Gem::Requirement
124
+ version_requirements: *70143497840360
125
+ - !ruby/object:Gem::Dependency
126
+ name: rest-client
127
+ requirement: &70143497839760 !ruby/object:Gem::Requirement
168
128
  none: false
169
- requirements:
170
- - - ">="
171
- - !ruby/object:Gem::Version
172
- hash: 3
173
- segments:
174
- - 0
175
- version: "0"
129
+ requirements:
130
+ - - ! '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
176
133
  type: :development
177
- version_requirements: *id011
134
+ prerelease: false
135
+ version_requirements: *70143497839760
178
136
  description: A server monitoring framework using the publish-subscribe model
179
- email:
137
+ email:
180
138
  - sean.porter@sonian.net
181
139
  - justin.kolberg@sonian.net
182
- executables:
140
+ executables:
183
141
  - sensu-api
184
142
  - sensu-client
185
143
  - sensu-server
186
144
  extensions: []
187
-
188
145
  extra_rdoc_files: []
189
-
190
- files:
146
+ files:
191
147
  - .gitignore
192
148
  - Gemfile
193
149
  - Gemfile.lock
@@ -203,41 +159,32 @@ files:
203
159
  - lib/sensu/config.rb
204
160
  - lib/sensu/helpers.rb
205
161
  - lib/sensu/server.rb
162
+ - sensu-logo.png
206
163
  - sensu.gemspec
207
164
  - sensu.windows
208
- has_rdoc: true
209
165
  homepage: https://github.com/sonian/sensu
210
- licenses:
166
+ licenses:
211
167
  - MIT
212
168
  post_install_message:
213
169
  rdoc_options: []
214
-
215
- require_paths:
170
+ require_paths:
216
171
  - lib
217
- required_ruby_version: !ruby/object:Gem::Requirement
172
+ required_ruby_version: !ruby/object:Gem::Requirement
218
173
  none: false
219
- requirements:
220
- - - ">="
221
- - !ruby/object:Gem::Version
222
- hash: 3
223
- segments:
224
- - 0
225
- version: "0"
226
- required_rubygems_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ! '>='
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
227
179
  none: false
228
- requirements:
229
- - - ">="
230
- - !ruby/object:Gem::Version
231
- hash: 3
232
- segments:
233
- - 0
234
- version: "0"
180
+ requirements:
181
+ - - ! '>='
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
235
184
  requirements: []
236
-
237
185
  rubyforge_project:
238
- rubygems_version: 1.3.7
186
+ rubygems_version: 1.8.10
239
187
  signing_key:
240
188
  specification_version: 3
241
189
  summary: A server monitoring framework
242
190
  test_files: []
243
-