1 #-*- coding: ISO-8859-1 -*-
2 # collect.py: the python collectd-unixsock module.
4 # Requires collectd to be configured with the unixsock plugin, like so:
8 # SocketFile "/var/run/collectd-unixsock"
12 # Copyright (C) 2008 Clay Loveless <clay@killersoft.com>
14 # This software is provided 'as-is', without any express or implied
15 # warranty. In no event will the author be held liable for any damages
16 # arising from the use of this software.
18 # Permission is granted to anyone to use this software for any purpose,
19 # including commercial applications, and to alter it and redistribute it
20 # freely, subject to the following restrictions:
22 # 1. The origin of this software must not be misrepresented; you must not
23 # claim that you wrote the original software. If you use this software
24 # in a product, an acknowledgment in the product documentation would be
25 # appreciated but is not required.
26 # 2. Altered source versions must be plainly marked as such, and must not be
27 # misrepresented as being the original software.
28 # 3. This notice may not be removed or altered from any source distribution.
36 def __init__(self, path='/var/run/collectd-unixsock', noisy=False):
39 self._sock = self._connect()
41 def flush(self, timeout=None, plugins=[], identifiers=[]):
42 """Send a FLUSH command.
45 http://collectd.org/wiki/index.php/Plain_text_protocol#FLUSH
48 # have to pass at least one plugin or identifier
49 if not plugins and not identifiers:
53 args.append("timeout=%s" % timeout)
55 plugin_args = map(lambda x: "plugin=%s" % x, plugins)
56 args.extend(plugin_args)
58 identifier_args = map(lambda x: "identifier=%s" % x, identifiers)
59 args.extend(identifier_args)
60 return self._cmd('FLUSH %s' % ' '.join(args))
62 def getthreshold(self, identifier):
63 """Send a GETTHRESHOLD command.
66 http://collectd.org/wiki/index.php/Plain_text_protocol#GETTHRESHOLD
69 numvalues = self._cmd('GETTHRESHOLD "%s"' % identifier)
72 lines = self._readlines(numvalues)
75 def getval(self, identifier, flush_after=True):
76 """Send a GETVAL command.
78 Also flushes the identifier if flush_after is True.
81 http://collectd.org/wiki/index.php/Plain_text_protocol#GETVAL
84 numvalues = self._cmd('GETVAL "%s"' % identifier)
87 lines = self._readlines(numvalues)
89 self.flush(identifiers=[identifier])
93 """Send a LISTVAL command.
96 http://collectd.org/wiki/index.php/Plain_text_protocol#LISTVAL
99 numvalues = self._cmd('LISTVAL')
102 lines = self._readlines(numvalues)
105 def putnotif(self, message, options={}):
106 """Send a PUTNOTIF command.
108 Options must be passed as a Python dictionary. Example:
109 options={'severity': 'failure', 'host': 'example.com'}
112 http://collectd.org/wiki/index.php/Plain_text_protocol#PUTNOTIF
117 options_args = map(lambda x: "%s=%s" % (x, options[x]), options)
118 args.extend(options_args)
119 args.append('message="%s"' % message)
120 return self._cmd('PUTNOTIF %s' % ' '.join(args))
122 def putval(self, identifier, values, options={}):
123 """Send a PUTVAL command.
125 Options must be passed as a Python dictionary. Example:
126 options={'interval': 10}
129 http://collectd.org/wiki/index.php/Plain_text_protocol#PUTVAL
133 args.append('"%s"' % identifier)
135 options_args = map(lambda x: "%s=%s" % (x, options[x]), options)
136 args.extend(options_args)
137 values = map(str, values)
138 args.append(':'.join(values))
139 return self._cmd('PUTVAL %s' % ' '.join(args))
143 return self._cmdattempt(c)
144 except socket.error, (errno, errstr):
145 sys.stderr.write("[error] Sending to socket failed: [%d] %s\n"
147 self._sock = self._connect()
148 return self._cmdattempt(c)
150 def _cmdattempt(self, c):
152 print "[send] %s" % c
154 sys.stderr.write("[error] Socket unavailable. Can not send.")
156 self._sock.send(c + "\n")
157 status_message = self._readline()
159 print "[recive] %s" % status_message
160 if not status_message:
162 code, message = status_message.split(' ', 1)
169 sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
170 sock.connect(self.path)
172 print "[socket] connected to %s" % self.path
174 except socket.error, (errno, errstr):
175 sys.stderr.write("[error] Connecting to socket failed: [%d] %s"
180 """Read single line from socket"""
182 sys.stderr.write("[error] Socket unavailable. Can not read.")
187 recv = self._sock.recv
195 except socket.error, (errno, errstr):
196 sys.stderr.write("[error] Reading from socket failed: [%d] %s"
198 self._sock = self._connect()
201 def _readlines(self, sizehint=0):
202 """Read multiple lines from socket"""
206 line = self._readline()
211 if sizehint and total >= sizehint:
220 except socket.error, (errno, errstr):
221 sys.stderr.write("[error] Closing socket failed: [%d] %s"
225 if __name__ == '__main__':
226 """Collect values from socket and dump to STDOUT"""
228 c = Collectd('/var/run/collectd-unixsock', noisy=True)
231 stamp, identifier = val.split()
232 print "\n%s" % identifier
233 print "\tUpdate time: %s" % stamp
235 values = c.getval(identifier)
236 print "\tValue list: %s" % ', '.join(values)
238 # don't fetch thresholds by default because collectd will crash
239 # if there is no treshold for the given identifier
240 #thresholds = c.getthreshold(identifier)
241 #print "\tThresholds: %s" % ', '.join(thresholds)