Source code for duct.sources.database.memcache

"""
.. module:: memcache
   :platform: Unix
   :synopsis: A source module for memcache stats

.. moduleauthor:: Colin Alston <colin@tamvera.com>
"""
import asyncio

from zope.interface import implementer

from duct.interfaces import IDuctSource
from duct.objects import Source

from duct.aggregators import Counter64


async def _get_memcache_stats(host, port, timeout=5.0):
    """Connect to memcached and retrieve stats as a dict."""
    reader, writer = await asyncio.wait_for(
        asyncio.open_connection(host, port), timeout=timeout)
    try:
        writer.write(b'stats\r\n')
        await writer.drain()

        stats = {}
        while True:
            line = (await reader.readline()).decode()
            if line.startswith('END'):
                break
            if line.startswith('STAT '):
                parts = line.split()
                if len(parts) == 3:
                    stats[parts[1]] = parts[2]
        return stats
    finally:
        writer.close()
        try:
            await writer.wait_closed()
        except Exception:
            pass


[docs] @implementer(IDuctSource) class Memcache(Source): """Reads memcache metrics :param host: Database host (default localhost) :type host: str. :param port: Database port (default 11211) :type port: int. **Metrics:** :(service name).(metrics): Metrics from memcached """ def __init__(self, *a, **kw): Source.__init__(self, *a, **kw) self.host = self.config.get('host', '127.0.0.1') self.port = self.config.get('port', 11211)
[docs] async def get(self): events = [] try: raw = await _get_memcache_stats(self.host, self.port) events.append(self.createEvent('ok', 'Connection', 1, prefix='state')) except Exception: events.append(self.createEvent('critical', 'Connection refused', 0, prefix='state')) return events counters = [ 'reclaimed', 'evictions', 'total_items', 'touch_hits', 'touch_misses', 'delete_misses', 'delete_hits', 'incr_hits', 'incr_misses', 'cas_hits', 'cas_misses', 'cas_badval', 'get_misses', 'get_hits', 'decr_misses', 'decr_hits', 'cmd_set', 'cmd_flush', 'cmd_touch', 'cmd_get', 'bytes_written', 'bytes_read', ] vals = ['curr_connections', 'curr_items', 'hash_bytes', 'bytes'] for key in counters: if key in raw: d = key.capitalize().replace('_', ' ') s = key.replace('_', '.') events.append(self.createEvent('ok', d, int(raw[key]), prefix=s, aggregation=Counter64)) for key in vals: if key in raw: d = key.capitalize().replace('_', ' ') s = key.replace('_', '.') events.append(self.createEvent('ok', d, int(raw[key]), prefix=s)) return events