metrics: Add counter support

Add support for a counter, where a metric key can be incremented or
decremented, optionally by a given value (default 1).

BUG=b:229737154
TEST=run_tests

Change-Id: I65408bd187d5de2ee7ede3e6172694d499deb452
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/3593895
Tested-by: Alex Klein <saklein@chromium.org>
Reviewed-by: Lizzy Presland <zland@google.com>
Commit-Queue: Alex Klein <saklein@chromium.org>
diff --git a/api/metrics.py b/api/metrics.py
index c61c0df..f521ec6 100644
--- a/api/metrics.py
+++ b/api/metrics.py
@@ -8,6 +8,7 @@
 module will be creating.
 """
 
+import collections
 import logging
 
 from chromite.utils import metrics
@@ -24,6 +25,8 @@
     output_events: A chromiumos.MetricEvent protobuf message.
     prefix: A string to prepend to all metric event names.
   """
+  counters = collections.defaultdict(int)
+  counter_times = {}
   timers = {}
 
   def make_name(name):
@@ -60,10 +63,26 @@
       output_event.name = make_name(input_event.name)
       output_event.timestamp_milliseconds = input_event.timestamp_epoch_millis
       output_event.gauge = input_event.arg
+    elif input_event.op == metrics.OP_INCREMENT_COUNTER:
+      counters[input_event.name] += input_event.arg
+      counter_times[input_event.name] = max(
+          input_event.timestamp_epoch_millis,
+          counter_times.get(input_event.name, 0))
+    elif input_event.op == metrics.OP_DECREMENT_COUNTER:
+      counters[input_event.name] -= input_event.arg
+      counter_times[input_event.name] = max(
+          input_event.timestamp_epoch_millis,
+          counter_times.get(input_event.name, 0))
     else:
       raise ValueError('unexpected op "%s" found in metric event: %s' % (
           input_event.op, input_event))
 
+  for counter, value in counters.items():
+    output_event = output_events.add()
+    output_event.name = make_name(counter)
+    output_event.gauge = value
+    output_event.timestamp_milliseconds = counter_times[counter]
+
   # This is a sanity-check for unclosed timers.
   # TODO(wbbradley): Turn this back into an assert https://crbug.com/1001909.
   if timers: