forked from phrawzty/rabbitmq-collectd-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrabbitmq_info.py
141 lines (115 loc) · 4.4 KB
/
rabbitmq_info.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# rabbitmq-collectd-plugin - rabbitmq_info.py
#
# Author: Daniel Maher (http://www.dark.ca/)
# Description: This plugin uses collectd's Python plugin to obtain Rabbitmq metrics.
#
# Loosely based on Garret Heaton's "redis-collectd-plugin"
# https://github.com/powdahound/redis-collectd-plugin
import collectd
import subprocess
import re
NAME = 'rabbitmq_info'
# Override in config by specifying 'RmqcBin'.
RABBITMQCTL_BIN = '/usr/sbin/rabbitmqctl'
# Override in config by specifying 'PmapBin'
PMAP_BIN = '/usr/bin/pmap'
# Override in config by specifying 'PidofBin'.
PIDOF_BIN = '/bin/pidof'
# Override in config by specifying 'Verbose'.
VERBOSE_LOGGING = False
# Obtain the interesting statistical info
def get_stats():
stats = {}
stats['ctl_messages'] = 0
stats['ctl_memory'] = 0
stats['ctl_consumers'] = 0
stats['pmap_mapped'] = 0
stats['pmap_used'] = 0
stats['pmap_shared'] = 0
# call rabbitmqctl
try:
p = subprocess.Popen([RABBITMQCTL_BIN, '-q', 'list_queues', 'messages', 'memory', 'consumers'], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except:
logger('err', 'Failed to run %s' % RABBITMQCTL_BIN)
return None
for line in p.stdout.readlines():
if re.match('\d', line):
ctl_stats = line.split()
stats['ctl_messages'] += int(ctl_stats[0])
stats['ctl_memory'] += int(ctl_stats[1])
stats['ctl_consumers'] += int(ctl_stats[2])
if not stats['ctl_memory'] > 0:
logger('warn', '%s reports 0 memory usage. This is probably incorrect.' % RABBITMQCTL_BIN)
# get the pid of rabbitmq (beam.smp)
try:
p = subprocess.Popen([PIDOF_BIN, 'beam.smp'], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except:
logger('err', 'Failed to run %s' % PIDOF_BIN)
return None
line = p.stdout.read().strip()
if not re.search('\D', line):
pid = line
else:
logger('err', '%s returned something strange.' % PIDOF_BIN)
return None
# use pmap to get proper memory stats
try:
p = subprocess.Popen([PMAP_BIN, '-d', pid], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except:
logger('err', 'Failed to run %s' % PMAP_BIN)
return None
line = p.stdout.readlines()[-1].strip()
if re.match('mapped', line):
m = re.match(r"\D+(\d+)\D+(\d+)\D+(\d+)", line)
stats['pmap_mapped'] = int(m.group(1))
stats['pmap_used'] = int(m.group(2))
stats['pmap_shared'] = int(m.group(3))
else:
logger('warn', '%s returned something strange.' % PMAP_BIN)
return None
# Verbose output
logger('verb', '[rmqctl] Messages: %i, Memory: %i, Consumers: %i' % (stats['ctl_messages'], stats['ctl_memory'], stats['ctl_consumers']))
logger('verb', '[pmap] Mapped: %i, Used: %i, Shared: %i' % (stats['pmap_mapped'], stats['pmap_used'], stats['pmap_shared']))
return stats
# Config data from collectd
def configure_callback(conf):
global RABBITMQCTL_BIN, PMAP_BIN, PIDOF_BIN, VERBOSE_LOGGING
for node in conf.children:
if node.key == 'RmqcBin':
RABBITMQCTL_BIN = node.values[0]
elif node.key == 'PmapBin':
PMAP_BIN = node.values[0]
elif node.key == 'PidofBin':
PIDOF_BIN = node.values[0]
elif node.key == 'Verbose':
VERBOSE_LOGGING = bool(node.values[0])
else:
logger('warn', 'Unknown config key: %s' % node.key)
# Send info to collectd
def read_callback():
logger('verb', 'read_callback')
info = get_stats()
if not info:
logger('err', 'No information received - very bad.')
return
logger('verb', 'About to trigger the dispatch..')
# send values
for key in info:
logger('verb', 'Dispatching %s : %i' % (key, info[key]))
val = collectd.Values(plugin=NAME)
val.type = 'gauge'
val.type_instance = key
val.values = [int(info[key])]
val.dispatch()
# Send log messages (via collectd)
def logger(t, msg):
if t == 'err':
collectd.error('%s: %s' % (NAME, msg))
if t == 'warn':
collectd.warning('%s: %s' % (NAME, msg))
elif t == 'verb' and VERBOSE_LOGGING == True:
collectd.info('%s: %s' % (NAME, msg))
# Runtime
collectd.register_config(configure_callback)
collectd.warning('Initialising rabbitmq_info')
collectd.register_read(read_callback)