metrics_utils.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #!/usr/bin/env python
  2. # Copyright (c) 2018 The Chromium Authors. All rights reserved.
  3. # Use of this source code is governed by a BSD-style license that can be
  4. # found in the LICENSE file.
  5. from __future__ import print_function
  6. import scm
  7. import subprocess2
  8. import sys
  9. from third_party import colorama
  10. # Current version of metrics recording.
  11. # When we add new metrics, the version number will be increased, we display the
  12. # user what has changed, and ask the user to agree again.
  13. CURRENT_VERSION = 0
  14. APP_URL = 'https://cit-cli-metrics.appspot.com'
  15. EMPTY_LINE = (
  16. '* *'
  17. )
  18. NOTICE_COUNTDOWN_HEADER = (
  19. '*****************************************************\n'
  20. '* METRICS COLLECTION WILL START IN %2d EXECUTIONS *'
  21. )
  22. NOTICE_COLLECTION_HEADER = (
  23. '*****************************************************\n'
  24. '* METRICS COLLECTION IS TAKING PLACE *'
  25. )
  26. NOTICE_VERSION_CHANGE_HEADER = (
  27. '*****************************************************\n'
  28. '* WE ARE COLLECTING ADDITIONAL METRICS *'
  29. )
  30. NOTICE_FOOTER = (
  31. '* For more information, and for how to disable this *\n'
  32. '* message, please see metrics.README.md in your *\n'
  33. '* depot_tools checkout. *\n'
  34. '*****************************************************\n'
  35. )
  36. CHANGE_NOTICE = {
  37. # No changes for version 0
  38. 0: '',
  39. }
  40. KNOWN_PROJECT_URLS = {
  41. 'https://chrome-internal.googlesource.com/chrome/ios_internal',
  42. 'https://chrome-internal.googlesource.com/infra/infra_internal',
  43. 'https://chromium.googlesource.com/breakpad/breakpad',
  44. 'https://chromium.googlesource.com/chromium/src',
  45. 'https://chromium.googlesource.com/chromium/tools/depot_tools',
  46. 'https://chromium.googlesource.com/crashpad/crashpad',
  47. 'https://chromium.googlesource.com/external/gyp',
  48. 'https://chromium.googlesource.com/external/naclports',
  49. 'https://chromium.googlesource.com/infra/goma/client',
  50. 'https://chromium.googlesource.com/infra/infra',
  51. 'https://chromium.googlesource.com/native_client/',
  52. 'https://chromium.googlesource.com/syzygy',
  53. 'https://chromium.googlesource.com/v8/v8',
  54. 'https://dart.googlesource.com/sdk',
  55. 'https://pdfium.googlesource.com/pdfium',
  56. 'https://skia.googlesource.com/buildbot',
  57. 'https://skia.googlesource.com/skia',
  58. 'https://webrtc.googlesource.com/src',
  59. }
  60. def get_python_version():
  61. """Return the python version in the major.minor.micro format."""
  62. return '{v.major}.{v.minor}.{v.micro}'.format(v=sys.version_info)
  63. def return_code_from_exception(exception):
  64. """Returns the exit code that would result of raising the exception."""
  65. if exception is None:
  66. return 0
  67. if isinstance(exception[1], SystemExit):
  68. return exception[1].code
  69. return 1
  70. def seconds_to_weeks(duration):
  71. """Transform a |duration| from seconds to weeks approximately.
  72. Drops the lowest 19 bits of the integer representation, which ammounts to
  73. about 6 days.
  74. """
  75. return int(duration) >> 19
  76. def get_repo_timestamp(path_to_repo):
  77. """Get an approximate timestamp for the upstream of |path_to_repo|.
  78. Returns the top two bits of the timestamp of the HEAD for the upstream of the
  79. branch path_to_repo is checked out at.
  80. """
  81. # Get the upstream for the current branch. If we're not in a branch, fallback
  82. # to HEAD.
  83. try:
  84. upstream = scm.GIT.GetUpstreamBranch(path_to_repo)
  85. except subprocess2.CalledProcessError:
  86. upstream = 'HEAD'
  87. # Get the timestamp of the HEAD for the upstream of the current branch.
  88. p = subprocess2.Popen(
  89. ['git', '-C', path_to_repo, 'log', '-n1', upstream, '--format=%at'],
  90. stdout=subprocess2.PIPE, stderr=subprocess2.PIPE)
  91. stdout, _ = p.communicate()
  92. # If there was an error, give up.
  93. if p.returncode != 0:
  94. return None
  95. # Get the age of the checkout in weeks.
  96. return seconds_to_weeks(stdout.strip())
  97. def print_notice(countdown):
  98. """Print a notice to let the user know the status of metrics collection."""
  99. colorama.init()
  100. print(colorama.Fore.RED + '\033[1m', file=sys.stderr, end='')
  101. if countdown:
  102. print(NOTICE_COUNTDOWN_HEADER % countdown, file=sys.stderr)
  103. else:
  104. print(NOTICE_COLLECTION_HEADER, file=sys.stderr)
  105. print(EMPTY_LINE, file=sys.stderr)
  106. print(NOTICE_FOOTER + colorama.Style.RESET_ALL, file=sys.stderr)
  107. def print_version_change(config_version):
  108. """Print a notice to let the user know we are collecting more metrics."""
  109. colorama.init()
  110. print(colorama.Fore.RED + '\033[1m', file=sys.stderr, end='')
  111. print(NOTICE_VERSION_CHANGE_HEADER, file=sys.stderr)
  112. print(EMPTY_LINE, file=sys.stderr)
  113. for version in range(config_version + 1, CURRENT_VERSION + 1):
  114. print(CHANGE_NOTICE[version], file=sys.stderr)
  115. print(EMPTY_LINE, file=sys.stderr)