[sysmon] Track the number of running sysmon processes

BUG=chromium:666013
TEST=Run sysmon on test host

Change-Id: I0fa323c8ad5707db80182057c42c6f8e91e7b17e
Reviewed-on: https://chromium-review.googlesource.com/414485
Commit-Ready: Allen Li <ayatane@chromium.org>
Tested-by: Allen Li <ayatane@chromium.org>
Reviewed-by: Aviv Keshet <akeshet@chromium.org>
diff --git a/scripts/sysmon/system_metrics.py b/scripts/sysmon/system_metrics.py
index 3d1778f..ff8f1a5 100644
--- a/scripts/sysmon/system_metrics.py
+++ b/scripts/sysmon/system_metrics.py
@@ -108,6 +108,9 @@
 _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.')
 _load_average_metric = ts_mon.FloatMetric(
     'dev/proc/load_average',
     description='Number of processes currently '
@@ -305,13 +308,17 @@
 
 def get_proc_info():
   autoserv_count = 0
+  sysmon_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
     total += 1
   logging.debug('autoserv_count: %s', autoserv_count)
   _autoserv_proc_count_metric.set(autoserv_count)
+  _sysmon_proc_count_metric.set(sysmon_count)
   _proc_count_metric.set(total)
 
 
@@ -328,6 +335,26 @@
   return proc.name() == 'autoserv'
 
 
+def _is_sysmon(proc):
+  """Return whether proc is a sysmon process."""
+  # This is fragile due to the virtualenv bootstrap of sysmon.
+  # The process tree for an Upstart invocation of sysmon is:
+  #
+  # init -> sudo -> python2 -> python
+  #
+  # If sysmon is started without using Upstart:
+  #
+  # init -> (shell) -> python2 -> python
+  #
+  # The extra python2 is due to the virtualenv wrapper script, which should do
+  # an exec to avoid wasting a process.  The fact that the first has a 2 and
+  # the second doesn't is basically just luck.
+  #
+  # TODO(ayatane): Once the chromite virtualenv wrapper uses exec, clean this
+  # up.
+  return proc.name() == 'python' and 'sysmon' in ' '.join(proc.cmdline())
+
+
 def get_load_avg():
   try:
     avg1, avg5, avg15 = os.getloadavg()