sysmon: Add metrics for unstaged git changes

Not sure if this is papering over a bug, but this is currently
breaking by workflow

BUG=chromium:724580
TEST=None

Change-Id: If2011dbadca93ecd7f270aed120ee359113707d9
Reviewed-on: https://chromium-review.googlesource.com/544104
Commit-Ready: Allen Li <ayatane@chromium.org>
Tested-by: Allen Li <ayatane@chromium.org>
Reviewed-by: Paul Hobbs <phobbs@google.com>
diff --git a/scripts/sysmon/git_metrics.py b/scripts/sysmon/git_metrics.py
index 219f486..a0aa7d4 100644
--- a/scripts/sysmon/git_metrics.py
+++ b/scripts/sysmon/git_metrics.py
@@ -7,6 +7,7 @@
 from __future__ import absolute_import
 from __future__ import print_function
 
+import collections
 import os
 import subprocess
 
@@ -16,6 +17,9 @@
 logger = logging.getLogger(__name__)
 
 
+_Stats = collections.namedtuple('_Stats', 'added,deleted,path')
+
+
 class _GitRepo(object):
   """Helper class for running git commands."""
 
@@ -38,6 +42,19 @@
     return int(self._check_output(['show', '-s', '--format=%ct', 'HEAD'])
                .strip())
 
+  def get_unstaged_changes(self):
+    """Return number of unstaged changes as (added, deleted)."""
+    added, deleted = 0, 0
+    # output looks like '1\t2\tfoo\n3\t4\tbar\n'
+    output = self._check_output(['diff-index', '--numstat', 'HEAD'])
+    stats_strings = (line.split() for line in output.splitlines())
+    stats_iter = (_Stats(int(added), int(deleted), path)
+             for added, deleted, path in stats_strings)
+    for stats in stats_iter:
+      added += stats.added
+      deleted += stats.deleted
+    return added, deleted
+
 
 class _GitMetricCollector(object):
   """Class for collecting metrics about a git repository.
@@ -56,6 +73,10 @@
       'git/timestamp',
       description='Current Git commit time as seconds since Unix Epoch.')
 
+  _unstaged_changes_metric = ts_mon.GaugeMetric(
+      'git/unstaged_changes',
+      description='Unstaged Git changes.')
+
   def __init__(self, gitdir, metric_path):
     self._gitdir = gitdir
     self._gitrepo = _GitRepo(os.path.expanduser(gitdir))
@@ -67,6 +88,7 @@
     try:
       self._collect_commit_hash_metric()
       self._collect_timestamp_metric()
+      self._collect_unstaged_changes_metric()
     except subprocess.CalledProcessError as e:
       logger.warning(u'Error collecting git metrics for %s: %s',
                      self._gitdir, e)
@@ -82,6 +104,13 @@
                  commit_time, self._gitdir)
     self._timestamp_metric.set(commit_time, self._fields)
 
+  def _collect_unstaged_changes_metric(self):
+    added, deleted = self._gitrepo.get_commit_time()
+    self._timestamp_metric.set(
+        added, fields=dict(change_type='added', **self._fields))
+    self._timestamp_metric.set(
+        deleted, fields=dict(change_type='deleted', **self._fields))
+
 
 _CHROMIUMOS_DIR = '~chromeos-test/chromiumos/'