sensu-plugins-couchbase 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -1
- data.tar.gz.sig +1 -2
- data/CHANGELOG.md +17 -8
- data/README.md +1 -1
- data/bin/check-couchbase-bucket-quota.rb +1 -1
- data/bin/metrics-couchbase.py +465 -0
- data/lib/sensu-plugins-couchbase/version.rb +2 -2
- metadata +29 -28
- metadata.gz.sig +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5aab37121a62f6578b8f1b3b4111a19d76afffb7
|
4
|
+
data.tar.gz: e3fc6a269e5ff21b9595e56799d64df095c02579
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f70878045a20540a290b1d48f50aa1026cda5e3f4f594514ca1c06345b99e6858afa9feea62526f707b919183e1abe098833158a94614f92c82a6c0e330ff15
|
7
|
+
data.tar.gz: c735ec7f613d60827a74a3564929a0bb98672ab08446913af9e9b7ce1a4d893e786d687e29e1f89e449264c8d1fd0e9b0f6e409132f6e4b590bc51f70c0ca67a
|
checksums.yaml.gz.sig
CHANGED
@@ -1 +1 @@
|
|
1
|
-
t�O
|
1
|
+
N�s<Z����y×�\���4���t��CA���1�S�`M�R ��ȉQ�b��ףf�Y薊�ĎsK��n��dI��hNm��p��L�g��\(����Y��m�[)T ,�9��պuБ�O&}0t��(�E�i�Q������������ڵ����$~����I����E�)�Z�����Oqn|�.4b5�Ѹ� Ɲ�j�3^Glg8�2�-P�_��f�vy���)5ŃR�ïZ�"���K:�sY��a�~
|
data.tar.gz.sig
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
h���?�c�Tqf� L�*Xs\�Tk��{��\���R]��<��]�3U�jݲ��м�,�����ӟZ캱�uZܧ{>��1L���a�R%CH�*hF�������K�E����ag��';��R�,NPcUr�.\��=j��1� >@����Ƌ��Z�ѷ�����|�?Z
|
1
|
+
2��W�L����|k���?�Q��!�/Flc��3�*ߋ.�o��=wj7o�x�������lj7��2��rP�Q@�7����t}U���hKP��߈��m��*.���0��6���%\]��ݒ-?N]A�d:��m��
|
data/CHANGELOG.md
CHANGED
@@ -3,21 +3,30 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
3
3
|
|
4
4
|
This CHANGELOG follows the format listed at [Keep A Changelog](http://keepachangelog.com/)
|
5
5
|
|
6
|
-
## Unreleased
|
6
|
+
## Unreleased
|
7
|
+
|
8
|
+
## 0.1.0 - 2015-08-11
|
9
|
+
### Added
|
10
|
+
- add metrics-couchbase.py plugin (requires python requests,DNS modules)
|
7
11
|
|
8
12
|
## [0.0.3] - 2015-07-14
|
9
13
|
### Changed
|
10
14
|
- updated sensu-plugin gem to 1.2.0
|
11
15
|
|
12
|
-
## 0.0.
|
13
|
-
|
14
|
-
### Added
|
15
|
-
- initial release
|
16
|
-
|
17
|
-
## 0.0.2 - 2015-06-02
|
16
|
+
## [0.0.2] - 2015-06-02
|
18
17
|
|
19
18
|
### Fixed
|
20
19
|
- added binstubs
|
21
20
|
|
22
21
|
### Changed
|
23
|
-
- removed cruft from /lib
|
22
|
+
- removed cruft from /lib
|
23
|
+
|
24
|
+
## 0.0.1 - 2015-05-04
|
25
|
+
|
26
|
+
### Added
|
27
|
+
- initial release
|
28
|
+
|
29
|
+
[unreleased]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/0.1.0...HEAD
|
30
|
+
[0.1.0]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/0.0.3...0.1.0
|
31
|
+
[0.0.3]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/0.0.2...0.0.3
|
32
|
+
[0.0.2]: https://github.com/sensu-plugins/sensu-plugins-ssl/compare/0.0.1...0.0.2
|
data/README.md
CHANGED
@@ -0,0 +1,465 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
#
|
3
|
+
# metrics-couchbase.py
|
4
|
+
#
|
5
|
+
# DESCRIPTION:
|
6
|
+
# Collects several couchbase stats using the couchbase stats REST API endpoints
|
7
|
+
#
|
8
|
+
# OUTPUT:
|
9
|
+
# graphite plain text protocol
|
10
|
+
#
|
11
|
+
# PLATFORMS:
|
12
|
+
# Linux
|
13
|
+
#
|
14
|
+
# DEPENDENCIES:
|
15
|
+
# python module: requests http://www.python-requests.org
|
16
|
+
# python module: pydns http://pydns.sourceforge.net
|
17
|
+
#
|
18
|
+
# USAGE:
|
19
|
+
# metrics-couchbase.py -u <user> -p <pw> -c <cb_host> [-s graphite_scheme] [-d] [-b] [-r]
|
20
|
+
# NOTES:
|
21
|
+
# This plugin gets *all* the CB cluster members dynamically and grab all the
|
22
|
+
# stats it can, in addition it grabs per bucket stats so be prepared for
|
23
|
+
# lots of stats...On a prod small CB cluster the output is ~5000 metrics.
|
24
|
+
# LICENSE:
|
25
|
+
# Jaime Gago contact@jaimegago.com
|
26
|
+
# Released under the same terms as Sensu (the MIT license); see LICENSE
|
27
|
+
# for details.
|
28
|
+
#
|
29
|
+
|
30
|
+
import DNS
|
31
|
+
import logging
|
32
|
+
import logging.handlers
|
33
|
+
import optparse
|
34
|
+
import requests
|
35
|
+
import sys
|
36
|
+
import time
|
37
|
+
from operator import add
|
38
|
+
|
39
|
+
FAILURE_CONSTANT = 1
|
40
|
+
|
41
|
+
PER_BUCKET_PER_NODE_STATS = [
|
42
|
+
'cas_hits',
|
43
|
+
'cmd_get',
|
44
|
+
'cmd_set',
|
45
|
+
'curr_connections',
|
46
|
+
'cpu_utilization_rate',
|
47
|
+
'curr_items',
|
48
|
+
'decr_hits',
|
49
|
+
'decr_misses',
|
50
|
+
'delete_misses',
|
51
|
+
'delete_hits',
|
52
|
+
'ep_bg_fetched',
|
53
|
+
'ep_flusher_todo',
|
54
|
+
'ep_max_size',
|
55
|
+
'ep_mem_high_wat',
|
56
|
+
'ep_mem_low_wat',
|
57
|
+
'ep_tmp_oom_errors',
|
58
|
+
'ep_queue_size',
|
59
|
+
'incr_hits',
|
60
|
+
'incr_misses',
|
61
|
+
'mem_used',
|
62
|
+
'ops',
|
63
|
+
'vb_active_eject',
|
64
|
+
'vb_active_itm_memory',
|
65
|
+
'vb_active_meta_data_memory',
|
66
|
+
'vb_active_num',
|
67
|
+
'vb_active_queue_drain',
|
68
|
+
'vb_active_queue_fill',
|
69
|
+
'vb_active_queue_size',
|
70
|
+
'vb_active_resident_items_ratio',
|
71
|
+
'vb_replica_num'
|
72
|
+
]
|
73
|
+
|
74
|
+
PER_BUCKET_STATS = [
|
75
|
+
'cas_hits',
|
76
|
+
'cmd_get',
|
77
|
+
'cmd_set',
|
78
|
+
'curr_items',
|
79
|
+
'decr_hits',
|
80
|
+
'decr_misses',
|
81
|
+
'incr_hits',
|
82
|
+
'incr_misses',
|
83
|
+
'ops',
|
84
|
+
'vb_active_resident_items_ratio',
|
85
|
+
]
|
86
|
+
|
87
|
+
WRITE_STATS = [
|
88
|
+
'cmd_set',
|
89
|
+
'incr_misses',
|
90
|
+
'incr_hits',
|
91
|
+
'decr_misses',
|
92
|
+
'decr_hits',
|
93
|
+
'cas_hits'
|
94
|
+
]
|
95
|
+
|
96
|
+
# Helper functions
|
97
|
+
def set_syslog():
|
98
|
+
'''Set a syslog logger'''
|
99
|
+
try:
|
100
|
+
logger = logging.getLogger(__name__)
|
101
|
+
logger.setLevel(logging.DEBUG)
|
102
|
+
|
103
|
+
formatter = logging.Formatter("%(pathname)s: %(message)s")
|
104
|
+
|
105
|
+
handler = logging.handlers.SysLogHandler(address = '/dev/log')
|
106
|
+
handler.setFormatter(formatter)
|
107
|
+
logger.addHandler(handler)
|
108
|
+
except Exception:
|
109
|
+
logging.critical("Failed to configure syslog handler")
|
110
|
+
sys.exit(1)
|
111
|
+
return logger
|
112
|
+
|
113
|
+
def min_med_max_avg(floats):
|
114
|
+
'''Return dict with min,median,max,avg(integers) from a list of floats'''
|
115
|
+
min_med_max_avg = {}
|
116
|
+
# Median calculations
|
117
|
+
values = sorted(floats)
|
118
|
+
midpoint = len(values) / 2
|
119
|
+
if len(values) % 2 == 0:
|
120
|
+
med = avg(values[midpoint:midpoint+2])
|
121
|
+
else:
|
122
|
+
med = values[midpoint]
|
123
|
+
min_med_max_avg['min'] = min(floats)
|
124
|
+
min_med_max_avg['med'] = med
|
125
|
+
min_med_max_avg['max'] = max(floats)
|
126
|
+
min_med_max_avg['avg'] = avg(floats)
|
127
|
+
return min_med_max_avg
|
128
|
+
|
129
|
+
def avg(floats):
|
130
|
+
length = len(floats)
|
131
|
+
total = sum(floats)
|
132
|
+
return total / length
|
133
|
+
|
134
|
+
def dns_reverse_lookup(dns_server, timeout_in_sec, ip, logger):
|
135
|
+
'''Tries to return a hostname doing a DNS rev lookup'''
|
136
|
+
dns_answered = False
|
137
|
+
try:
|
138
|
+
reversed_ip = '.'.join(ip.split('.')[::-1])
|
139
|
+
except Exception as e:
|
140
|
+
logger.critical('not a valid IP')
|
141
|
+
logger.critical(e)
|
142
|
+
sys.exit(FAILURE_CONSTANT)
|
143
|
+
try:
|
144
|
+
dns_obj = DNS.DnsRequest(server=dns_server, timeout=timeout_in_sec)
|
145
|
+
except Exception, error:
|
146
|
+
logger.critical('failed to talk to DNS NS')
|
147
|
+
logger.critical(e)
|
148
|
+
sys.exit(FAILURE_CONSTANT)
|
149
|
+
try:
|
150
|
+
dns_response = dns_obj.req(reversed_ip + '.in-addr.arpa', qtype='PTR')
|
151
|
+
if len(dns_response.answers):
|
152
|
+
dns_answered = True
|
153
|
+
except Exception as e:
|
154
|
+
logger.info('failed to rev lookup target IP')
|
155
|
+
logger.info(e)
|
156
|
+
pass
|
157
|
+
if dns_answered:
|
158
|
+
return dns_response.answers[0]['data'].split('.')[0]
|
159
|
+
else:
|
160
|
+
return ip
|
161
|
+
|
162
|
+
def strip_port(ip_and_port, logger):
|
163
|
+
'''strips :1234 from 10.10.10.10:1234'''
|
164
|
+
try:
|
165
|
+
ip, port = ip_and_port.split(':')
|
166
|
+
except Exception as e:
|
167
|
+
logger.critical('could not strip port from %s' % ip_and_port)
|
168
|
+
logger.critical(e)
|
169
|
+
return ip
|
170
|
+
|
171
|
+
def graphite_printer(all_stats, date, scheme, host_format=False):
|
172
|
+
'''Takes a dict with stats_compute func structure flattens it for Graphite
|
173
|
+
plain text protocol'''
|
174
|
+
|
175
|
+
for host in all_stats:
|
176
|
+
if host_format:
|
177
|
+
host_formated = host.replace('.', '_')
|
178
|
+
host_formated = host_formated.replace(':', '_')
|
179
|
+
else:
|
180
|
+
host_formated = host
|
181
|
+
for bucket in all_stats[host]:
|
182
|
+
for stat_name in all_stats[host][bucket]:
|
183
|
+
for stats in all_stats[host][bucket][stat_name]:
|
184
|
+
value = all_stats[host][bucket][stat_name][stats]
|
185
|
+
if host_formated == 'per_bucket':
|
186
|
+
print "%s.%s.%s.%s.%s %s %d" % (scheme, host_formated, bucket,
|
187
|
+
stat_name, stats, value, date)
|
188
|
+
else:
|
189
|
+
print "%s.per_bucket_per_node.%s.%s.%s.%s %s %d" % (scheme, host_formated, bucket,
|
190
|
+
stat_name, stats, value, date)
|
191
|
+
|
192
|
+
# Couchbase API dedicated functions
|
193
|
+
def get_buckets(couchbase_host, couchbase_rest_port, user, password, logger):
|
194
|
+
'''Get CouchBase buckets from REST API'''
|
195
|
+
try:
|
196
|
+
query = 'http://%s:%s/pools/default/buckets' % (couchbase_host,
|
197
|
+
couchbase_rest_port)
|
198
|
+
response = requests.get(query, auth=(user, password))
|
199
|
+
data = response.json()
|
200
|
+
except Exception as e:
|
201
|
+
logger.critical('Could not get buckets from Couchbase REST API')
|
202
|
+
logger.critical(e)
|
203
|
+
sys.exit(FAILURE_CONSTANT)
|
204
|
+
buckets = []
|
205
|
+
for bucket in data:
|
206
|
+
buckets.append(bucket['name'])
|
207
|
+
return buckets
|
208
|
+
|
209
|
+
def get_nodes_in_cluster(couchbase_host, couchbase_rest_port, user, password,
|
210
|
+
logger):
|
211
|
+
'''Get Couchbase cluster hostnames from REST API'''
|
212
|
+
try:
|
213
|
+
query = 'http://%s:%s/pools/default' % (couchbase_host, couchbase_rest_port)
|
214
|
+
response = requests.get(query, auth=(user, password))
|
215
|
+
data = response.json()
|
216
|
+
except Exception as e:
|
217
|
+
logger.critical('Could not get nodes from Couchbase REST API')
|
218
|
+
logger.critical(e)
|
219
|
+
sys.exit(FAILURE_CONSTANT)
|
220
|
+
cb_nodes = []
|
221
|
+
for node in data['nodes']:
|
222
|
+
if node['clusterMembership'] == 'active':
|
223
|
+
cb_nodes.append(node['hostname'])
|
224
|
+
return cb_nodes
|
225
|
+
|
226
|
+
def urls_generator(couchbase_host, couchbase_rest_port, buckets,
|
227
|
+
couchbase_nodes, logger, bucket_format=False):
|
228
|
+
# This hits the same host to get all the stats but it can be changed to
|
229
|
+
# hit each Couchbase node host for the per node stats
|
230
|
+
'''Generate URLs from buckets and nodes to hit Couchbase REST API
|
231
|
+
|
232
|
+
returns dict with following data structure:
|
233
|
+
|
234
|
+
{'per_bucket_cluster_urls':[ ('per_bucket',<bucket_foo>,<URL_foo>),
|
235
|
+
('per_bucket',<bucket_bar>,<URL_bar>),...],
|
236
|
+
|
237
|
+
'per_bucket_per_nodes_urls':[ (<node_foo>,<bucket_foo>,<URL_foo>),
|
238
|
+
(<node_foo>,<bucket_bar>,<URL_bar>),
|
239
|
+
(<node_baz>,<bucket_foo>,<URL_baz>),...]
|
240
|
+
}'''
|
241
|
+
|
242
|
+
cluster_nodes_buckets_urls = {}
|
243
|
+
cluster_stats_urls = []
|
244
|
+
per_node_urls = []
|
245
|
+
for bucket in buckets:
|
246
|
+
try:
|
247
|
+
cluster_url = "http://%s:%s/pools/default/buckets/%s/stats" % (
|
248
|
+
couchbase_host, couchbase_rest_port, bucket)
|
249
|
+
if bucket_format:
|
250
|
+
bucket_formated = bucket.replace('.', '_')
|
251
|
+
else:
|
252
|
+
bucket_formated = bucket
|
253
|
+
cluster_bucket_url = ('per_bucket', bucket_formated, cluster_url)
|
254
|
+
cluster_stats_urls.append(cluster_bucket_url)
|
255
|
+
except Exception as e:
|
256
|
+
logger.critical('Failed to generate list of URLs for per cluster queries')
|
257
|
+
logger.critical(e)
|
258
|
+
sys.exit(FAILURE_CONSTANT)
|
259
|
+
try:
|
260
|
+
for couchbase_node in couchbase_nodes:
|
261
|
+
node_url = "http://%s:%s/pools/default/buckets/%s/nodes/%s/stats" % (
|
262
|
+
couchbase_host, couchbase_rest_port, bucket, couchbase_node)
|
263
|
+
if bucket_format:
|
264
|
+
bucket_formated = bucket.replace('.', '_')
|
265
|
+
else:
|
266
|
+
bucket_formated = bucket
|
267
|
+
node_bucket_url = (couchbase_node, bucket_formated, node_url)
|
268
|
+
per_node_urls.append(node_bucket_url)
|
269
|
+
except Exception as e:
|
270
|
+
logger.critical('Failed to generate list of urls for per node queries')
|
271
|
+
logger.critical(e)
|
272
|
+
|
273
|
+
cluster_nodes_buckets_urls['per_bucket_cluster_urls'] = cluster_stats_urls
|
274
|
+
cluster_nodes_buckets_urls['per_bucket_per_nodes_urls'] = per_node_urls
|
275
|
+
return cluster_nodes_buckets_urls
|
276
|
+
|
277
|
+
def get_stats(url, user, password, cutoff, logger):
|
278
|
+
'''Get couchbase stats (JSON) via REST API'''
|
279
|
+
try:
|
280
|
+
params = { 'haveTStamp': cutoff, 'zoom':'minute'}
|
281
|
+
response = requests.get(url, auth=(user, password), params=params)
|
282
|
+
return response.json()
|
283
|
+
except Exception as e:
|
284
|
+
logger.critical('Could not retrieve json data from %s' % url)
|
285
|
+
logger.critical(e)
|
286
|
+
sys.exit(FAILURE_CONSTANT)
|
287
|
+
|
288
|
+
def stats_compute(hosts_buckets_urls, stats_names, write_stats, user,
|
289
|
+
password, cutoff, logger):
|
290
|
+
hosts_buckets_stats = {}
|
291
|
+
hosts_buckets_write_stats = {}
|
292
|
+
for host_bucket_url in hosts_buckets_urls:
|
293
|
+
host = host_bucket_url[0]
|
294
|
+
bucket = host_bucket_url[1]
|
295
|
+
url = host_bucket_url[2]
|
296
|
+
stats = get_stats(url, user, password, cutoff, logger)
|
297
|
+
stats_names_values = {}
|
298
|
+
bucket_stats_names_values = {}
|
299
|
+
# Needed because of len(stats) inconsistency in between queries
|
300
|
+
number_of_data_points = len(stats['op']['samples'][write_stats[0]])
|
301
|
+
|
302
|
+
# Calculate regular stats
|
303
|
+
if host not in hosts_buckets_stats:
|
304
|
+
hosts_buckets_stats[host] = {}
|
305
|
+
|
306
|
+
for stat_name in stats_names:
|
307
|
+
stats_names_values[stat_name] = min_med_max_avg(
|
308
|
+
stats['op']['samples'][stat_name])
|
309
|
+
bucket_stats_names_values[bucket] = stats_names_values
|
310
|
+
host_buckets_stats_names_values = hosts_buckets_stats[host].copy()
|
311
|
+
host_buckets_stats_names_values.update(bucket_stats_names_values)
|
312
|
+
|
313
|
+
hosts_buckets_stats[host] = host_buckets_stats_names_values
|
314
|
+
|
315
|
+
# Calculate write sums per bucket basis (per index)
|
316
|
+
if host not in hosts_buckets_write_stats:
|
317
|
+
hosts_buckets_write_stats[host] = {}
|
318
|
+
|
319
|
+
if bucket not in hosts_buckets_write_stats[host]:
|
320
|
+
hosts_buckets_write_stats[host][bucket] = {}
|
321
|
+
# During testing got both 59 and 60 length depending on the buckets
|
322
|
+
# (consistent per query) so we initialize the write sum list length
|
323
|
+
# to the right value on a per bucket basis
|
324
|
+
hosts_buckets_write_stats[host][bucket]['writes'] = [ 0 for x in range(0,
|
325
|
+
number_of_data_points) ]
|
326
|
+
|
327
|
+
for write_stat_name in write_stats:
|
328
|
+
hosts_buckets_write_stats[host][bucket]['writes'] = map(add, stats[
|
329
|
+
'op']['samples'][write_stat_name], hosts_buckets_write_stats[host][
|
330
|
+
bucket]['writes'])
|
331
|
+
|
332
|
+
hosts_buckets_write_stats[host][bucket]['writes'] = min_med_max_avg(
|
333
|
+
hosts_buckets_write_stats[host][bucket]['writes'])
|
334
|
+
|
335
|
+
# Merge the write stats to the regular stats
|
336
|
+
for host in hosts_buckets_write_stats:
|
337
|
+
for bucket in hosts_buckets_write_stats[host]:
|
338
|
+
hosts_buckets_stats[host][bucket]['writes'] = hosts_buckets_write_stats[
|
339
|
+
host][bucket]['writes']
|
340
|
+
return hosts_buckets_stats
|
341
|
+
|
342
|
+
def main():
|
343
|
+
parser = optparse.OptionParser()
|
344
|
+
|
345
|
+
parser.add_option('-c', '--couchbase-host',
|
346
|
+
help = 'Couchbase metrics source host',
|
347
|
+
dest = 'couchbase_host',
|
348
|
+
metavar = 'COUCHBASE_HOST',
|
349
|
+
type = str)
|
350
|
+
|
351
|
+
parser.add_option('-b', '--bucket_format',
|
352
|
+
help = 'replaces dots (.) in buckets names with underscores (_)',
|
353
|
+
action = 'store_true',
|
354
|
+
default = False,
|
355
|
+
dest = 'bucket_format')
|
356
|
+
|
357
|
+
parser.add_option('-d', '--dns-lookup',
|
358
|
+
help = 'Try a rev DNS lookup for couchbase nodes host',
|
359
|
+
action = 'store_true',
|
360
|
+
default = False,
|
361
|
+
dest = 'rev_dns')
|
362
|
+
|
363
|
+
parser.add_option('-i', '--interval',
|
364
|
+
help = 'Interval for stat collection in seconds, default to 60',
|
365
|
+
dest = 'interval',
|
366
|
+
default = 60,
|
367
|
+
metavar = 'INTERVAL',
|
368
|
+
type = int)
|
369
|
+
|
370
|
+
parser.add_option('-r', '--host_format',
|
371
|
+
help = 'replaces dots (.) in nodes hostnames with underscores (_)',
|
372
|
+
action = 'store_true',
|
373
|
+
default = False,
|
374
|
+
dest = 'host_format')
|
375
|
+
|
376
|
+
parser.add_option('-n', '--dns-name-server',
|
377
|
+
help = 'dns server for rev lookups',
|
378
|
+
dest = 'dns_ns',
|
379
|
+
default = '8.8.8.8',
|
380
|
+
metavar = 'DNS_NAMESERVER',
|
381
|
+
type = str)
|
382
|
+
|
383
|
+
parser.add_option('-s', '--scheme',
|
384
|
+
help = 'Metric Graphite naming scheme, text to prepend to metric',
|
385
|
+
default = 'couchbase',
|
386
|
+
dest = 'graphite_scheme',
|
387
|
+
metavar = 'SCHEME')
|
388
|
+
|
389
|
+
parser.add_option('-u', '--user',
|
390
|
+
help = 'couchbase user with access to rest',
|
391
|
+
dest = 'user',
|
392
|
+
metavar = 'USER')
|
393
|
+
|
394
|
+
parser.add_option('-p', '--password',
|
395
|
+
help = 'couchbase user password',
|
396
|
+
dest = 'password',
|
397
|
+
metavar = 'PASSWORD')
|
398
|
+
|
399
|
+
parser.add_option('-w', '--couchbase_rest_port',
|
400
|
+
help = 'couchbase REST port, defaults to 8091',
|
401
|
+
default = 8091,
|
402
|
+
dest = 'couchbase_rest_port',
|
403
|
+
metavar = 'COUCHBASE_REST_PORT')
|
404
|
+
|
405
|
+
(options, args) = parser.parse_args()
|
406
|
+
|
407
|
+
if not options.couchbase_host:
|
408
|
+
print 'A couchbase metrics source host is required'
|
409
|
+
sys.exit(FAILURE_CONSTANT)
|
410
|
+
|
411
|
+
if not options.user or not options.password:
|
412
|
+
print 'A couchbase user and password are required'
|
413
|
+
sys.exit(FAILURE_CONSTANT)
|
414
|
+
|
415
|
+
couchbase_host = options.couchbase_host
|
416
|
+
couchbase_rest_port = options.couchbase_rest_port
|
417
|
+
dns_ns = options.dns_ns
|
418
|
+
interval = options.interval
|
419
|
+
password = options.password
|
420
|
+
graphite_scheme = options.graphite_scheme
|
421
|
+
user = options.user
|
422
|
+
|
423
|
+
logger = set_syslog()
|
424
|
+
|
425
|
+
cutoff = int(time.time() - interval)
|
426
|
+
|
427
|
+
# Generate URLs to hit for all buckets and all nodes
|
428
|
+
buckets = get_buckets(couchbase_host, couchbase_rest_port, user, password,
|
429
|
+
logger)
|
430
|
+
cb_nodes = get_nodes_in_cluster(couchbase_host, couchbase_rest_port, user,
|
431
|
+
password, logger)
|
432
|
+
buckets_nodes_and_cluster_urls = urls_generator(couchbase_host,
|
433
|
+
couchbase_rest_port, buckets, cb_nodes, logger,
|
434
|
+
bucket_format=options.bucket_format)
|
435
|
+
# Get and compute the stats
|
436
|
+
|
437
|
+
## Cluster stats
|
438
|
+
cluster_buckets_urls = buckets_nodes_and_cluster_urls[
|
439
|
+
'per_bucket_cluster_urls']
|
440
|
+
cluster_stats = stats_compute(cluster_buckets_urls, PER_BUCKET_STATS,
|
441
|
+
WRITE_STATS, user, password, cutoff, logger)
|
442
|
+
|
443
|
+
## Per node stats
|
444
|
+
nodes_buckets_urls = buckets_nodes_and_cluster_urls[
|
445
|
+
'per_bucket_per_nodes_urls']
|
446
|
+
node_stats = stats_compute(nodes_buckets_urls, PER_BUCKET_PER_NODE_STATS,
|
447
|
+
WRITE_STATS, user, password, cutoff, logger)
|
448
|
+
### Replace nodes IPs with hostnames via DNS rev lookup
|
449
|
+
if options.rev_dns:
|
450
|
+
node_stats_hostnames = {}
|
451
|
+
for host in node_stats:
|
452
|
+
ip = strip_port(host,logger)
|
453
|
+
hostname = dns_reverse_lookup(dns_ns, 5, ip, logger)
|
454
|
+
node_stats_hostnames[hostname] = node_stats[host]
|
455
|
+
node_stats = node_stats_hostnames
|
456
|
+
|
457
|
+
all_stats = cluster_stats.copy()
|
458
|
+
all_stats.update(node_stats)
|
459
|
+
|
460
|
+
now = time.time()
|
461
|
+
graphite_printer(all_stats, now, options.graphite_scheme,
|
462
|
+
host_format=options.host_format)
|
463
|
+
|
464
|
+
if __name__ == '__main__':
|
465
|
+
main()
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sensu-plugins-couchbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sensu Plugins and contributors
|
@@ -30,7 +30,7 @@ cert_chain:
|
|
30
30
|
8sHuVruarogxxKPBzlL2is4EUb6oN/RdpGx2l4254+nyR+abg//Ed27Ym0PkB4lk
|
31
31
|
HP0m8WSjZmFr109pE/sVsM5jtOCvogyujQOjNVGN4gz1wwPr
|
32
32
|
-----END CERTIFICATE-----
|
33
|
-
date: 2015-
|
33
|
+
date: 2015-08-12 00:00:00.000000000 Z
|
34
34
|
dependencies:
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: rest_client
|
@@ -61,103 +61,103 @@ dependencies:
|
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: 1.2.0
|
63
63
|
- !ruby/object:Gem::Dependency
|
64
|
-
name:
|
64
|
+
name: bundler
|
65
65
|
requirement: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '1.7'
|
70
70
|
type: :development
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
74
|
- - "~>"
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '
|
76
|
+
version: '1.7'
|
77
77
|
- !ruby/object:Gem::Dependency
|
78
|
-
name:
|
78
|
+
name: codeclimate-test-reporter
|
79
79
|
requirement: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- -
|
81
|
+
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: '0.
|
83
|
+
version: '0.4'
|
84
84
|
type: :development
|
85
85
|
prerelease: false
|
86
86
|
version_requirements: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
|
-
- -
|
88
|
+
- - "~>"
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: '0.
|
90
|
+
version: '0.4'
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
|
-
name:
|
92
|
+
name: github-markup
|
93
93
|
requirement: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
95
|
- - "~>"
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: '3
|
97
|
+
version: '1.3'
|
98
98
|
type: :development
|
99
99
|
prerelease: false
|
100
100
|
version_requirements: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
102
|
- - "~>"
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version: '3
|
104
|
+
version: '1.3'
|
105
105
|
- !ruby/object:Gem::Dependency
|
106
|
-
name:
|
106
|
+
name: rake
|
107
107
|
requirement: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
109
|
- - "~>"
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
-
version: '
|
111
|
+
version: '10.0'
|
112
112
|
type: :development
|
113
113
|
prerelease: false
|
114
114
|
version_requirements: !ruby/object:Gem::Requirement
|
115
115
|
requirements:
|
116
116
|
- - "~>"
|
117
117
|
- !ruby/object:Gem::Version
|
118
|
-
version: '
|
118
|
+
version: '10.0'
|
119
119
|
- !ruby/object:Gem::Dependency
|
120
|
-
name:
|
120
|
+
name: redcarpet
|
121
121
|
requirement: !ruby/object:Gem::Requirement
|
122
122
|
requirements:
|
123
123
|
- - "~>"
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: '
|
125
|
+
version: '3.2'
|
126
126
|
type: :development
|
127
127
|
prerelease: false
|
128
128
|
version_requirements: !ruby/object:Gem::Requirement
|
129
129
|
requirements:
|
130
130
|
- - "~>"
|
131
131
|
- !ruby/object:Gem::Version
|
132
|
-
version: '
|
132
|
+
version: '3.2'
|
133
133
|
- !ruby/object:Gem::Dependency
|
134
|
-
name:
|
134
|
+
name: rubocop
|
135
135
|
requirement: !ruby/object:Gem::Requirement
|
136
136
|
requirements:
|
137
|
-
- -
|
137
|
+
- - '='
|
138
138
|
- !ruby/object:Gem::Version
|
139
|
-
version:
|
139
|
+
version: 0.32.1
|
140
140
|
type: :development
|
141
141
|
prerelease: false
|
142
142
|
version_requirements: !ruby/object:Gem::Requirement
|
143
143
|
requirements:
|
144
|
-
- -
|
144
|
+
- - '='
|
145
145
|
- !ruby/object:Gem::Version
|
146
|
-
version:
|
146
|
+
version: 0.32.1
|
147
147
|
- !ruby/object:Gem::Dependency
|
148
|
-
name:
|
148
|
+
name: rspec
|
149
149
|
requirement: !ruby/object:Gem::Requirement
|
150
150
|
requirements:
|
151
151
|
- - "~>"
|
152
152
|
- !ruby/object:Gem::Version
|
153
|
-
version: '3.
|
153
|
+
version: '3.1'
|
154
154
|
type: :development
|
155
155
|
prerelease: false
|
156
156
|
version_requirements: !ruby/object:Gem::Requirement
|
157
157
|
requirements:
|
158
158
|
- - "~>"
|
159
159
|
- !ruby/object:Gem::Version
|
160
|
-
version: '3.
|
160
|
+
version: '3.1'
|
161
161
|
- !ruby/object:Gem::Dependency
|
162
162
|
name: yard
|
163
163
|
requirement: !ruby/object:Gem::Requirement
|
@@ -197,6 +197,7 @@ files:
|
|
197
197
|
- LICENSE
|
198
198
|
- README.md
|
199
199
|
- bin/check-couchbase-bucket-quota.rb
|
200
|
+
- bin/metrics-couchbase.py
|
200
201
|
- lib/sensu-plugins-couchbase.rb
|
201
202
|
- lib/sensu-plugins-couchbase/version.rb
|
202
203
|
homepage: https://github.com/sensu-plugins/sensu-plugins-couchbase
|
@@ -225,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
225
226
|
version: '0'
|
226
227
|
requirements: []
|
227
228
|
rubyforge_project:
|
228
|
-
rubygems_version: 2.4.
|
229
|
+
rubygems_version: 2.4.8
|
229
230
|
signing_key:
|
230
231
|
specification_version: 4
|
231
232
|
summary: Sensu plugins for couchbase
|
metadata.gz.sig
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
|
1
|
+
� ��=n����7a)a��\������[��C���݅T�6��(�B2�f��P����|� ��;Ќqg�K}��F�S�d��Ʌ�� �p��H+�j�(M�V���ǗYz�7��.�f�1.��+�0ɇk��#�+����0�L�u5�p
|
2
|
+
�q襇+�m]�C$1�_�H��������;�jp���ET���ĨM������|\���ȍ��V$cP�Qk��G���9>GT�~D����DSOB
|