1 # -*- coding: utf-8 -*-
2 # Description: memcached netdata python.d module
3 # Author: Pawel Krupa (paulfantom)
5 from base import SocketService
7 # default module values (can be overridden per job in `config`)
12 # default job configuration (overridden by python.d.plugin)
13 # config = {'local': {
14 # 'update_every': update_every,
16 # 'priority': priority,
17 # 'host': 'localhost',
22 ORDER = ['cache', 'net', 'connections', 'items', 'evicted_reclaimed',
23 'get', 'get_rate', 'set_rate', 'cas', 'delete', 'increment', 'decrement', 'touch', 'touch_rate']
27 'options': [None, 'Cache Size', 'megabytes', 'cache', 'memcached.cache', 'stacked'],
29 ['avail', 'available', 'absolute', 1, 1048576],
30 ['used', 'used', 'absolute', 1, 1048576]
33 'options': [None, 'Network', 'kilobits/s', 'network', 'memcached.net', 'area'],
35 ['bytes_read', 'in', 'incremental', 8, 1024],
36 ['bytes_written', 'out', 'incremental', -8, 1024]
39 'options': [None, 'Connections', 'connections/s', 'connections', 'memcached.connections', 'line'],
41 ['curr_connections', 'current', 'incremental'],
42 ['rejected_connections', 'rejected', 'incremental'],
43 ['total_connections', 'total', 'incremental']
46 'options': [None, 'Items', 'items', 'items', 'memcached.items', 'line'],
48 ['curr_items', 'current', 'absolute'],
49 ['total_items', 'total', 'absolute']
51 'evicted_reclaimed': {
52 'options': [None, 'Items', 'items', 'items', 'memcached.evicted_reclaimed', 'line'],
54 ['reclaimed', 'reclaimed', 'absolute'],
55 ['evictions', 'evicted', 'absolute']
58 'options': [None, 'Requests', 'requests', 'get ops', 'memcached.get', 'stacked'],
60 ['get_hits', 'hits', 'percent-of-absolute-row'],
61 ['get_misses', 'misses', 'percent-of-absolute-row']
64 'options': [None, 'Rate', 'requests/s', 'get ops', 'memcached.get_rate', 'line'],
66 ['cmd_get', 'rate', 'incremental']
69 'options': [None, 'Rate', 'requests/s', 'set ops', 'memcached.set_rate', 'line'],
71 ['cmd_set', 'rate', 'incremental']
74 'options': [None, 'Requests', 'requests', 'delete ops', 'memcached.delete', 'stacked'],
76 ['delete_hits', 'hits', 'percent-of-absolute-row'],
77 ['delete_misses', 'misses', 'percent-of-absolute-row'],
80 'options': [None, 'Requests', 'requests', 'check and set ops', 'memcached.cas', 'stacked'],
82 ['cas_hits', 'hits', 'percent-of-absolute-row'],
83 ['cas_misses', 'misses', 'percent-of-absolute-row'],
84 ['cas_badval', 'bad value', 'percent-of-absolute-row']
87 'options': [None, 'Requests', 'requests', 'increment ops', 'memcached.increment', 'stacked'],
89 ['incr_hits', 'hits', 'percent-of-absolute-row'],
90 ['incr_misses', 'misses', 'percent-of-absolute-row']
93 'options': [None, 'Requests', 'requests', 'decrement ops', 'memcached.decrement', 'stacked'],
95 ['decr_hits', 'hits', 'percent-of-absolute-row'],
96 ['decr_misses', 'misses', 'percent-of-absolute-row']
99 'options': [None, 'Requests', 'requests', 'touch ops', 'memcached.touch', 'stacked'],
101 ['touch_hits', 'hits', 'percent-of-absolute-row'],
102 ['touch_misses', 'misses', 'percent-of-absolute-row']
105 'options': [None, 'Rate', 'requests/s', 'touch ops', 'memcached.touch_rate', 'line'],
107 ['cmd_touch', 'rate', 'incremental']
112 class Service(SocketService):
113 def __init__(self, configuration=None, name=None):
114 SocketService.__init__(self, configuration=configuration, name=name)
115 self.request = "stats\r\n"
116 self.host = "localhost"
118 self._keep_alive = True
119 self.unix_socket = None
121 self.definitions = CHARTS
128 response = self._get_raw_data()
130 # error has already been logged
133 if response.startswith('ERROR'):
134 self.error("received ERROR")
138 parsed = response.split("\n")
139 except AttributeError:
140 self.error("response is invalid/empty")
146 if line.startswith('STAT'):
148 t = line[5:].split(' ')
150 except (IndexError, ValueError):
151 self.debug("invalid line received: " + str(line))
155 self.error("received data doesn't have any records")
158 # custom calculations
160 data['avail'] = int(data['limit_maxbytes']) - int(data['bytes'])
161 data['used'] = int(data['bytes'])
167 def _check_raw_data(self, data):
168 if data.endswith('END\r\n'):
169 self.debug("received full response from memcached")
172 self.debug("waiting more data from memcached")
177 Parse configuration, check if memcached is available
183 self.chart_name += "_" + self.name
184 data = self._get_data()