Skip to content

Commit 8832066

Browse files
author
Michael Spiegel
committed
Report metrics from /api/overview endpoint.
Emit metrics from rabbitmq /api/overview endpoint to ganglia. Additional miscellaneous changes: - deleted unused global variable 'url' - deleted unused function validatedResults(). It called 'isInstance' which is undefined. Probably intention was to invoke 'isinstance'. - added 'username' and 'password' command line options.
1 parent 9f740e8 commit 8832066

1 file changed

Lines changed: 82 additions & 21 deletions

File tree

rabbit/python_modules/rabbitmq.py

Lines changed: 82 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
from string import Template
1616

17-
global url, descriptors, last_update, vhost, username, password, url_template, result, result_dict, keyToPath
17+
global descriptors, last_update, vhost, username, password, url_template, result, result_dict, keyToPath
1818

1919
log = None
2020

@@ -28,7 +28,7 @@
2828
keyToPath = {}
2929
last_update = None
3030
#last_update = {}
31-
compiled_results = {"nodes": None, "queues": None, "connections": None, "exchanges": None}
31+
compiled_results = {"nodes": None, "queues": None, "connections": None, "exchanges": None, "overview": None}
3232
#Make initial stat test time dict
3333
#for stat_type in ('queues', 'connections','exchanges', 'nodes'):
3434
# last_update[stat_type] = None
@@ -91,6 +91,26 @@
9191

9292
EXCHANGE_METRICS = ['rmq_exchange_publish_in_rate', 'rmq_exchange_publish_out_rate']
9393

94+
keyToPath['rmq_overview_message_stats_publish'] = "message_stats{0}publish".format(JSON_PATH_SEPARATOR)
95+
keyToPath['rmq_overview_message_stats_ack'] = "message_stats{0}ack".format(JSON_PATH_SEPARATOR)
96+
keyToPath['rmq_overview_message_stats_deliver_get'] = "message_stats{0}deliver_get".format(JSON_PATH_SEPARATOR)
97+
keyToPath['rmq_overview_message_stats_deliver'] = "message_stats{0}deliver".format(JSON_PATH_SEPARATOR)
98+
keyToPath['rmq_overview_message_stats_deliver_no_ack'] = "message_stats{0}deliver_no_ack".format(JSON_PATH_SEPARATOR)
99+
keyToPath['rmq_overview_queue_totals_messages'] = "queue_totals{0}messages".format(JSON_PATH_SEPARATOR)
100+
keyToPath['rmq_overview_queue_totals_messages_ready'] = "queue_totals{0}messages_ready".format(JSON_PATH_SEPARATOR)
101+
keyToPath['rmq_overview_queue_totals_messages_unacknowledged'] = "queue_totals{0}messages_unacknowledged".format(JSON_PATH_SEPARATOR)
102+
keyToPath['rmq_overview_object_totals_consumers'] = "object_totals{0}consumers".format(JSON_PATH_SEPARATOR)
103+
keyToPath['rmq_overview_object_totals_queues'] = "object_totals{0}queues".format(JSON_PATH_SEPARATOR)
104+
keyToPath['rmq_overview_object_totals_exchanges'] = "object_totals{0}exchanges".format(JSON_PATH_SEPARATOR)
105+
keyToPath['rmq_overview_object_totals_connections'] = "object_totals{0}connections".format(JSON_PATH_SEPARATOR)
106+
keyToPath['rmq_overview_object_totals_channels'] = "object_totals{0}channels".format(JSON_PATH_SEPARATOR)
107+
108+
OVERVIEW_METRICS = ['rmq_overview_message_stats_publish', 'rmq_overview_message_stats_ack', 'rmq_overview_message_stats_deliver_get',
109+
'rmq_overview_message_stats_deliver', 'rmq_overview_message_stats_deliver_no_ack',
110+
'rmq_overview_queue_totals_messages', 'rmq_overview_queue_totals_messages_ready',
111+
'rmq_overview_queue_totals_messages_unacknowledged', 'rmq_overview_object_totals_consumers',
112+
'rmq_overview_object_totals_queues', 'rmq_overview_object_totals_exchanges',
113+
'rmq_overview_object_totals_connections', 'rmq_overview_object_totals_channels']
94114

