sensu-plugins-couchbase 0.0.2 → 0.1.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 +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
|