sensu-plugins-elasticsearch 0.5.3 → 1.0.0

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.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YjkwYTFiOWMzYjAzMzY0OTNiZjE5ZDZkNWY3NTliNzJiMGU2NWQ4ZQ==
5
- data.tar.gz: !binary |-
6
- OWI1ZTYzMjU5NTM1MzljZDA5NTlkOTViYThiNzBlZDY0ODQ2NTA1Yg==
2
+ SHA1:
3
+ metadata.gz: 916ac07d3bae1f72dfe1b147803712caf0051397
4
+ data.tar.gz: 49eb92c702d9b07a3f7d607f0cf412e32acf230d
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MGNhNjRjZWEzZjQ2OTBlYjI5OTJjY2Y5YmFmOTc5ZTE2YjFhODNjYjc2OWMy
10
- YmQ0OWMyZWRlMWJjYTMwODU2MzQxNjc3ZjFmYTI2ZTliODI1ODQxMmFmOGQz
11
- ZDNkNjFkNTU5OTFhYjdiNWEzYjQ2NzAyMDc2MTIwNzAxNmMwODQ=
12
- data.tar.gz: !binary |-
13
- MzYyODViMzE4OTExZGU1Y2RjMWJkY2UzNTVjMGZiY2Q1Y2QzNGJjZGY2NGQ0
14
- YTRkOWEzNTA0MThkYzE5ZDI1NjNhOWM1YjAyMGQwNzk5MjQ3ZDAzMzY0N2I1
15
- YTUzNDJhYTRmMTJlMDFiNzIzMjVmMGNkZTRjOGNlZjZkNDRiYmY=
6
+ metadata.gz: 6e1845230c4cf9911e5843f032d56bfee2cbdeccc370bf43ed5d0873665dca17b1e3c51b01416b5aac9ca008f77ae619da5804f095edbd925b76975c57c46f29
7
+ data.tar.gz: 80a2ea4fc5e0ebe877eb57f76d4510fee044fa95c1bd871c9813195109233462b890dc06957c887c197ad73fa455ee417a699b99d662f279787de8d087460f82
@@ -5,6 +5,27 @@ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachang
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [1.0.0] - 2016-07-29
9
+ ### Added
10
+ - Added AWS transport gem and configuration for check-es-query-* sensu calls to use --transport=AWS (@brendangibat)
11
+ - Added a rescue for 503 on several checks: (@majormoses)
12
+ - check-es-circuit-breakers.rb
13
+ - check-es-cluster-status.rb
14
+ - check-es-file-descriptors.rb
15
+ - check-es-heap.rb
16
+ - Added option --localhost for check-es-circuit-breakers.rb to only check its local node for broken circuit (@majormoses)
17
+ - Add Ruby 2.3.0 support (@eheydrick)
18
+ - Allow using newer patch versions of elasticsearch gem within the same minor (@majormoses)
19
+ - Add check-es-cluster-health to check Elasticsearch cluster health and status (@brendangibat)
20
+ - Add check-es-indices-size to check if indicies grow above a certain size (@brendangibat)
21
+ - Add handler-es-delete-indices handler to delete indicies (@brendangibat)
22
+
23
+ ### Removed
24
+ - Ruby 1.9.3 support (@eheydrick)
25
+
26
+ ### Changed
27
+ - Update to Rubocop 0.40 and cleanup (@eheydrick)
28
+
8
29
  ## [0.5.3] - 2016-04-02
9
30
  ### Added
10
31
  - check-es-indexes (check for dup indexes) (Yieldbot)
@@ -47,6 +68,7 @@ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachang
47
68
  - Update elasticsearch gem to 1.0.14
48
69
 
49
70
  ### Added
71
+ - Add check-es-cluster-health that checks health status with elasticsearch gem and can use AWS transport for checks.
50
72
  - Add check-es-circuit-breakers.rb, to alert when circuit breakers have been tripped
51
73
 
52
74
  ## [0.2.0] - 2015-10-15
@@ -85,8 +107,9 @@ This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachang
85
107
  ### Added
86
108
  - initial release
87
109
 
88
- [Unreleased]: https://github.com/sensu-plugins/sensu-plugins-elasticsearch/compare/0.5.3...HEAD
89
- [0.5.3]: https://github.com/sensu-plugins/sensu-plugins-elasticsearch/compare/0.4.2...0.4.3
110
+ [Unreleased]: https://github.com/sensu-plugins/sensu-plugins-elasticsearch/compare/1.0.0...HEAD
111
+ [1.0.0]: https://github.com/sensu-plugins/sensu-plugins-elasticsearch/compare/0.5.3...1.0.0
112
+ [0.5.3]: https://github.com/sensu-plugins/sensu-plugins-elasticsearch/compare/0.4.3...0.5.3
90
113
  [0.4.3]: https://github.com/sensu-plugins/sensu-plugins-elasticsearch/compare/0.4.2...0.4.3
91
114
  [0.4.2]: https://github.com/sensu-plugins/sensu-plugins-elasticsearch/compare/0.4.1...0.4.2
92
115
  [0.4.1]: https://github.com/sensu-plugins/sensu-plugins-elasticsearch/compare/0.4.0...0.4.1
data/README.md CHANGED
@@ -9,15 +9,18 @@
9
9
  ## Functionality
10
10
 
11
11
  ## Files
12
- * /bin/check-es-circuit-breakers.rb
12
+ * /bin/check-es-circuit-breakers.rb
13
+ * /bin/check-es-cluster-health.rb
13
14
  * /bin/check-es-cluster-status.rb
14
15
  * /bin/check-es-file-descriptors.rb
15
16
  * /bin/check-es-heap.rb
16
17
  * /bin/check-es-indexes.rb
18
+ * /bin/check-es-indicies-sizes.rb
17
19
  * /bin/check-es-node-status.rb
