metrics: Add a mechanism to notify users when we want to collect additional metrics.

When we change the version number in metrics_utils:

If the user is not a Googler, or has opted out explicitly, nothing happens
and we still don't collect metrics.

If we're collecting metrics from the user, we stop collecting metrics
and display a notice telling them what has changed.
That notice will be displayed ten times, after which we will
resume collecting metrics. A notice telling them we're collecting metrics
will still be displayed.

Bug: None
Change-Id: If1cc12b2fc06f0d6237714c4f182367b1afdf9fb
Reviewed-on: https://chromium-review.googlesource.com/c/1285395
Commit-Queue: Edward Lesmes <ehmaldonado@chromium.org>
Reviewed-by: Andrii Shyshkalov <tandrii@chromium.org>
diff --git a/metrics.py b/metrics.py
index 6b556e2..c2c88e0 100644
--- a/metrics.py
+++ b/metrics.py
@@ -69,6 +69,7 @@
     # safe values otherwise.
     self._config.setdefault('countdown', DEFAULT_COUNTDOWN)
     self._config.setdefault('opt-in', None)
+    self._config.setdefault('version', metrics_utils.CURRENT_VERSION)
 
     if config != self._config:
       print(INVALID_CONFIG_WARNING, file=sys.stderr)
@@ -84,6 +85,11 @@
       self._config['opt-in'] = False
 
   @property
+  def version(self):
+    self._ensure_initialized()
+    return self._config['version']
+
+  @property
   def is_googler(self):
     self._ensure_initialized()
     return self._config['is-googler']
@@ -97,6 +103,7 @@
   def opted_in(self, value):
     self._ensure_initialized()
     self._config['opt-in'] = value
+    self._config['version'] = metrics_utils.CURRENT_VERSION
     self._write_config()
 
   @property
@@ -104,13 +111,34 @@
     self._ensure_initialized()
     return self._config['countdown']
 
+  @property
+  def should_collect_metrics(self):
+    # Don't collect the metrics unless the user is a googler, the user has opted
+    # in, or the countdown has expired.
+    if not self.is_googler:
+      return False
+    if self.opted_in is False:
+      return False
+    if self.opted_in is None and self.countdown > 0:
+      return False
+    return True
+
   def decrease_countdown(self):
     self._ensure_initialized()
     if self.countdown == 0:
       return
     self._config['countdown'] -= 1
+    if self.countdown == 0:
+      self._config['version'] = metrics_utils.CURRENT_VERSION
     self._write_config()
 
+  def reset_config(self):
+    # Only reset countdown if we're already collecting metrics.
+    if self.should_collect_metrics:
+      self._ensure_initialized()
+      self._config['countdown'] = DEFAULT_COUNTDOWN
+      self._config['opt-in'] = None
+
 
 class MetricsCollector(object):
   def __init__(self):
@@ -198,10 +226,7 @@
       # file.
       if DISABLE_METRICS_COLLECTION:
         return func
-      # Don't collect the metrics unless the user is a googler, the user has
-      # opted in, or the countdown has expired.
-      if (not self.config.is_googler or self.config.opted_in == False
-          or (self.config.opted_in is None and self.config.countdown > 0)):
+      if not self.config.should_collect_metrics:
         return func
       # Otherwise, collect the metrics.
       # Needed to preserve the __name__ and __doc__ attributes of func.
@@ -236,6 +261,13 @@
       elif not isinstance(exception[1], SystemExit):
         traceback.print_exception(*exception)
 
+    # Check if the version has changed
+    if (not DISABLE_METRICS_COLLECTION and self.config.is_googler
+        and self.config.opted_in is not False
+        and self.config.version != metrics_utils.CURRENT_VERSION):
+      metrics_utils.print_version_change(self.config.version)
+      self.config.reset_config()
+
     # Print the notice
     if (not DISABLE_METRICS_COLLECTION and self.config.is_googler
         and self.config.opted_in is None):