Files
scylladb/tools/scyllatop/collectd.py
Yoav Kleinberger 43071bf488 tools/scyllatop: handle absentee metrics
Sometimes a metric previously reported from collectd is not available
anymore. Previously, this caused scyllatop to log and exception to the
user - which in effect destroyes the user experience and inhibits
monitoring other metrics. This patch makes ScyllaTop handle this
problem. It will display such metrics and 'not available', and exclude
them from some and average computations.

Closes issue #1287.

Signed-off-by: Yoav Kleinberger <yoav@scylladb.com>
Message-Id: <1465301178-27544-1-git-send-email-yoav@scylladb.com>
2016-06-08 16:35:55 +03:00

57 lines
2.0 KiB
Python

import socket
import re
import atexit
import os
import parseexception
import logging
COLLECTD_EXAMPLE_CONFIGURATION = '\n'.join(['LoadPlugin unixsock',
'',
'<Plugin unixsock>',
' SocketFile "{socket}"',
' SocketGroup "wheel"',
' SocketPerms "0660"',
' DeleteSocket false',
'</Plugin>'])
class Collectd(object):
_FIRST_LINE_PATTERN = re.compile('^(?P<lines>\d+)')
def __init__(self, socketName):
try:
self._connect(socketName)
atexit.register(self._cleanup)
except Exception as e:
logging.error('could not connect to {0}. {1}'.format(socketName, e))
quit()
def _connect(self, socketName):
logging.info('connecting to unix socket: {0}'.format(socketName))
self._socket = socket.socket(socket.SOCK_STREAM, socket.AF_UNIX)
self._socket.connect(socketName)
self._lineReader = os.fdopen(self._socket.fileno())
def query(self, command):
self._send(command)
return self._readLines()
def _send(self, command):
withNewline = '{command}\n'.format(command=command)
octets = withNewline.encode('ascii')
self._socket.send(octets)
def _readLines(self):
line = self._lineReader.readline()
if line.strip() == '-1 No such value':
return None
match = self._FIRST_LINE_PATTERN.search(line)
if match is None:
raise parseexception.ParseException('could not parse first line of response from collectd: {0}'.format(line))
howManyLines = int(match.groupdict()['lines'])
return [self._lineReader.readline() for _ in range(howManyLines)]
def _cleanup(self):
self._lineReader.close()
self._socket.close()