18
20
  * /bin/check-es-query-count.rb
19
21
  * /bin/check-es-query-exists.rb
20
- * /bin/check-es-shard-allocation
22
+ * /bin/check-es-shard-allocation-status.rb
23
+ * /bin/handler-es-delete-indices.rb
21
24
  * /bin/metrics-es-cluster.rb
22
25
  * /bin/metrics-es-node.rb
23
26
  * /bin/metrics-es-node-graphite.rb
@@ -69,6 +69,13 @@ class ESCircuitBreaker < Sensu::Plugin::Check::CLI
69
69
  short: '-e',
70
70
  long: '--https'
71
71
 
72
+ option :localhost,
73
+ description: 'only check local node',
74
+ short: '-l',
75
+ long: '--localhost',
76
+ boolean: true,
77
+ default: false
78
+
72
79
  def get_es_resource(resource)
73
80
  headers = {}
74
81
  if config[:user] && config[:password]
@@ -88,13 +95,19 @@ class ESCircuitBreaker < Sensu::Plugin::Check::CLI
88
95
  critical 'Connection refused'
89
96
  rescue RestClient::RequestTimeout
90
97
  critical 'Connection timed out'
98
+ rescue RestClient::ServiceUnavailable
99
+ warning 'Service is unavailable'
91
100
  rescue Errno::ECONNRESET
92
101
  critical 'Connection reset by peer'
93
102
  end
94
103
 
95
104
  def breaker_status
96
105
  breakers = {}
97
- status = get_es_resource('/_nodes/stats/breaker')
106
+ status = if config[:localhost]
107
+ get_es_resource('/_nodes/_local/stats/breaker')
108
+ else
109
+ get_es_resource('/_nodes/stats/breaker')
110
+ end
98
111
  status['nodes'].each_pair do |_node, stat|
99
112
  host = stat['host']
100
113
  breakers[host] = {}
@@ -0,0 +1,118 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # check-es-cluster-health
4
+ #
5
+ # DESCRIPTION:
6
+ # This plugin checks the ElasticSearch cluster health and status.
7
+ #
8
+ # OUTPUT:
9
+ # plain text
10
+ #
11
+ # PLATFORMS:
12
+ # Linux
13
+ #
14
+ # DEPENDENCIES:
15
+ # gem: sensu-plugin
16
+ # gem: elasticsearch
17
+ # gem: aws_es_transport
18
+ #
19
+ # USAGE:
20
+ # Checks against the ElasticSearch api for cluster health using the
21
+ # elasticsearch gem
22
+ #
23
+ # NOTES:
24
+ #
25
+ # LICENSE:
26
+ # Brendan Gibat <brendan.gibat@gmail.com>
27
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
28
+ # for details.
29
+ #
30
+
31
+ require 'sensu-plugin/check/cli'
32
+ require 'elasticsearch'
33
+ require 'aws_es_transport'
34
+ require 'sensu-plugins-elasticsearch'
35
+
36
+ #
37
+ # ES Cluster Health
38
+ #
39
+ class ESClusterHealth < Sensu::Plugin::Check::CLI
40
+ include ElasticsearchCommon
41
+
42
+ option :transport,
43
+ long: '--transport TRANSPORT',
44
+ description: 'Transport to use to communicate with ES. Use "AWS" for signed AWS transports.'
45
+
46
+ option :region,
47
+ long: '--region REGION',
48
+ description: 'Region (necessary for AWS Transport)'
49
+
50
+ option :host,
51
+ description: 'Elasticsearch host',
52
+ short: '-h HOST',
53
+ long: '--host HOST',
54
+ default: 'localhost'
55
+
56
+ option :level,
57
+ description: 'Level of detail to check returend information ("cluster", "indices", "shards").',
58
+ short: '-l LEVEL',
59
+ long: '--level LEVEL'
60
+
61
+ option :local,
62
+ description: 'Return local information, do not retrieve the state from master node.',
63
+ long: '--local',
64
+ boolean: true
65
+
66
+ option :port,
67
+ description: 'Elasticsearch port',
68
+ short: '-p PORT',
69
+ long: '--port PORT',
70
+ proc: proc(&:to_i),
71
+ default: 9200
72
+
73
+ option :scheme,
74
+ description: 'Elasticsearch connection scheme, defaults to https for authenticated connections',
75
+ short: '-s SCHEME',
76
+ long: '--scheme SCHEME'
77
+
78
+ option :password,
79
+ description: 'Elasticsearch connection password',
80
+ short: '-P PASSWORD',
81
+ long: '--password PASSWORD'
82
+
83
+ option :user,
84
+ description: 'Elasticsearch connection user',
85
+ short: '-u USER',
86
+ long: '--user USER'
87
+
88
+ option :timeout,
89
+ description: 'Elasticsearch query timeout in seconds',
90
+ short: '-t TIMEOUT',
91
+ long: '--timeout TIMEOUT',
92
+ proc: proc(&:to_i),
93
+ default: 30
94
+
95
+ def run
96
+ options = {}
97
+ unless config[:level].nil?
98
+ options[:level] = config[:level]
99
+ end
100
+ unless config[:local].nil?
101
+ options[:local] = config[:local]
102
+ end
103
+ unless config[:index].nil?
104
+ options[:index] = config[:index]
105
+ end
106
+ health = client.cluster.health options
107
+ case health['status']
108
+ when 'yellow'
109
+ warning 'Cluster state is Yellow'
110
+ when 'red'
111
+ critical 'Cluster state is Red'
112
+ when 'green'
113
+ ok
114
+ else
115
+ unknown "Cluster state is in an unknown health: #{health['status']}"
116
+ end
117
+ end
118
+ end
@@ -102,6 +102,8 @@ class ESClusterStatus < Sensu::Plugin::Check::CLI
102
102
  critical 'Connection refused'
