sysmon: Add CPU percent per process metric
BUG=chromium:728911
TEST=None
This commit is the combination of multiple commits. Their commit
messages are as follows:
commit c25ee1049101d6dba3211644586ed918be0881b6
Author: Allen Li <ayatane@chromium.org>
Date: Wed Jun 21 12:23:46 2017 -0700
sysmon: Make a class for process metric collection
The current code structure encourages linear growth of the function
size.
BUG=chromium:728911
TEST=None
Change-Id: Ic9a1c027f6e0d47d6e915b76879663d28c63632a
commit 291db06dfa626142f9eec8ee82bee82b179fdba9
Author: Allen Li <ayatane@chromium.org>
Date: Wed Jun 21 12:39:22 2017 -0700
sysmon: Extract per-process metrics into class
BUG=chromium:728911
TEST=None
Change-Id: Ib688a21336cde877bea86e1bbaa9c4746e7f073e
commit 84a7ae65e88bbcf16dab2904f1c15fb56717592f
Author: Allen Li <ayatane@chromium.org>
Date: Wed Jun 21 13:03:10 2017 -0700
sysmon: Use Monarch streams for process count
BUG=chromium:728911
TEST=None
Change-Id: I31d12e561a98632b5aa2993cfc8ffa2d49b2669c
commit 16a01ee2197656d670db7346437124bd532f450f
Author: Allen Li <ayatane@chromium.org>
Date: Wed Jun 21 14:25:00 2017 -0700
sysmon: Add CPU percent per process metric
Im not sure how accurate summing the CPU percent for all processes is
with respect to threads and such, but we can push this out first and
augment the logic if the metrics are too far off.
BUG=chromium:728911
TEST=None
Change-Id: Ibe3ea7fa90940bba8c32af65e55290391eae7c49
Change-Id: I67cf7bed920700df4fc7989c181e0f19960f3f87
Reviewed-on: https://chromium-review.googlesource.com/545102
Commit-Ready: Allen Li <ayatane@chromium.org>
Tested-by: Allen Li <ayatane@chromium.org>
Reviewed-by: Allen Li <ayatane@chromium.org>
diff --git a/scripts/sysmon/proc_metrics.py b/scripts/sysmon/proc_metrics.py
index c712fd8..3527509 100644
--- a/scripts/sysmon/proc_metrics.py
+++ b/scripts/sysmon/proc_metrics.py
@@ -14,40 +14,87 @@
logger = logging.getLogger(__name__)
-_proc_count_metric = ts_mon.GaugeMetric(
- 'dev/proc/count',
+_count_metric = ts_mon.GaugeMetric(
+ 'proc/count',
description='Number of processes currently running.')
-_autoserv_proc_count_metric = ts_mon.GaugeMetric(
- 'dev/proc/autoserv_count',
- description='Number of autoserv processes currently running.')
-_sysmon_proc_count_metric = ts_mon.GaugeMetric(
- 'dev/proc/sysmon_count',
- description='Number of sysmon processes currently running.')
-_apache_proc_count_metric = ts_mon.GaugeMetric(
- 'dev/proc/apache_count',
- description='Number of apache processes currently running.')
+_cpu_percent_metric = ts_mon.GaugeMetric(
+ 'proc/cpu_percent',
+ description='CPU usage percent of processes.')
def collect_proc_info():
- autoserv_count = 0
- sysmon_count = 0
- apache_count = 0
- total = 0
- for proc in psutil.process_iter():
- if _is_parent_autoserv(proc):
- autoserv_count += 1
- elif _is_sysmon(proc):
- sysmon_count += 1
- elif _is_apache(proc):
- apache_count += 1
- total += 1
- logger.debug(u'autoserv_count: %s', autoserv_count)
- logger.debug(u'sysmon_count: %s', sysmon_count)
- logger.debug(u'apache_count: %s', apache_count)
- _autoserv_proc_count_metric.set(autoserv_count)
- _sysmon_proc_count_metric.set(sysmon_count)
- _apache_proc_count_metric.set(apache_count)
- _proc_count_metric.set(total)
+ collector = _ProcessMetricsCollector()
+ collector.collect()
+
+
+class _ProcessMetricsCollector(object):
+ """Class for collecting process metrics."""
+
+ def __init__(self):
+ self._metrics = [
+ _ProcessMetric('autoserv',
+ test_func=_is_parent_autoserv),
+ _ProcessMetric('sysmon',
+ test_func=_is_sysmon),
+ _ProcessMetric('apache',
+ test_func=_is_apache),
+ ]
+ self._other_metric = _ProcessMetric('other')
+
+ def collect(self):
+ for proc in psutil.process_iter():
+ self._collect_proc(proc)
+ self._flush()
+
+ def _collect_proc(self, proc):
+ collected = []
+ for metric in self._metrics:
+ collected.append(metric.add(proc))
+ if not any(collected):
+ self._other_metric.add(proc)
+
+ def _flush(self):
+ for metric in self._metrics:
+ metric.flush()
+ self._other_metric.flush()
+
+
+class _ProcessMetric(object):
+ """Class for gathering process metrics."""
+
+ def __init__(self, process_name, test_func=lambda proc: True):
+ """Initialize instance.
+
+ process_name is used to identify the metric stream.
+
+ test_func is a function called
+ for each process. If it returns True, the process is counted. The
+ default test is to count every process.
+ """
+ self._fields = {
+ 'process_name': process_name,
+ }
+ self._test_func = test_func
+ self._count = 0
+ self._cpu_percent = 0
+
+ def add(self, proc):
+ """Do metric collection for the given process.
+
+ Returns True if the process was collected.
+ """
+ if not self._test_func(proc):
+ return False
+ self._count += 1
+ self._cpu_percent += proc.cpu_percent()
+ return True
+
+ def flush(self):
+ """Finish collection and send metrics."""
+ _count_metric.set(self._count, fields=self._fields)
+ self._count = 0
+ _cpu_percent_metric.set(self._count, fields=self._fields)
+ self._cpu_percent = 0
def _is_parent_autoserv(proc):