sensu 0.6.8 → 0.6.9

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/.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
-