1 # -*- coding: utf-8 -*-
2 # Description: PHP-FPM netdata python.d module
3 # Author: Pawel Krupa (paulfantom)
5 from base import UrlService
9 # default module values (can be overridden per job in `config`)
14 # default job configuration (overridden by python.d.plugin)
15 # config = {'local': {
16 # 'update_every': update_every,
18 # 'priority': priority,
19 # 'url': 'http://localhost/status?full&json'
22 # charts order (can be overridden if you want less charts, or different order)
25 ('active processes', 'active'),
26 ('max active processes', 'maxActive'),
27 ('idle processes', 'idle'),
28 ('accepted conn', 'requests'),
29 ('max children reached', 'reached'),
30 ('slow requests', 'slow')
34 ('request duration', 'ReqDur'),
35 ('last request cpu', 'ReqCpu'),
36 ('last request memory', 'ReqMem')
40 def average(collection):
41 return sum(collection, 0.0) / max(len(collection), 1)
49 ORDER = ['connections', 'requests', 'performance', 'request_duration', 'request_cpu', 'request_mem']
53 'options': [None, 'PHP-FPM Active Connections', 'connections', 'active connections', 'phpfpm.connections',
57 ['maxActive', 'max active'],
61 'options': [None, 'PHP-FPM Requests', 'requests/s', 'requests', 'phpfpm.requests', 'line'],
63 ['requests', None, 'incremental']
66 'options': [None, 'PHP-FPM Performance', 'status', 'performance', 'phpfpm.performance', 'line'],
68 ['reached', 'max children reached'],
69 ['slow', 'slow requests']
72 'options': [None, 'PHP-FPM Request Duration', 'milliseconds', 'request duration', 'phpfpm.request_duration',
75 ['minReqDur', 'min', 'absolute', 1, 1000],
76 ['maxReqDur', 'max', 'absolute', 1, 1000],
77 ['avgReqDur', 'avg', 'absolute', 1, 1000]
80 'options': [None, 'PHP-FPM Request CPU', 'percent', 'request CPU', 'phpfpm.request_cpu', 'line'],
87 'options': [None, 'PHP-FPM Request Memory', 'kilobytes', 'request memory', 'phpfpm.request_mem', 'line'],
89 ['minReqMem', 'min', 'absolute', 1, 1024],
90 ['maxReqMem', 'max', 'absolute', 1, 1024],
91 ['avgReqMem', 'avg', 'absolute', 1, 1024]
96 class Service(UrlService):
97 def __init__(self, configuration=None, name=None):
98 UrlService.__init__(self, configuration=configuration, name=name)
99 self.url = self.configuration.get('url', 'http://localhost/status?full&json')
101 self.definitions = CHARTS
102 self.regex = re.compile(r'([a-z][a-z ]+): ([\d.]+)')
103 self.json = '&json' in self.url or '?json' in self.url
104 self.json_full = self.url.endswith(('?full&json', '?json&full'))
105 self.if_all_processes_running = dict([(c_name + p_name, 0) for c_name, func in CALC
106 for metric, p_name in PER_PROCESS_INFO])
110 Format data received from http request
113 raw = self._get_raw_data()
117 raw_json = parse_raw_data_(is_json=self.json, regex=self.regex, raw_data=raw)
119 # Per Pool info: active connections, requests and performance charts
120 to_netdata = fetch_data_(raw_data=raw_json, metrics_list=POOL_INFO)
122 # Per Process Info: duration, cpu and memory charts (min, max, avg)
125 to_netdata.update(self.if_all_processes_running) # If all processes are in running state
126 # Metrics are always 0 if the process is not in Idle state because calculation is done
127 # when the request processing has terminated
128 for process in [p for p in raw_json['processes'] if p['state'] == 'Idle']:
129 p_info.update(fetch_data_(raw_data=process, metrics_list=PER_PROCESS_INFO, pid=str(process['pid'])))
132 for new_name in PER_PROCESS_INFO:
133 for name, function in CALC:
134 to_netdata[name + new_name[1]] = function([p_info[k] for k in p_info if new_name[1] in k])
136 return to_netdata or None
139 def fetch_data_(raw_data, metrics_list, pid=''):
141 :param raw_data: dict
142 :param metrics_list: list
147 for metric, new_name in metrics_list:
148 if metric in raw_data:
149 result[new_name + pid] = float(raw_data[metric])
153 def parse_raw_data_(is_json, regex, raw_data):
156 :param regex: compiled regular expr
157 :param raw_data: dict
162 return json.loads(raw_data)
166 raw_data = ' '.join(raw_data.split())
167 return dict(regex.findall(raw_data))