95115
def dig_it_up(obj, path):
96116
try:
@@ -103,9 +123,8 @@ def dig_it_up(obj, path):
103123
return False
104124

105125

106-
def refreshStats(stats=('nodes', 'queues'), vhosts=['/']):
107-
global url_template
108-
global last_update, url, compiled_results
126+
def refreshStats(stats=('nodes', 'queues', 'overview'), vhosts=['/']):
127+
global url_template, last_update
109128

110129
now = time.time()
111130

@@ -119,10 +138,13 @@ def refreshStats(stats=('nodes', 'queues'), vhosts=['/']):
119138
last_update = now
120139
for stat in stats:
121140
for vhost in vhosts:
122-
if stat in ('nodes'):
141+
if stat in ('nodes', 'overview'):
123142
vhost = '/'
124143
result_dict = {}
125-
urlstring = url_template.safe_substitute(stats=stat, vhost=vhost)
144+
if stat == 'overview':
145+
urlstring = overview_url
146+
else:
147+
urlstring = url_template.safe_substitute(stats=stat, vhost=vhost)
126148
log.debug('urlspring: %s' % urlstring)
127149
result = json.load(urllib2.urlopen(urlstring))
128150
# Rearrange results so entry is held in a dict keyed by name - queue name, host name, etc.
@@ -131,23 +153,16 @@ def refreshStats(stats=('nodes', 'queues'), vhosts=['/']):
131153
name = entry['name']
132154
result_dict[name] = entry
133155
compiled_results[(stat, vhost)] = result_dict
156+
elif stat in ("overview"):
157+
compiled_results[(stat, vhost)] = result
134158

135159
return compiled_results
136160

137-
138-
def validatedResult(value):
139-
if not isInstance(value, bool):
140-
return float(value)
141-
else:
142-
return None
143-
144-
145161
def list_queues(vhost):
146162
global compiled_results
147163
queues = compiled_results[('queues', vhost)].keys()
148164
return queues
149165

150-
151166
def list_nodes():
152167
global compiled_results
153168
nodes = compiled_results[('nodes', '/')].keys()
@@ -159,7 +174,6 @@ def list_exchanges(vhost):
159174
exchanges = compiled_results[('exchanges', vhost)].keys()
160175
return exchanges
161176

162-
163177
def getQueueStat(name):
164178
refreshStats(stats=STATS, vhosts=vhosts)
165179
# Split a name like "rmq_backing_queue_ack_egress_rate.access"
@@ -206,6 +220,29 @@ def getNodeStat(name):
206220
return float(value)
207221

208222

223+
def getOverviewStat(name):
224+
refreshStats(stats=STATS, vhosts=vhosts)
225+
# Split a name like "rmq_backing_queue_ack_egress_rate.access"
226+
227+
# handle queue names with . in them
228+
229+
log.debug(name)
230+
stat_name, vhost = name.split(METRIC_TOKEN_SEPARATOR)
231+
232+
vhost = vhost.replace('-', '/') # decoding vhost from metric name
233+
# Run refreshStats to get the result object
234+
result = compiled_results[('overview', vhost)]
235+
236+
value = dig_it_up(result, keyToPath[stat_name])
237+
238+
# Convert Booleans
239+
if value is True:
240+
value = 1
241+
elif value is False:
242+
value = 0
243+
244+
return float(value)
245+
209246
def getExchangeStat(name):
210247
refreshStats(stats=STATS, vhosts=vhosts)
211248
# Split a name like "rmq_backing_queue_ack_egress_rate.access"
@@ -254,7 +291,7 @@ def str2bool(string):
254291