103
103
  rescue RestClient::RequestTimeout
104
104
  critical 'Connection timed out'
105
+ rescue RestClient::ServiceUnavailable
106
+ critical 'Service is unavailable'
105
107
  rescue Errno::ECONNRESET
106
108
  critical 'Connection reset by peer'
107
109
  end
@@ -101,6 +101,8 @@ class ESFileDescriptors < Sensu::Plugin::Check::CLI
101
101
  warning 'Connection refused'
102
102
  rescue RestClient::RequestTimeout
103
103
  warning 'Connection timed out'
104
+ rescue RestClient::ServiceUnavailable
105
+ warning 'Service is unavailable'
104
106
  end
105
107
 
106
108
  def acquire_es_version
@@ -114,6 +114,8 @@ class ESHeap < Sensu::Plugin::Check::CLI
114
114
  warning 'Connection refused'
115
115
  rescue RestClient::RequestTimeout
116
116
  warning 'Connection timed out'
117
+ rescue RestClient::ServiceUnavailable
118
+ warning 'Service is unavailable'
117
119
  rescue JSON::ParserError
118
120
  warning 'Elasticsearch API returned invalid JSON'
119
121
  end
@@ -0,0 +1,185 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # check-es-indices-sizes.rb
4
+ #
5
+ # DESCRIPTION:
6
+ # This check sends a critical event when the indices mathing the date pattern
7
+ # are above a MB value.
8
+ #
9
+ # OUTPUT:
10
+ # plain text
11
+ #
12
+ # PLATFORMS:
13
+ # Linux
14
+ #
15
+ # DEPENDENCIES:
16
+ # gem: sensu-plugin
17
+ # gem: elasticsearch
18
+ # gem: aws_es_transport
19
+ #
20
+ # USAGE:
21
+ # ./check-es-indices-sizes.rb -h localhost -p 9200 -m 155000
22
+ #
23
+ # NOTES:
24
+ #
25
+ # LICENSE:
26
+ # Brendan Leon Gibat <brendan.gibat@gmail.com>
27
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
28
+ # for details.
29
+ #
30
+
31
+ require 'sensu-plugin/check/cli'
32
+ require 'elasticsearch'
33
+ require 'aws_es_transport'
34
+ require 'sensu-plugins-elasticsearch'
35
+
36
+ class ESCheckIndicesSizes < Sensu::Plugin::Check::CLI
37
+ include ElasticsearchCommon
38
+
39
+ option :transport,
40
+ long: '--transport TRANSPORT',
41
+ description: 'Transport to use to communicate with ES. Use "AWS" for signed AWS transports.'
42
+
43
+ option :region,
44
+ long: '--region REGION',
45
+ description: 'Region (necessary for AWS Transport)'
46
+
47
+ option :host,
48
+ description: 'Elasticsearch host',
49
+ short: '-h HOST',
50
+ long: '--host HOST',
51
+ default: 'localhost'
52
+
53
+ option :port,
54
+ description: 'Elasticsearch port',
55
+ short: '-p PORT',
56
+ long: '--port PORT',
57
+ proc: proc(&:to_i),
58
+ default: 9200
59
+
60
+ option :scheme,
61
+ description: 'Elasticsearch connection scheme, defaults to https for authenticated connections',
62
+ short: '-s SCHEME',
63
+ long: '--scheme SCHEME'
64
+
65
+ option :password,
66
+ description: 'Elasticsearch connection password',
67
+ short: '-P PASSWORD',
68
+ long: '--password PASSWORD'
69
+
70
+ option :user,
71
+ description: 'Elasticsearch connection user',
72
+ short: '-u USER',
73
+ long: '--user USER'
74
+
75
+ option :timeout,
76
+ description: 'Elasticsearch query timeout in seconds',
77
+ short: '-t TIMEOUT',
78
+ long: '--timeout TIMEOUT',
79
+ proc: proc(&:to_i),
80
+ default: 30
81
+
82
+ option :used_percent,
83
+ description: 'Percentage of bytes to use for indices matching pattern.',
84
+ short: '-a USED_PERCENTAGE',
85
+ long: '--used-percentage USED_PERCENTAGE',
86
+ proc: proc(&:to_i),
87
+ default: 80
88
+
89
+ option :maximum_megabytes,
90
+ description: 'Maximum number megabytes for date based indices to use.',
91
+ short: '-m MAXIMUM_MEGABYTES',
92
+ long: '--maximum-megabytes MAXIMUM_MEGABYTES',
93
+ proc: proc(&:to_i),
94
+ default: 0
95
+
96
+ option :pattern_regex,
97
+ description: 'Regular expression to use for matching date based indices. Four named groups are matched, pattern, year, month, day.',
98
+ short: '-x PATTERN_REGEX',
99
+ long: '--pattern-regex PATTERN_REGEX',
100
+ default: '^(?<pattern>.*)-(?<year>\d\d\d\d)\.(?<month>\d\d?).(?<day>\d\d?)$'
101
+
102
+ def get_indices_to_delete(starting_date, total_bytes_to_delete, indices_with_sizes)
103
+ total_bytes_deleted = 0
104
+ curr_date = DateTime.now
105
+
106
+ indices_to_delete = []
107
+
108
+ # We don't delete the current day, as it is most likely being used.
109
+ while total_bytes_deleted < total_bytes_to_delete && starting_date < curr_date
110
+ same_day_indices = indices_with_sizes.values.map do |pattern|
111
+ pattern.select do |index|
112
+ index['date'] == starting_date
113
+ end
114
+ end.flatten
115
+ same_day_indices.each do |index|
116
+ if total_bytes_deleted < total_bytes_to_delete
117
+ indices_to_delete.push(index['index'])
118
+ total_bytes_deleted += index['size']
119
+ end
120
+ end
121
+ starting_date += 1
122
+ end
123
+
124
+ indices_to_delete
125
+ end
126
+
127
+ def build_indices_with_sizes
128
+ indices_fs_stats = client.indices.stats store: true
129
+ pattern_regex = Regexp.new(config[:pattern_regex])
130
+
131
+ index_with_sizes = indices_fs_stats['indices'].keys.each_with_object({}) do |key, hash|
132
+ matching_index = pattern_regex.match(key)
133
+ unless matching_index.nil?
134
+ base_pattern = matching_index[:pattern]
135
+ unless base_pattern.nil?
136
+ unless hash.include?(base_pattern)
137
+ hash[base_pattern] = []
138
+ end
139
+ index_date = DateTime.new(matching_index[:year].to_i, matching_index[:month].to_i, matching_index[:day].to_i)
140
+ hash[base_pattern].push(
141
+ size: indices_fs_stats['indices'][key]['total']['store']['size_in_bytes'].to_i,
142
+ date: index_date,
143
+ index: key
144
+ )
145
+ end
146
+ end
147
+ end
148
+
149
+ index_with_sizes
150
+ end
151
+
152
+ def run
153
+ node_fs_stats = client.nodes.stats metric: 'fs,indices'
154
+ nodes_being_used = node_fs_stats['nodes'].values.select { |node| node['indices']['store']['size_in_bytes'] > 0 }
155
+ # rubocop:disable SingleLineBlockParams
156
+ # rubocop:disable LineLength
157
+ used_in_bytes = nodes_being_used.map { |node| node['fs']['data'].map { |data| data['total_in_bytes'] - data['available_in_bytes'] }.flatten }.flatten.inject { |sum, x| sum + x }
158
+ # rubocop:enable LineLength
159
+ total_in_bytes = nodes_being_used.map { |node| node['fs']['data'].map { |data| data['total_in_bytes'] }.flatten }.flatten.inject { |sum, x| sum + x }
160
+ # rubocop:enable SingleLineBlockParams
161
+
162
+ if config[:maximum_megabytes] > 0
163
+ target_bytes_used = config[:maximum_megabytes] * 1_000_000
164
+ else
165
+ if config[:used_percent] > 100 || config[:used_percent] < 0
166
+ critical 'You can not make used-percentages greater than 100 or less than 0.'
167
+ end
168
+ target_bytes_used = (total_in_bytes.to_f * (config[:used_percent].to_f / 100.0)).to_i
169
+ end
170
+
171
+ total_bytes_to_delete = used_in_bytes - target_bytes_used
172
+ if total_bytes_to_delete <= 0
173
+ ok "Used space in bytes: #{used_in_bytes}, Total in bytes: #{total_in_bytes}"
174
+ end
175
+
176
+ indices_with_sizes = build_indices_with_sizes
177
+
178
+ oldest = indices_with_sizes.values.flatten.map { |index| index['date'] }.min
179
+ indices_to_delete = get_indices_to_delete(oldest, total_bytes_to_delete, indices_with_sizes)
180
+
181
+ critical "Not enough space, #{total_bytes_to_delete} bytes need to be deleted. Used space in bytes: " \
182
+ "#{used_in_bytes}, Total in bytes: #{total_in_bytes}. Indices to delete: " \
183
+ "#{indices_to_delete.sort.map { |i| "INDEX[#{i}]" }.join(', ')}"
184
+ end
185
+ end
@@ -14,6 +14,7 @@
14
14
  # DEPENDENCIES:
15
15
  # gem: sensu-plugin
16
16
  # gem: elasticsearch
17
+ # gem: aws_es_transport
17
18
  #
18
19
  # USAGE:
19
20
  # This example checks that the count of special_type logs matching a query of
@@ -34,10 +35,12 @@
34
35
  require 'sensu-plugin/check/cli'
35
36
  require 'elasticsearch'
36
37
  require 'time'
38
+ require 'uri'
39
+ require 'aws_es_transport'
37
40
  require 'sensu-plugins-elasticsearch'
38
41
 
39
42
  #
40
- # ES Heap
43
+ # ES Query Count
41
44
  #
42
45
  class ESQueryCount < Sensu::Plugin::Check::CLI
43
46
  include ElasticsearchCommon
@@ -50,6 +53,14 @@ class ESQueryCount < Sensu::Plugin::Check::CLI
50
53
  short: '-i INDEX',
51
54
  long: '--indices INDEX'
52
55
 
56
+ option :transport,
57
+ long: '--transport TRANSPORT',
58
+ description: 'Transport to use to communicate with ES. Use "AWS" for signed AWS transports.'
59
+
60
+ option :region,
61
+ long: '--region REGION',
62
+ description: 'Region (necessary for AWS Transport)'
63
+
53
64
  option :types,
54
65
  description: 'Elasticsearch types to limit searches to, comma separated list.',
55
66
  long: '--types TYPES'
@@ -65,6 +76,12 @@ class ESQueryCount < Sensu::Plugin::Check::CLI
65
76
  proc: proc(&:to_i),
66
77
  default: 0
67
78
 
79
+ option :ignore_unavailable,
80
+ description: 'Ignore unavailable indices.',
81
+ long: '--ignore-unavailable',
82
+ boolean: true,
83
+ default: true
84
+
68
85
  option :minutes_previous,
69
86
  description: 'Minutes before offset to check @timestamp against query.',
70
87
  long: '--minutes-previous MINUTES_PREVIOUS',
@@ -142,8 +159,7 @@ class ESQueryCount < Sensu::Plugin::Check::CLI
142
159
  option :scheme,
143
160
  description: 'Elasticsearch connection scheme, defaults to https for authenticated connections',
144
161
  short: '-s SCHEME',
145
- long: '--scheme SCHEME',
146
- default: 'https'
162
+ long: '--scheme SCHEME'
147
163
 
148
164
  option :password,
149
165
  description: 'Elasticsearch connection password',
@@ -181,31 +197,68 @@ class ESQueryCount < Sensu::Plugin::Check::CLI
181
197
  description: 'Invert thresholds',
182
198
  boolean: true
183
199
 
200
+ option :kibana_url,
201
+ long: '--kibana-url KIBANA_URL',
202
+ description: 'Kibana URL query prefix that will be in critical / warning response output.'
203
+
204
+ def kibana_info
205
+ kibana_date_format = '%Y-%m-%dT%H:%M:%S.%LZ'
206
+ unless config[:kibana_url].nil?
207
+ index = config[:index]
208
+ unless config[:date_index].nil?
209
+ date_index_partition = config[:date_index].split('%')
210
+ index = "[#{date_index_partition.first}]" \
211
+ "#{date_index_partition[1..-1].join.sub('Y', 'YYYY').sub('y', 'YY').sub('m', 'MM').sub('d', 'DD').sub('j', 'DDDD').sub('H', 'hh')}"
212
+ end
213
+ end_time = Time.now.utc.to_i
214
+ start_time = end_time
215
+ if config[:minutes_previous] != 0
216
+ start_time -= (config[:minutes_previous] * 60)
217
+ end
218
+ if config[:hours_previous] != 0
219
+ start_time -= (config[:hours_previous] * 60 * 60)
220
+ end
221
+ if config[:days_previous] != 0
222
+ start_time -= (config[:days_previous] * 60 * 60 * 24)
223
+ end
224
+ if config[:weeks_previous] != 0
225
+ start_time -= (config[:weeks_previous] * 60 * 60 * 24 * 7)
226
+ end
227
+ if config[:months_previous] != 0
228
+ start_time -= (config[:months_previous] * 60 * 60 * 24 * 7 * 31)
229
+ end
230
+ "Kibana logs: #{config[:kibana_url]}/#/discover?_g=" \
231
+ "(refreshInterval:(display:Off,section:0,value:0),time:(from:'" \
232
+ "#{URI.escape(Time.at(start_time).utc.strftime kibana_date_format)}',mode:absolute,to:'" \
233
+ "#{URI.escape(Time.at(end_time).utc.strftime kibana_date_format)}'))&_a=(columns:!(_source),index:" \
234
+ "#{URI.escape(index)},interval:auto,query:(query_string:(analyze_wildcard:!t,query:'" \
235
+ "#{URI.escape(config[:query])}')),sort:!('@timestamp',desc))&dummy"
236
+ end
237
+ end
238
+
184
239
  def run
185
240
  response = client.count(build_request_options)
186
241
  if config[:invert]
187
242
  if response['count'] < config[:crit]
188
- critical "Query count (#{response['count']}) was below critical threshold"
243
+ critical "Query count (#{response['count']}) was below critical threshold. #{kibana_info}"
189
244
  elsif response['count'] < config[:warn]
190
- warning "Query count (#{response['count']}) was below warning threshold"
245
+ warning "Query count (#{response['count']}) was below warning threshold. #{kibana_info}"
191
246
  else
192
247
  ok "Query count (#{response['count']}) was ok"
193
248
  end
249
+ elsif response['count'] > config[:crit]
250
+ critical "Query count (#{response['count']}) was above critical threshold. #{kibana_info}"
251
+ elsif response['count'] > config[:warn]
252
+ warning "Query count (#{response['count']}) was above warning threshold. #{kibana_info}"
194
253
  else
195
- if response['count'] > config[:crit] # rubocop:disable Style/IfInsideElse
196
- critical "Query count (#{response['count']}) was above critical threshold"
197
- elsif response['count'] > config[:warn]
198
- warning "Query count (#{response['count']}) was above warning threshold"
199
- else
200
- ok "Query count (#{response['count']}) was ok"
201
- end
254
+ ok "Query count (#{response['count']}) was ok"
202
255
  end
203
256
  rescue Elasticsearch::Transport::Transport::Errors::NotFound
204
257
  if config[:invert]
205
258
  if response['count'] < config[:crit]
206
- critical "Query count (#{response['count']}) was below critical threshold"
259
+ critical "Query count (#{response['count']}) was below critical threshold. #{kibana_info}"
207
260
  elsif response['count'] < config[:warn]
208
- warning "Query count (#{response['count']}) was below warning threshold"
261
+ warning "Query count (#{response['count']}) was below warning threshold. #{kibana_info}"
209
262
  else
210
263
  ok "Query count (#{response['count']}) was ok"
211
264
  end
@@ -35,10 +35,12 @@
35
35
 
36
36
  require 'sensu-plugin/check/cli'
37
37
  require 'elasticsearch'
38
+ require 'time'
39
+ require 'aws_es_transport'
38
40
  require 'sensu-plugins-elasticsearch'
39
41
 
40
42
  #
41
- # ES Heap
43
+ # ES Query Exists
42
44
  #
43
45
  class ESQueryExists < Sensu::Plugin::Check::CLI
44
46
  include ElasticsearchCommon
@@ -51,6 +53,14 @@ class ESQueryExists < Sensu::Plugin::Check::CLI
51
53
  short: '-i INDEX',
52
54
  long: '--indices INDEX'
53
55
 
56
+ option :transport,
57
+ long: '--transport TRANSPORT',
58
+ description: 'Transport to use to communicate with ES. Use "AWS" for signed AWS transports.'
59
+
60
+ option :region,
61
+ long: '--region REGION',
62
+ description: 'Region (necessary for AWS Transport)'
63
+
54
64
  option :types,
55
65
  description: 'Elasticsearch types to limit searches to, comma separated list.',
56
66
  long: '--types TYPES'
@@ -114,10 +124,9 @@ class ESQueryExists < Sensu::Plugin::Check::CLI
114
124
  boolean: true,
115
125
  default: false
116
126
 
117
- option :query,
118
- description: 'Elasticsearch query',
119
- short: '-q QUERY',
120
- long: '--query QUERY',
127
+ option :id,
128
+ description: 'ID of the ElasticSearch document to check for existence',
129
+ long: '--id ID',
121
130
  required: true
122
131
 
123
132
  option :host,
@@ -136,8 +145,7 @@ class ESQueryExists < Sensu::Plugin::Check::CLI
136
145
  option :scheme,
137
146
  description: 'Elasticsearch connection scheme, defaults to https for authenticated connections',
138
147
  short: '-s SCHEME',
139
- long: '--scheme SCHEME',
140
- default: 'https'
148
+ long: '--scheme SCHEME'
141
149
 
142
150
  option :password,
143
151
  description: 'Elasticsearch connection password',
@@ -157,28 +165,35 @@ class ESQueryExists < Sensu::Plugin::Check::CLI
157
165
  default: 30
158
166
 
159
167
  option :warn,
160
- short: '-w N',
161
- long: '--warn N',
162
- description: 'Result count WARNING threshold',
163
- proc: proc(&:to_i),
164
- default: 0
165
-
166
- option :crit,
167
- short: '-c N',
168
- long: '--crit N',
169
- description: 'Result count CRITICAL threshold',
170
- proc: proc(&:to_i),
171
- default: 0
168
+ short: '-w',
169
+ long: '--warn',
170
+ description: 'Warn instead of critical',
171
+ boolean: true,
172
+ default: false
172
173
 
173
174
  option :invert,
174
175
  long: '--invert',
175
- description: 'Invert thresholds',
176
- boolean: true
176
+ description: 'Invert status',
177
+ boolean: true,
178
+ default: false
177
179
 
178
- def run # rubocop:disable all
179
- client.exists(build_request_options)
180
+ def run
181
+ if client.exists?(build_request_options)
182
+ if config[:invert]
183
+ if config[:warn]
184
+ warning
185
+ else
186
+ critical
187
+ end
188
+ else
189
+ ok
190
+ end
191
+ elsif config[:invert]
180
192
  ok
181
- rescue Elasticsearch::Transport::Transport::Errors::NotFound
193
+ elsif config[:warn]
194
+ warning
195
+ else
182
196
  critical
183
197
  end
198
+ end
184
199
  end
@@ -0,0 +1,99 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # handler-es-delete-indices.rb
4
+ #
5
+ # DESCRIPTION:
6
+ # This handler deletes indices.
7
+ #
8
+ # OUTPUT:
9
+ # plain text
10
+ #
11
+ # PLATFORMS:
12
+ # Linux
13
+ #
14
+ # DEPENDENCIES:
15
+ # gem: sensu-plugin
16
+ # gem: elasticsearch
17
+ # gem: aws_es_transport
18
+ #
19
+ # USAGE:
20
+ # Deletes the indices given to it from a check output and a configured
21
+ # regex, and then deletes the indices matched.
22
+ #
23
+ # NOTES:
24
+ #
25
+ # LICENSE:
26
+ # Brendan Leon Gibat <brendan.gibat@gmail.com>
27
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
28
+ # for details.
29
+ #
30
+
31
+ require 'sensu-handler'
32
+ require 'elasticsearch'
33
+ require 'aws_es_transport'
34
+ require 'sensu-plugins-elasticsearch'
35
+
36
+ class ESIndexCleanup < Sensu::Handler
37
+ include ElasticsearchCommon
38
+
39
+ option :transport,
40
+ long: '--transport TRANSPORT',
41
+ description: 'Transport to use to communicate with ES. Use "AWS" for signed AWS transports.'
42
+
43
+ option :region,
44
+ long: '--region REGION',
45
+ description: 'Region (necessary for AWS Transport)'
46
+
47
+ option :host,
48
+ description: 'Elasticsearch host',
49
+ short: '-h HOST',
50
+ long: '--host HOST',
51
+ default: 'localhost'
52
+
53
+ option :port,
54
+ description: 'Elasticsearch port',
55
+ short: '-p PORT',
56
+ long: '--port PORT',
57
+ proc: proc(&:to_i),
58
+ default: 9200
59
+
60
+ option :scheme,
61
+ description: 'Elasticsearch connection scheme, defaults to https for authenticated connections',
62
+ short: '-s SCHEME',
63
+ long: '--scheme SCHEME'
64
+
65
+ option :password,
66
+ description: 'Elasticsearch connection password',
67
+ short: '-P PASSWORD',
68
+ long: '--password PASSWORD'
69
+
70
+ option :user,
71
+ description: 'Elasticsearch connection user',
72
+ short: '-u USER',
73
+ long: '--user USER'
74
+
75
+ option :timeout,
76
+ description: 'Elasticsearch query timeout in seconds',
77
+ short: '-t TIMEOUT',
78
+ long: '--timeout TIMEOUT',
79
+ proc: proc(&:to_i),
80
+ default: 60
81
+
82
+ option :event_regex,
83
+ description: 'Elasticsearch connection user',
84
+ short: '-e EVENT_REGEX',
85
+ long: '--event-regex EVENT_REGEX',
86
+ default: 'INDEX\[([^\]]+)\]'
87
+
88
+ def handle
89
+ event_regex = Regexp.new(config[:event_regex])
90
+ indices_to_delete = @event['check']['output'].scan(event_regex).flatten
91
+ if !indices_to_delete.nil? && !indices_to_delete.empty?
92
+
93
+ puts("Deleting indices: [ #{indices_to_delete.sort.join(', ')} ]")
94
+ client.indices.delete index: indices_to_delete
95
+ else
96
+ puts('No indices matched pattern to delete.')
97
+ end
98
+ end
99
+ end
@@ -15,6 +15,7 @@
15
15
  # Released under the same terms as Sensu (the MIT license); see LICENSE
16
16
  # for details.
17
17
  #
18
+
18
19
  require_relative 'elasticsearch-query.rb'
19
20
 
20
21
  module ElasticsearchCommon
@@ -24,19 +25,24 @@ module ElasticsearchCommon
24
25
  end
25
26
 
26
27
  def client
27
- @client ||= begin
28
- if !config[:user].nil? && !config[:pass].nil? && !config[:scheme].nil?
29
- Elasticsearch::Client.new hosts: [{
30
- host: config[:host],
31
- port: config[:port],
32
- user: config[:user],
33
- password: config[:password],
34
- scheme: config[:scheme],
35
- request_timeout: config[:timeout]
36
- }]
37
- else
38
- Elasticsearch::Client.new host: "#{config[:host]}:#{config[:port]}", request_timeout: config[:timeout]
39
- end
28
+ transport_class = nil
29
+ if config[:transport] == 'AWS'
30
+ transport_class = Elasticsearch::Transport::Transport::HTTP::AWS
40
31
  end
32
+
33
+ host = {
34
+ host: config[:host],
35
+ port: config[:port],
36
+ request_timeout: config[:timeout],
37
+ scheme: config[:scheme]
38
+ }
39
+
40
+ if !config[:user].nil? && !config[:password].nil?
41
+ host[:user] = config[:user]
42
+ host[:password] = config[:password]
43
+ host[:scheme] = 'https' unless config[:scheme]
44
+ end
45
+
46
+ @client ||= Elasticsearch::Client.new(transport_class: transport_class, hosts: [host], region: config[:region])
41
47
  end
42
48
  end
@@ -63,10 +63,19 @@ module ElasticsearchQuery
63
63
  def build_request_options
64
64
  end_time = (Time.now.utc - config[:offset])
65
65
  options = {
66
+
66
67
  index: indices(end_time),
67
68
  ignore_unavailable: true
68
69
  }
69
70
 
71
+ unless config[:ignore_unavailable].nil?
72
+ options[:ignore_unavailable] = config[:ignore_unavailable]
73
+ end
74
+
75
+ unless config[:id].nil?
76
+ options[:id] = config[:id]
77
+ end
78
+
70
79
  if !config[:body].nil?
71
80
  options[:body] = config[:body]
72
81
  else
@@ -1,8 +1,8 @@
1
1
  module SensuPluginsElasticsearch
2
2
  module Version
3
- MAJOR = 0
4
- MINOR = 5
5
- PATCH = 3
3
+ MAJOR = 1
4
+ MINOR = 0
5
+ PATCH = 0
6
6
 
7
7
  VER_STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sensu-plugins-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sensu Plugins and contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-02 00:00:00.000000000 Z
11
+ date: 2016-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -28,170 +28,202 @@ dependencies:
28
28
  name: elasticsearch
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '='
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: 1.0.14
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '='
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 1.0.14
41
+ - !ruby/object:Gem::Dependency
42
+ name: aws-es-transport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.1'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: sensu-plugin
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - ~>
59
+ - - "~>"
46
60
  - !ruby/object:Gem::Version
47
61
  version: '1.2'
48
62
  type: :runtime
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - ~>
66
+ - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '1.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: json
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.8'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.8'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: bundler
57
85
  requirement: !ruby/object:Gem::Requirement
58
86
  requirements:
59
- - - ~>
87
+ - - "~>"
60
88
  - !ruby/object:Gem::Version
61
89
  version: '1.7'
62
90
  type: :development
63
91
  prerelease: false
64
92
  version_requirements: !ruby/object:Gem::Requirement
65
93
  requirements:
66
- - - ~>
94
+ - - "~>"
67
95
  - !ruby/object:Gem::Version
68
96
  version: '1.7'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: codeclimate-test-reporter
71
99
  requirement: !ruby/object:Gem::Requirement
72
100
  requirements:
73
- - - ~>
101
+ - - "~>"
74
102
  - !ruby/object:Gem::Version
75
103
  version: '0.4'
76
104
  type: :development
77
105
  prerelease: false
78
106
  version_requirements: !ruby/object:Gem::Requirement
79
107
  requirements:
80
- - - ~>
108
+ - - "~>"
81
109
  - !ruby/object:Gem::Version
82
110
  version: '0.4'
83
111
  - !ruby/object:Gem::Dependency
84
112
  name: github-markup
85
113
  requirement: !ruby/object:Gem::Requirement
86
114
  requirements:
87
- - - ~>
115
+ - - "~>"
88
116
  - !ruby/object:Gem::Version
89
117
  version: '1.3'
90
118
  type: :development
91
119
  prerelease: false
92
120
  version_requirements: !ruby/object:Gem::Requirement
93
121
  requirements:
94
- - - ~>
122
+ - - "~>"
95
123
  - !ruby/object:Gem::Version
96
124
  version: '1.3'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: pry
99
127
  requirement: !ruby/object:Gem::Requirement
100
128
  requirements:
101
- - - ~>
129
+ - - "~>"
102
130
  - !ruby/object:Gem::Version
103
131
  version: '0.10'
104
132
  type: :development
105
133
  prerelease: false
106
134
  version_requirements: !ruby/object:Gem::Requirement
107
135
  requirements:
108
- - - ~>
136
+ - - "~>"
109
137
  - !ruby/object:Gem::Version
110
138
  version: '0.10'
111
139
  - !ruby/object:Gem::Dependency
112
140
  name: rake
113
141
  requirement: !ruby/object:Gem::Requirement
114
142
  requirements:
115
- - - ~>
143
+ - - "~>"
116
144
  - !ruby/object:Gem::Version
117
145
  version: '10.0'
118
146
  type: :development
119
147
  prerelease: false
120
148
  version_requirements: !ruby/object:Gem::Requirement
121
149
  requirements:
122
- - - ~>
150
+ - - "~>"
123
151
  - !ruby/object:Gem::Version
124
152
  version: '10.0'
125
153
  - !ruby/object:Gem::Dependency
126
154
  name: redcarpet
127
155
  requirement: !ruby/object:Gem::Requirement
128
156
  requirements:
129
- - - ~>
157
+ - - "~>"
130
158
  - !ruby/object:Gem::Version
131
159
  version: '3.2'
132
160
  type: :development
133
161
  prerelease: false
134
162
  version_requirements: !ruby/object:Gem::Requirement
135
163
  requirements:
136
- - - ~>
164
+ - - "~>"
137
165
  - !ruby/object:Gem::Version
138
166
  version: '3.2'
139
167
  - !ruby/object:Gem::Dependency
140
168
  name: rubocop
141
169
  requirement: !ruby/object:Gem::Requirement
142
170
  requirements:
143
- - - ~>
171
+ - - "~>"
144
172
  - !ruby/object:Gem::Version
145
- version: '0.37'
173
+ version: 0.40.0
146
174
  type: :development
147
175
  prerelease: false
148
176
  version_requirements: !ruby/object:Gem::Requirement
149
177
  requirements:
150
- - - ~>
178
+ - - "~>"
151
179
  - !ruby/object:Gem::Version
152
- version: '0.37'
180
+ version: 0.40.0
153
181
  - !ruby/object:Gem::Dependency
154
182
  name: rspec
155
183
  requirement: !ruby/object:Gem::Requirement
156
184
  requirements:
157
- - - ~>
185
+ - - "~>"
158
186
  - !ruby/object:Gem::Version
159
187
  version: '3.1'
160
188
  type: :development
161
189
  prerelease: false
162
190
  version_requirements: !ruby/object:Gem::Requirement
163
191
  requirements:
164
- - - ~>
192
+ - - "~>"
165
193
  - !ruby/object:Gem::Version
166
194
  version: '3.1'
167
195
  - !ruby/object:Gem::Dependency
168
196
  name: yard
169
197
  requirement: !ruby/object:Gem::Requirement
170
198
  requirements:
171
- - - ~>
199
+ - - "~>"
172
200
  - !ruby/object:Gem::Version
173
201
  version: '0.8'
174
202
  type: :development
175
203
  prerelease: false
176
204
  version_requirements: !ruby/object:Gem::Requirement
177
205
  requirements:
178
- - - ~>
206
+ - - "~>"
179
207
  - !ruby/object:Gem::Version
180
208
  version: '0.8'
181
- description: ! "This plugin provides native ElasticSearch instrumentation\n for
182
- monitoring and metrics collection, including:\n service
183
- health and metrics for cluster, node, and more."
184
- email: <sensu-users@googlegroups.com>
209
+ description: |-
210
+ This plugin provides native ElasticSearch instrumentation
211
+ for monitoring and metrics collection, including:
212
+ service health and metrics for cluster, node, and more.
213
+ email: "<sensu-users@googlegroups.com>"
185
214
  executables:
186
215
  - check-es-circuit-breakers.rb
216
+ - check-es-cluster-health.rb
187
217
  - check-es-cluster-status.rb
188
218
  - check-es-file-descriptors.rb
189
219
  - check-es-heap.rb
190
220
  - check-es-indexes.rb
221
+ - check-es-indices-sizes.rb
191
222
  - check-es-node-status.rb
192
223
  - check-es-query-count.rb
193
224
  - check-es-query-exists.rb
194
225
  - check-es-shard-allocation-status.rb
226
+ - handler-es-delete-indices.rb
195
227
  - metrics-es-cluster.rb
196
228
  - metrics-es-node-graphite.rb
197
229
  - metrics-es-node.rb
@@ -202,14 +234,17 @@ files:
202
234
  - LICENSE
203
235
  - README.md
204
236
  - bin/check-es-circuit-breakers.rb
237
+ - bin/check-es-cluster-health.rb
205
238
  - bin/check-es-cluster-status.rb
206
239
  - bin/check-es-file-descriptors.rb
207
240
  - bin/check-es-heap.rb
208
241
  - bin/check-es-indexes.rb
242
+ - bin/check-es-indices-sizes.rb
209
243
  - bin/check-es-node-status.rb
210
244
  - bin/check-es-query-count.rb
211
245
  - bin/check-es-query-exists.rb
212
246
  - bin/check-es-shard-allocation-status.rb
247
+ - bin/handler-es-delete-indices.rb
213
248
  - bin/metrics-es-cluster.rb
214
249
  - bin/metrics-es-node-graphite.rb
215
250
  - bin/metrics-es-node.rb
@@ -233,17 +268,17 @@ require_paths:
233
268
  - lib
234
269
  required_ruby_version: !ruby/object:Gem::Requirement
235
270
  requirements:
236
- - - ! '>='
271
+ - - ">="
237
272
  - !ruby/object:Gem::Version
238
- version: 1.9.3
273
+ version: 2.0.0
239
274
  required_rubygems_version: !ruby/object:Gem::Requirement
240
275
  requirements:
241
- - - ! '>='
276
+ - - ">="
242
277
  - !ruby/object:Gem::Version
243
278
  version: '0'
244
279
  requirements: []
245
280
  rubyforge_project:
246
- rubygems_version: 2.4.5
281
+ rubygems_version: 2.5.1
247
282
  signing_key:
248
283
  specification_version: 4
249
284
  summary: Sensu plugins for elasticsearch