• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2014 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import contextlib
6import logging
7import os
8
9from pylib.constants import host_paths
10
11_COLORAMA_PATH = os.path.join(
12    host_paths.DIR_SOURCE_ROOT, 'third_party', 'colorama', 'src')
13
14with host_paths.SysPath(_COLORAMA_PATH):
15  import colorama
16
17class ColorStreamHandler(logging.StreamHandler):
18  """Handler that can be used to colorize logging output.
19
20  Example using a specific logger:
21
22    logger = logging.getLogger('my_logger')
23    logger.addHandler(ColorStreamHandler())
24    logger.info('message')
25
26  Example using the root logger:
27
28    ColorStreamHandler.MakeDefault()
29    logging.info('message')
30
31  """
32  # pylint does not see members added dynamically in the constructor.
33  # pylint: disable=no-member
34  color_map = {
35    logging.DEBUG: colorama.Fore.CYAN,
36    logging.WARNING: colorama.Fore.YELLOW,
37    logging.ERROR: colorama.Fore.RED,
38    logging.CRITICAL: colorama.Back.RED + colorama.Style.BRIGHT,
39  }
40
41  def __init__(self, force_color=False):
42    super(ColorStreamHandler, self).__init__()
43    self.force_color = force_color
44
45  @property
46  def is_tty(self):
47    isatty = getattr(self.stream, 'isatty', None)
48    return isatty and isatty()
49
50  #override
51  def format(self, record):
52    message = logging.StreamHandler.format(self, record)
53    if self.force_color or self.is_tty:
54      return self.Colorize(message, record.levelno)
55    return message
56
57  def Colorize(self, message, log_level):
58    try:
59      return self.color_map[log_level] + message + colorama.Style.RESET_ALL
60    except KeyError:
61      return message
62
63  @staticmethod
64  def MakeDefault(force_color=False):
65     """
66     Replaces the default logging handlers with a coloring handler. To use
67     a colorizing handler at the same time as others, either register them
68     after this call, or add the ColorStreamHandler on the logger using
69     Logger.addHandler()
70
71     Args:
72       force_color: Set to True to bypass the tty check and always colorize.
73     """
74     # If the existing handlers aren't removed, messages are duplicated
75     logging.getLogger().handlers = []
76     logging.getLogger().addHandler(ColorStreamHandler(force_color))
77
78
79@contextlib.contextmanager
80def SuppressLogging(level=logging.ERROR):
81  """Momentarilly suppress logging events from all loggers.
82
83  TODO(jbudorick): This is not thread safe. Log events from other threads might
84  also inadvertently dissapear.
85
86  Example:
87
88    with logging_utils.SuppressLogging():
89      # all but CRITICAL logging messages are suppressed
90      logging.info('just doing some thing') # not shown
91      logging.critical('something really bad happened') # still shown
92
93  Args:
94    level: logging events with this or lower levels are suppressed.
95  """
96  logging.disable(level)
97  yield
98  logging.disable(logging.NOTSET)
99