diff --git a/metrics.py b/metrics.py index 69c19e4174..df366a4013 100644 --- a/metrics.py +++ b/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]) diff --git a/metrics_utils.py b/metrics_utils.py index 281b78624d..5792118f66 100644 --- a/metrics_utils.py +++ b/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) diff --git a/upload_metrics.py b/upload_metrics.py index 41fd1930af..2578cc5c82 100644 --- a/upload_metrics.py +++ b/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