Browse Source

metrics: Report bot metrics if DEPOT_TOOLS_REPORT_BUILD is set

If the DEPOT_TOOLS_REPORT_BUILD envvar is set, Depot Tools will
report information about the builder running the command
(e.g. buildbucket project, bucket, builder and build id).

It will also authenticate to the metrics server, and ignore any
requests not made by ChOps service accounts.

Change-Id: I078a4c2170b4226086c42f289fa449bdebc87179
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2861213
Commit-Queue: Edward Lesmes <ehmaldonado@chromium.org>
Reviewed-by: Josip Sokcevic <sokcevic@google.com>
Edward Lesmes 4 năm trước cách đây
mục cha
commit
1e59a247ab
3 tập tin đã thay đổi với 66 bổ sung19 xóa
  1. 10 2
      metrics.py
  2. 43 10
      metrics_utils.py
  3. 13 7
      upload_metrics.py

+ 10 - 2
metrics.py

@@ -117,12 +117,16 @@ class _Config(object):
 
   @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.
+    # DEPOT_TOOLS_REPORT_BUILD is set on bots to report metrics.
+    if os.getenv(metrics_utils.DEPOT_TOOLS_REPORT_BUILD):
+      return True
+    # Don't report metrics if user is not a Googler.
     if not self.is_googler:
       return False
+    # Don't report metrics if user has opted out.
     if self.opted_in is False:
       return False
+    # Don't report metrics if countdown hasn't reached 0.
     if self.opted_in is None and self.countdown > 0:
       return False
     return True
@@ -227,6 +231,10 @@ class MetricsCollector(object):
     if git_version:
       self.add('git_version', git_version)
 
+    bot_metrics = metrics_utils.get_bot_metrics()
+    if bot_metrics:
+      self.add('bot_metrics', bot_metrics)
+
     self._upload_metrics_data()
     if exception:
       gclient_utils.reraise(exception[0], exception[1], exception[2])

+ 43 - 10
metrics_utils.py

@@ -6,6 +6,7 @@
 from __future__ import print_function
 
 import re
+import os
 import scm
 import subprocess2
 import sys
@@ -19,10 +20,13 @@ except ImportError:  # For Py3 compatibility
 # Current version of metrics recording.
 # When we add new metrics, the version number will be increased, we display the
 # user what has changed, and ask the user to agree again.
-CURRENT_VERSION = 1
+CURRENT_VERSION = 2
 
 APP_URL = 'https://cit-cli-metrics.appspot.com'
 
+DEPOT_TOOLS_REPORT_BUILD = 'DEPOT_TOOLS_REPORT_BUILD'
+
+
 def get_notice_countdown_header(countdown):
   if countdown == 0:
     yield '     METRICS COLLECTION IS TAKING PLACE'
@@ -43,15 +47,28 @@ def get_notice_footer():
 
 def get_change_notice(version):
   if version == 0:
-    pass # No changes for version 0
+    return [] # No changes for version 0
   elif version == 1:
-    yield 'We want to collect the Git version.'
-    yield 'We want to collect information about the HTTP'
-    yield 'requests that depot_tools makes, and the git and'
-    yield 'cipd commands it executes.'
-    yield ''
-    yield 'We only collect known strings to make sure we'
-    yield 'don\'t record PII.'
+    return [
+      'We want to collect the Git version.',
+      'We want to collect information about the HTTP',
+      'requests that depot_tools makes, and the git and',
+      'cipd commands it executes.',
+      '',
+      'We only collect known strings to make sure we',
+      'don\'t record PII.',
+    ]
+  elif version == 2:
+    return [
+      'We will start collecting metrics from bots.',
+      'There are no changes for developers.',
+      'If the DEPOT_TOOLS_REPORT_BUILD environment variable is set,',
+      'we will report information about the current build',
+      '(e.g. buildbucket project, bucket, builder and build id),',
+      'and authenticate to the metrics collection server.',
+      'This information will only be recorded for requests',
+      'authenticated as bot service accounts.',
+    ]
 
 
 KNOWN_PROJECT_URLS = {
@@ -174,6 +191,22 @@ def get_git_version():
   return '%s.%s.%s' % match.groups()
 
 
+def get_bot_metrics():
+  build = os.getenv(DEPOT_TOOLS_REPORT_BUILD)
+  if not build or build.count('/') != 3:
+    return None
+  project, bucket, builder, build = build.split('/')
+  return {
+    'build_id': int(build),
+    'builder': {
+      'project': project,
+      'bucket': bucket,
+      'builder': builder,
+    },
+  }
+
+
+
 def return_code_from_exception(exception):
   """Returns the exit code that would result of raising the exception."""
   if exception is None:
@@ -289,5 +322,5 @@ def print_version_change(config_version):
   lines = list(get_notice_version_change_header())
   for version in range(config_version + 1, CURRENT_VERSION + 1):
     lines.append('')
-    lines += list(get_change_notice(version))
+    lines += get_change_notice(version)
   print_boxed_text(sys.stderr.write, 49, lines)

+ 13 - 7
upload_metrics.py

@@ -1,21 +1,27 @@
-#!/usr/bin/env python
+#!/usr/bin/env vpython3
 # Copyright (c) 2018 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import os
 import sys
+import urllib.error
+import urllib.request
 
-from third_party.six.moves import urllib
-from third_party.six.moves import input # pylint: disable=redefined-builtin
-
+import auth
 import metrics_utils
 
-
 def main():
   metrics = input()
   try:
-    urllib.request.urlopen(
-        metrics_utils.APP_URL + '/upload', metrics.encode('utf-8'))
+    headers = {}
+    if 'bot_metrics' in metrics:
+      token = auth.Authenticator().get_access_token().token
+      headers = {'Authorization': 'Bearer ' + token}
+    urllib.request.urlopen(urllib.request.Request(
+        url=metrics_utils.APP_URL + '/upload',
+        data=metrics.encode('utf-8'),
+        headers=headers))
   except (urllib.error.HTTPError, urllib.error.URLError):
     pass