forked from jacobian/munin-plugins
-
Notifications
You must be signed in to change notification settings - Fork 0
/
perlbal_
executable file
·166 lines (136 loc) · 5.4 KB
/
perlbal_
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/usr/bin/env python
"""
Munin script to monitor perlbal.
Following the munin style, this reads argv[0] to decide what to monitor.
Currently supported modes are:
- Number of requests in a given pool
- Number of requests per backend
- Number or requests per HTTP code
"""
import telnetlib
import socket
import munin
from BaseHTTPServer import BaseHTTPRequestHandler
# You may want to modify these to a group of relevant codes.
#HTTP_STATUS_CODES = set(BaseHTTPRequestHandler.responses.keys())
HTTP_STATUS_CODES = set([200, 304, 404, 503])
class Perlbal(munin.Plugin):
env_vars = {
"host": "192.168.0.110",
"port": "9999"
}
def _connect(self):
return telnetlib.Telnet(self.env["host"], int(self.env["port"]))
@property
def backends(self):
"""Returns the Perlbal backend information."""
c = self._connect()
c.write('nodes\r\n')
data = c.read_until('.\r\n')
backends = {}
for line in data.splitlines()[:-1]:
entries = line.split()
if len(entries) == 4:
backends.setdefault(entries[0], {}).setdefault(entries[1], {})[entries[2]] = int(entries[3])
elif len(entries) == 3:
backends.setdefault(entries[0], {})[entries[1]] = int(entries[2])
c.close()
return backends
def config_pool_requests(self, pool=None):
if not pool: return []
return [
('graph_title', 'Perlbal requests in pool %s' % pool),
('graph_args', '-l 0 --base 1000'),
('graph_vlabel', 'Requests'),
('graph_category', 'Perlbal'),
('graph_info', 'Tracks the number of requests the %s pool handles' % pool),
('graph_period', 'second'),
('requests.label', 'Requests per second'),
('requests.type', 'DERIVE'),
('requests.min', '0'),
]
def fetch_pool_requests(self, pool=None):
if not pool: return []
c = self._connect()
c.write("show pool %s\r\n"% pool)
data = c.read_until(".\r\n")
nodelines = data.strip().split("\r\n")[:-1]
nodes = (line.strip().split() for line in nodelines)
return [("requests.value", sum(int(reqs) for node, reqs in nodes))]
def config_requests_per_backend(self):
config = [
('graph_title', 'Perlbal requests per backend'),
('graph_args', '-l 0 --base 1000'),
('graph_vlabel', 'Requests'),
('graph_category', 'Perlbal'),
('graph_info', 'Tracks the number of requests per backend'),
]
for be in self.backends:
beid = self.fieldname(be)
config.extend([('%s.label' % beid, be),
('%s.type' % beid, 'DERIVE'),
('%s.min' % beid, '0'),
('%s.draw' % beid, 'STACK')])
return config
def fetch_requests_per_backend(self):
for backend, data in self.backends.iteritems():
yield ('%s.value' % self.fieldname(backend), data.get('connects', 0))
def config_status_codes(self):
config = [
('graph_title', 'Perlbal status codes'),
('graph_args', '-l 0 --base 1000'),
('graph_vlabel', 'HTTP status codes'),
('graph_category', 'Perlbal'),
('graph_info', 'Tracks the number of requests grouped by HTTP status codes'),
]
for code in sorted(HTTP_STATUS_CODES):
cid = 'code_%s' % code
config.extend([('%s.label' % cid, code),
('%s.type' % cid, 'DERIVE'),
('%s.min' % cid, '0'),
('%s.draw' % cid, 'STACK')])
return config
def fetch_status_codes(self):
codes = {}
for data in self.backends.itervalues():
for code, value in data.get('responsecodes', {}).iteritems():
codes[code] = codes.get(code, 0) + value
for code in HTTP_STATUS_CODES:
yield ('code_%s.value' % code, codes.get(str(code), 0))
def fetch(self, args):
if not args:
return []
if args[0] == 'responsecode':
return self.fetch_status_codes()
elif args[0] == 'backendrequest':
return self.fetch_requests_per_backend()
elif args[0] == 'poolrequest':
return self.fetch_pool_requests('_'.join(args[1:]))
def config(self, args):
if not args:
return []
if args[0] == 'responsecode':
return self.config_status_codes()
elif args[0] == 'backendrequest':
return self.config_requests_per_backend()
elif args[0] == 'poolrequest':
return self.config_pool_requests('_'.join(args[1:]))
def autoconf(self):
try:
self._connect()
except socket.error:
return False
return True
def suggest(self):
suggestions = set('responsecode', 'backendrequest')
c = self._connect()
c.write('show pool\r\n')
data = c.read_until('.\r\n').strip()
pools = set(line.strip().split()[0]
for line
in data.splitlines()
if line != '.')
suggestions.update(['poolrequest_%s' % p for p in pools])
return suggestions
if __name__ == '__main__':
munin.run(Perlbal)