255292
def metric_init(params):
256293
''' Create the metric definition object '''
257-
global descriptors, stats, vhost, username, password, urlstring, url_template, compiled_results, STATS, vhosts, zero_rates_when_idle
294+
global descriptors, stats, vhost, username, password, urlstring, url_template, overview_url, compiled_results, STATS, vhosts, zero_rates_when_idle
258295
if log is None:
259296
setup_logging('syslog', params['syslog_facility'], params['log_level'])
260297
log.info('received the following params: %r' % params)
@@ -274,6 +311,7 @@ def metric_init(params):
274311
zero_rates_when_idle = str2bool(params['zero_rates_when_idle'])
275312

276313
url = 'http://%s:%s/api/$stats/$vhost' % (host, port)
314+
overview_url = 'http://%s:%s/api/overview' % (host, port)
277315
base_url = 'http://%s:%s/api' % (host, port)
278316
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
279317
password_mgr.add_password(None, base_url, username, password)
@@ -357,12 +395,29 @@ def buildExchangeDescriptors():
357395
log.debug(d1)
358396
descriptors.append(d1)
359397

398+
def buildOverviewDescriptors():
399+
for vhost, metric in product(vhosts, OVERVIEW_METRICS):
400+
name = "{1}{0}{2}".format(METRIC_TOKEN_SEPARATOR, metric, vhost.replace('/', '-'))
401+
log.debug(name)
402+
d1 = create_desc({'name': name.encode('ascii', 'ignore'),
403+
'call_back': getOverviewStat,
404+
'value_type': 'float',
405+
'units': 'N',
406+
'slope': 'both',
407+
'format': '%f',
408+
'description': 'Overview_Metric',
409+
'groups': 'rabbitmq,overview'})
410+
log.debug(d1)
411+
descriptors.append(d1)
412+
360413
if 'queues' in STATS:
361414
buildQueueDescriptors()
362415
if 'nodes' in STATS:
363416
buildNodeDescriptors()
364417
if 'exchanges' in STATS:
365418
buildExchangeDescriptors()
419+
if 'overview' in STATS:
420+
buildOverviewDescriptors()
366421
# buildTestNodeStat()
367422

368423
return descriptors
@@ -397,15 +452,21 @@ def setup_logging(handlers, facility, level):
397452

398453
def parse_args(argv):
399454
parser = optparse.OptionParser()
455+
parser.add_option('--username',
456+
action='store', dest='username', default='username',
457+
help='')
458+
parser.add_option('--password',
459+
action='store', dest='password', default='password',
460+
help='')
400461
parser.add_option('--admin-host',
401462
action='store', dest='admin_host', default='localhost',
402463
help='')
403464
parser.add_option('--admin-port',
404465
action='store', dest='admin_port', default=15672,
405466
help='')
406467
parser.add_option('--stats',
407-
action='store', dest='stats', default='nodes,queues,exchanges',
408-
help='csv of which stats to emit, choies: nodes, queues')
468+
action='store', dest='stats', default='nodes,queues,exchanges,overview',
469+
help='csv of which stats to emit, choies: nodes, queues, exchanges, overview')
409470
parser.add_option('--vhosts',
410471
action='store', dest='vhosts', default='/',
411472
help='csv of vhosts')
@@ -431,7 +492,7 @@ def main(argv):
431492
(opts, args) = parse_args(argv)
432493
setup_logging(opts.log, opts.log_facility, opts.log_level)
433494
# in config files we use '/' in vhosts names but we should convert '/' to '-' when calculating a metric
434-
parameters = {"vhost": "/", "username": "guest", "password": "guest", "metric_group": "rabbitmq",
495+
parameters = {"vhost": "/", "username": opts.username, "password": opts.password, "metric_group": "rabbitmq",
435496
"zero_rates_when_idle": "yes",
436497
"host": opts.admin_host, "port": opts.admin_port,
437498
"stats": opts.stats.split(','),

0 commit comments

Comments
 (0)