From 534303bfd4bd8778b66bd8355e1c2dffb05f7e47 Mon Sep 17 00:00:00 2001 From: Clint Armstrong Date: Wed, 21 Sep 2016 11:42:17 -0400 Subject: [PATCH] Improve phpfpm module. * Get the fpm stats in json format for easy parsing * Get stats for each process and track maximums and averages for each. --- conf.d/python.d/phpfpm.conf | 7 +++-- python.d/phpfpm.chart.py | 61 ++++++++++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/conf.d/python.d/phpfpm.conf b/conf.d/python.d/phpfpm.conf index 06d2367a..f5d067cc 100644 --- a/conf.d/python.d/phpfpm.conf +++ b/conf.d/python.d/phpfpm.conf @@ -57,6 +57,7 @@ # Additionally to the above, PHP-FPM also supports the following: # # url: 'URL' # the URL to fetch nginx's status stats +# # Be sure and include ?full&status at the end of the url # # if the URL is password protected, the following are supported: # @@ -70,13 +71,13 @@ localhost: name : 'local' - url : "http://localhost/status" + url : "http://localhost/status?full&json" localipv4: name : 'local' - url : "http://127.0.0.1/status" + url : "http://127.0.0.1/status?full&json" localipv6: name : 'local' - url : "http://::1/status" + url : "http://::1/status?full&json" diff --git a/python.d/phpfpm.chart.py b/python.d/phpfpm.chart.py index d1791d42..7f2da9cc 100755 --- a/python.d/phpfpm.chart.py +++ b/python.d/phpfpm.chart.py @@ -3,6 +3,7 @@ # Author: Pawel Krupa (paulfantom) from base import UrlService +import json # default module values (can be overridden per job in `config`) # update_every = 2 @@ -18,7 +19,7 @@ retries = 60 # }} # charts order (can be overridden if you want less charts, or different order) -ORDER = ['connections', 'requests', 'performance'] +ORDER = ['connections', 'requests', 'performance', 'request_duration', 'request_cpu', 'request_mem'] CHARTS = { 'connections': { @@ -38,6 +39,24 @@ CHARTS = { 'lines': [ ["reached", 'max children reached'], ["slow", 'slow requests'] + ]}, + 'request_duration': { + 'options': [None, 'PHP-FPM Request Duration', 'milliseconds', 'phpfpm', 'phpfpm.request_duration', 'line'], + 'lines': [ + ["maxReqDur", 'max request duration'], + ["avgReqDur", 'average request duration'] + ]}, + 'request_cpu': { + 'options': [None, 'PHP-FPM Request CPU', 'percent', 'phpfpm', 'phpfpm.request_cpu', 'line'], + 'lines': [ + ["maxReqCPU", 'max request cpu'], + ["avgReqCPU", 'average request cpu'] + ]}, + 'request_mem': { + 'options': [None, 'PHP-FPM Request Memory', 'kilobytes', 'phpfpm', 'phpfpm.request_mem', 'line'], + 'lines': [ + ["maxReqMem", 'max request memory'], + ["avgReqMem", 'average request memory'] ]} } @@ -46,7 +65,7 @@ class Service(UrlService): def __init__(self, configuration=None, name=None): UrlService.__init__(self, configuration=configuration, name=name) if len(self.url) == 0: - self.url = "http://localhost/status" + self.url = "http://localhost/status?full&json" self.order = ORDER self.definitions = CHARTS self.assignment = {"active processes": 'active', @@ -55,6 +74,9 @@ class Service(UrlService): "accepted conn": 'requests', "max children reached": 'reached', "slow requests": 'slow'} + self.proc_assignment = {"request duration": 'ReqDur', + "last request cpu": 'ReqCPU', + "last request memory": 'ReqMem'} def _get_data(self): """ @@ -62,17 +84,34 @@ class Service(UrlService): :return: dict """ try: - raw = self._get_raw_data().split('\n') + raw = self._get_raw_data() except AttributeError: return None - data = {} - for row in raw: - tmp = row.split(":") - if str(tmp[0]) in self.assignment: - try: - data[self.assignment[tmp[0]]] = int(tmp[1]) - except (IndexError, ValueError): - pass + + try: + raw_json = json.loads(raw) + except ValueError: + return None + + data = {self.assignment[k]: v for k, v in raw_json.items() if k in self.assignment} + + c = 0 + for proc in raw_json['processes']: + if proc['state'] != 'Idle': + continue + c += 1 + for k, v in self.proc_assignment.items(): + d = proc[k] + if v == 'ReqDur': + d = d/1000 + if v == 'ReqMem': + d = d/1024 + if 'max' + v not in data or data['max' + v] < d: + data['max' + v] = d + if 'avg' + v not in data: + data['avg' + v] = 0 + data['avg' + v] = (data['avg' + v] + d) / c + if len(data) == 0: return None return data -- 2.39.2