Revert "Android: Add logging_ext.py module."
This reverts commit 9d96ef6894f46439e73300cdecf8ba30285e77f6.
Reason for revert: blocks rolls into clank on ToT bot.
BUG=758505
Original change's description:
> Android: Add logging_ext.py module.
>
> Adds color in a better way to pylib code.
> Additionally added some more useful test logs (such as whether
> tests pass/fail as they are run and predicted time remaining).
>
> Adding -quiet option which will make the logs as they were
> previously.
>
> Change-Id: I0cec6334a38544ccbb4a4fde6df65b6b56c2547d
> Reviewed-on: https://chromium-review.googlesource.com/603916
> Commit-Queue: Michael Case <[email protected]>
> Reviewed-by: Andrew Grieve <[email protected]>
> Reviewed-by: John Budorick <[email protected]>
> Cr-Commit-Position: refs/heads/master@{#496922}
[email protected],[email protected],[email protected],[email protected]
Change-Id: I11ca3412b5b3516bfd7107aa3f0732e7331b9941
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/631724
Reviewed-by: Anthony Berent <[email protected]>
Commit-Queue: Anthony Berent <[email protected]>
Cr-Commit-Position: refs/heads/master@{#496992}
diff --git a/build/android/play_services/update.py b/build/android/play_services/update.py
index 8a43058..5297b3cf 100755
--- a/build/android/play_services/update.py
+++ b/build/android/play_services/update.py
@@ -22,8 +22,8 @@
from devil.utils import cmd_helper
from play_services import utils
from pylib import constants
-from pylib import logging_ext
from pylib.constants import host_paths
+from pylib.utils import logging_utils
sys.path.append(os.path.join(host_paths.DIR_SOURCE_ROOT, 'build'))
import find_depot_tools # pylint: disable=import-error,unused-import
@@ -89,8 +89,10 @@
AddBucketArguments(parser_upload)
args = parser.parse_args(raw_args)
+ if args.verbose:
+ logging.basicConfig(level=logging.DEBUG)
+ logging_utils.ColorStreamHandler.MakeDefault(not _IsBotEnvironment())
devil_chromium.Initialize()
- logging_ext.Initialize(args.verbose_count)
return args.func(args)
@@ -100,21 +102,25 @@
allows to put arguments after the command: `foo.py upload --debug --force`
instead of `foo.py --debug upload --force`
'''
+
parser.add_argument('--sdk-root',
help='base path to the Android SDK tools root',
default=constants.ANDROID_SDK_ROOT)
+
parser.add_argument('-v', '--verbose',
- dest='verbose_count', default=0, action='count',
- help='Verbose level (multiple times for more)')
+ action='store_true',
+ help='print debug information')
def AddBucketArguments(parser):
parser.add_argument('--bucket',
help='name of the bucket where the files are stored',
default=GMS_CLOUD_STORAGE)
+
parser.add_argument('--config',
help='JSON Configuration file',
default=CONFIG_DEFAULT_PATH)
+
parser.add_argument('--dry-run',
action='store_true',
help=('run the script in dry run mode. Files will be '
@@ -122,6 +128,7 @@
'cloud storage. The bucket name will be as path '
'to that directory relative to the repository '
'root.'))
+
parser.add_argument('-f', '--force',
action='store_true',
help='run even if the library is already up to date')
@@ -177,7 +184,7 @@
license_sha1 = os.path.join(SHA1_DIRECTORY, LICENSE_FILE_NAME + '.sha1')
_DownloadFromBucket(bucket_path, license_sha1, new_license,
- bool(args.verbose_count), args.dry_run)
+ args.verbose, args.dry_run)
if (not _IsBotEnvironment() and
not _CheckLicenseAgreement(new_license, paths.license,
@@ -190,7 +197,7 @@
new_lib_zip = os.path.join(tmp_root, ZIP_FILE_NAME)
_DownloadFromBucket(bucket_path, new_lib_zip_sha1, new_lib_zip,
- bool(args.verbose_count), args.dry_run)
+ args.verbose, args.dry_run)
try:
# Remove the deprecated sdk directory.
diff --git a/build/android/pylib/base/test_collection.py b/build/android/pylib/base/test_collection.py
index 19e1f0dc..de51027 100644
--- a/build/android/pylib/base/test_collection.py
+++ b/build/android/pylib/base/test_collection.py
@@ -74,3 +74,7 @@
"""Return the number of tests currently in the collection."""
return len(self._tests)
+ def test_names(self):
+ """Return a list of the names of the tests currently in the collection."""
+ with self._lock:
+ return list(t.test for t in self._tests)
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index ee84437..8030d0f 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -21,7 +21,6 @@
from devil.android.tools import system_app
from devil.utils import reraiser_thread
from incremental_install import installer
-from pylib import logging_ext
from pylib import valgrind_tools
from pylib.android import logdog_logcat_monitor
from pylib.base import base_test_result
@@ -589,15 +588,6 @@
if self._env.concurrent_adb:
post_test_step_thread_group.JoinAll()
-
- if result.GetType() == base_test_result.ResultType.PASS:
- logging_ext.test_pass('%s %s', result.GetType(), test_display_name)
- elif result.GetType() in (base_test_result.ResultType.NOTRUN,
- base_test_result.ResultType.SKIP):
- pass
- else:
- logging_ext.test_fail('%s %s', result.GetType(), test_display_name)
-
return results, None
def _GetTestsFromRunner(self):
diff --git a/build/android/pylib/local/device/local_device_test_run.py b/build/android/pylib/local/device/local_device_test_run.py
index 6f8cbf2..94e9c82 100644
--- a/build/android/pylib/local/device/local_device_test_run.py
+++ b/build/android/pylib/local/device/local_device_test_run.py
@@ -6,7 +6,6 @@
import logging
import posixpath
import signal
-import time
import thread
import threading
@@ -14,7 +13,6 @@
from devil.android import crash_handler
from devil.android import device_errors
from devil.utils import signal_handler
-from pylib import logging_ext
from pylib import valgrind_tools
from pylib.base import base_test_result
from pylib.base import test_run
@@ -53,15 +51,10 @@
super(LocalDeviceTestRun, self).__init__(env, test_instance)
self._tools = {}
- # Fields used for logging time remaining estimates
- self._start_tests_remaining = None
- self._start_time = None
- self._last_time_log = None
- self._log_lock = threading.Lock()
-
#override
def RunTests(self):
tests = self._GetTests()
+
exit_now = threading.Event()
@local_device_environment.handle_shard_failures
@@ -72,8 +65,6 @@
result = None
rerun = None
- if isinstance(tests, test_collection.TestCollection):
- self._MaybeLogTimeRemaining(tests)
try:
result, rerun = crash_handler.RetryOnSystemCrash(
lambda d, t=test: self._RunTest(d, t),
@@ -129,9 +120,6 @@
try:
if self._ShouldShard():
tc = test_collection.TestCollection(self._CreateShards(tests))
- self._start_tests_remaining = len(tc)
- self._start_time = time.time()
- self._last_time_log = time.time()
self._env.parallel_devices.pMap(
run_tests_on_device, tc, try_results).pGet(None)
else:
@@ -161,41 +149,6 @@
return results
- def _MaybeLogTimeRemaining(self, tests):
- """Log an estimate for how long remains to run the test suite.
-
- If this function has not logged an estimate in the previous |LOG_COOLDOWN|
- then it will log the number of tests remaining to run. This function will
- also attempt to estimate the time remaining in the test run. It does this
- by (1) looking to see if runtimes for tests were cached by a previous run,
- (2) else attempt to extrapolate test runtimes from the tests run so far,
- (3) or fall back to a hardcoded fix value.
-
- Args:
- tests: Test collection.
- """
- LOG_COOLDOWN = 60 # seconds
-
- # Lock is to prevent multiple test shards from simultaneously printing
- # time estimate.
- with self._log_lock:
- if time.time() - self._last_time_log < LOG_COOLDOWN:
- return
- self._last_time_log = time.time()
-
- tests_remaining = len(tests)
- if tests_remaining < self._start_tests_remaining:
- avg_test_duration = (float(time.time() - self._start_time) /
- (self._start_tests_remaining - tests_remaining))
- else:
- avg_test_duration = 1.0
-
- time_estimate = (avg_test_duration * tests_remaining /
- len(self._env.devices))
- logging_ext.test_time('Tests remaining: %d, '
- 'Estimated time remaining: %.2f seconds',
- tests_remaining, time_estimate)
-
def _GetTestsToRetry(self, tests, try_results):
def is_failure_result(test_result):
diff --git a/build/android/pylib/logging_ext/__init__.py b/build/android/pylib/logging_ext/__init__.py
deleted file mode 100644
index 62604c5..0000000
--- a/build/android/pylib/logging_ext/__init__.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright 2017 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.
-
-"""Wrapper around logging to set some custom logging functionality."""
-
-import contextlib
-import logging
-import os
-import time
-import sys
-
-from pylib.constants import host_paths
-from pylib.utils import unicode_characters
-
-_COLORAMA_PATH = os.path.join(
- host_paths.DIR_SOURCE_ROOT, 'third_party', 'colorama', 'src')
-
-with host_paths.SysPath(_COLORAMA_PATH, position=0):
- import colorama
-
-TEST_FAIL = logging.INFO + 3
-TEST_PASS = logging.INFO + 2
-TEST_TIME = logging.INFO + 1
-
-
-def _set_log_level(verbose_count):
- if verbose_count == -1: # Quiet
- log_level = logging.WARNING
- elif verbose_count == 0: # Default
- log_level = logging.INFO + 1
- elif verbose_count == 1:
- log_level = logging.INFO
- elif verbose_count >= 2:
- log_level = logging.DEBUG
- logging.getLogger().setLevel(log_level)
-
-
-class CustomFormatter(logging.Formatter):
- """Custom log formatter."""
- # pylint does not see members added dynamically in the constructor.
- # pylint: disable=no-member
- COLOR_MAP = {
- logging.DEBUG: colorama.Fore.CYAN + colorama.Style.DIM,
- logging.WARNING: colorama.Fore.YELLOW,
- logging.ERROR: colorama.Back.RED,
- logging.CRITICAL: colorama.Back.RED,
- TEST_PASS: colorama.Fore.GREEN + colorama.Style.BRIGHT,
- TEST_FAIL: colorama.Fore.RED + colorama.Style.BRIGHT,
- TEST_TIME: colorama.Fore.MAGENTA + colorama.Style.BRIGHT,
- }
-
- # override
- def __init__(self, color, fmt='%(threadName)-4s %(message)s'):
- logging.Formatter.__init__(self, fmt=fmt)
- self._creation_time = time.time()
- self._should_colorize = color
-
- # override
- def format(self, record):
- msg = logging.Formatter.format(self, record)
- if 'MainThread' in msg[:19]:
- msg = msg.replace('MainThread', 'Main', 1)
- timediff = time.time() - self._creation_time
-
- level_tag = record.levelname[0]
- if self._should_colorize:
- level_tag = '%s%-1s%s' % (
- self.COLOR_MAP.get(record.levelno, ''),
- level_tag, colorama.Style.RESET_ALL)
-
- return '%s %8.3fs %s' % (level_tag, timediff, msg)
-
-
-logging.addLevelName(TEST_TIME, unicode_characters.CLOCK)
-def test_time(message, *args, **kwargs):
- logger = logging.getLogger()
- if logger.isEnabledFor(TEST_TIME):
- # pylint: disable=protected-access
- logger._log(TEST_TIME, message, args, **kwargs)
-
-
-logging.addLevelName(TEST_FAIL, unicode_characters.CROSS)
-def test_fail(message, *args, **kwargs):
- logger = logging.getLogger()
- if logger.isEnabledFor(TEST_FAIL):
- # pylint: disable=protected-access
- logger._log(TEST_FAIL, message, args, **kwargs)
-
-
-logging.addLevelName(TEST_PASS, unicode_characters.CHECK)
-def test_pass(message, *args, **kwargs):
- logger = logging.getLogger()
- if logger.isEnabledFor(TEST_PASS):
- # pylint: disable=protected-access
- logger._log(TEST_PASS, message, args, **kwargs)
-
-
-def Initialize(log_level):
- logging.getLogger().handlers = []
- handler = logging.StreamHandler(stream=sys.stderr)
- logging.getLogger().addHandler(handler)
- handler.setFormatter(CustomFormatter(color=sys.stderr.isatty()))
- _set_log_level(log_level)
-
diff --git a/build/android/pylib/utils/logging_utils.py b/build/android/pylib/utils/logging_utils.py
new file mode 100644
index 0000000..082f9e8
--- /dev/null
+++ b/build/android/pylib/utils/logging_utils.py
@@ -0,0 +1,111 @@
+# Copyright 2014 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 contextlib
+import logging
+import os
+
+from pylib.constants import host_paths
+
+_COLORAMA_PATH = os.path.join(
+ host_paths.DIR_SOURCE_ROOT, 'third_party', 'colorama', 'src')
+
+with host_paths.SysPath(_COLORAMA_PATH, position=0):
+ import colorama
+
+
+class _ColorFormatter(logging.Formatter):
+ # pylint does not see members added dynamically in the constructor.
+ # pylint: disable=no-member
+ color_map = {
+ logging.DEBUG: colorama.Fore.CYAN,
+ logging.WARNING: colorama.Fore.YELLOW,
+ logging.ERROR: colorama.Fore.RED,
+ logging.CRITICAL: colorama.Back.RED,
+ }
+
+ def __init__(self, wrapped_formatter=None):
+ """Wraps a |logging.Formatter| and adds color."""
+ super(_ColorFormatter, self).__init__(self)
+ self._wrapped_formatter = wrapped_formatter or logging.Formatter()
+
+ #override
+ def format(self, record):
+ message = self._wrapped_formatter.format(record)
+ return self.Colorize(message, record.levelno)
+
+ def Colorize(self, message, log_level):
+ try:
+ return self.color_map[log_level] + message + colorama.Style.RESET_ALL
+ except KeyError:
+ return message
+
+
+class ColorStreamHandler(logging.StreamHandler):
+ """Handler that can be used to colorize logging output.
+
+ Example using a specific logger:
+
+ logger = logging.getLogger('my_logger')
+ logger.addHandler(ColorStreamHandler())
+ logger.info('message')
+
+ Example using the root logger:
+
+ ColorStreamHandler.MakeDefault()
+ logging.info('message')
+
+ """
+ def __init__(self, force_color=False):
+ super(ColorStreamHandler, self).__init__()
+ self.force_color = force_color
+ self.setFormatter(logging.Formatter())
+
+ @property
+ def is_tty(self):
+ isatty = getattr(self.stream, 'isatty', None)
+ return isatty and isatty()
+
+ #override
+ def setFormatter(self, formatter):
+ if self.force_color or self.is_tty:
+ formatter = _ColorFormatter(formatter)
+ super(ColorStreamHandler, self).setFormatter(formatter)
+
+ @staticmethod
+ def MakeDefault(force_color=False):
+ """
+ Replaces the default logging handlers with a coloring handler. To use
+ a colorizing handler at the same time as others, either register them
+ after this call, or add the ColorStreamHandler on the logger using
+ Logger.addHandler()
+
+ Args:
+ force_color: Set to True to bypass the tty check and always colorize.
+ """
+ # If the existing handlers aren't removed, messages are duplicated
+ logging.getLogger().handlers = []
+ logging.getLogger().addHandler(ColorStreamHandler(force_color))
+
+
[email protected]
+def SuppressLogging(level=logging.ERROR):
+ """Momentarilly suppress logging events from all loggers.
+
+ TODO(jbudorick): This is not thread safe. Log events from other threads might
+ also inadvertently disappear.
+
+ Example:
+
+ with logging_utils.SuppressLogging():
+ # all but CRITICAL logging messages are suppressed
+ logging.info('just doing some thing') # not shown
+ logging.critical('something really bad happened') # still shown
+
+ Args:
+ level: logging events with this or lower levels are suppressed.
+ """
+ logging.disable(level)
+ yield
+ logging.disable(logging.NOTSET)
diff --git a/build/android/pylib/utils/unicode_characters.py b/build/android/pylib/utils/unicode_characters.py
deleted file mode 100644
index 0d56077..0000000
--- a/build/android/pylib/utils/unicode_characters.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright 2017 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.
-
-"""Helper module that contains unicode character constants."""
-
-CHECK = u'\u2714'
-CLOCK = u'\u231A'
-CROSS = u'\u274C'
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 7677329a..01a0ec53 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -31,9 +31,9 @@
from devil import base_error
from devil.utils import reraiser_thread
+from devil.utils import run_tests_helper
from pylib import constants
-from pylib import logging_ext
from pylib.base import base_test_result
from pylib.base import environment_factory
from pylib.base import test_instance_factory
@@ -41,6 +41,7 @@
from pylib.results import json_results
from pylib.results import report_results
from pylib.utils import logdog_helper
+from pylib.utils import logging_utils
from py_utils import contextlib_ext
@@ -178,6 +179,7 @@
'--gs-results-bucket',
help='Google Storage bucket to upload results to.')
+
parser.add_argument(
'--output-directory',
dest='output_directory', type=os.path.realpath,
@@ -192,17 +194,20 @@
'-v', '--verbose',
dest='verbose_count', default=0, action='count',
help='Verbose level (multiple times for more)')
- parser.add_argument(
- '-q', '--quiet',
- dest='quiet', action='store_true',
- help='Option for very quiet logging.')
AddTestLauncherOptions(parser)
def ProcessCommonOptions(args):
"""Processes and handles all common options."""
- logging_ext.Initialize(-1 if args.quiet else args.verbose_count)
+ run_tests_helper.SetLogLevel(args.verbose_count, add_handler=False)
+ if args.verbose_count > 0:
+ handler = logging_utils.ColorStreamHandler()
+ else:
+ handler = logging.StreamHandler(sys.stdout)
+ handler.setFormatter(run_tests_helper.CustomFormatter())
+ logging.getLogger().addHandler(handler)
+
constants.SetBuildType(args.build_type)
if args.output_directory:
constants.SetOutputDirectory(args.output_directory)
@@ -844,6 +849,7 @@
continue
all_raw_results.append(raw_results)
+
iteration_results = base_test_result.TestRunResults()
for r in reversed(raw_results):
iteration_results.AddTestRunResults(r)
diff --git a/build/android/test_runner.pydeps b/build/android/test_runner.pydeps
index c4b3c43..573577e 100644
--- a/build/android/test_runner.pydeps
+++ b/build/android/test_runner.pydeps
@@ -163,7 +163,6 @@
pylib/local/machine/__init__.py
pylib/local/machine/local_machine_environment.py
pylib/local/machine/local_machine_junit_test_run.py
-pylib/logging_ext/__init__.py
pylib/monkey/__init__.py
pylib/monkey/monkey_test_instance.py
pylib/perf/__init__.py
@@ -183,11 +182,11 @@
pylib/utils/google_storage_helper.py
pylib/utils/instrumentation_tracing.py
pylib/utils/logdog_helper.py
+pylib/utils/logging_utils.py
pylib/utils/proguard.py
pylib/utils/repo_utils.py
pylib/utils/shared_preference_utils.py
pylib/utils/time_profile.py
-pylib/utils/unicode_characters.py
pylib/valgrind_tools.py
test_runner.py
tombstones.py