msg.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. # ex:ts=4:sw=4:sts=4:et
  2. # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
  3. """
  4. BitBake 'msg' implementation
  5. Message handling infrastructure for bitbake
  6. """
  7. # Copyright (C) 2006 Richard Purdie
  8. #
  9. # This program is free software; you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License version 2 as
  11. # published by the Free Software Foundation.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License along
  19. # with this program; if not, write to the Free Software Foundation, Inc.,
  20. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. import sys
  22. import copy
  23. import logging
  24. import collections
  25. from itertools import groupby
  26. import warnings
  27. import bb
  28. import bb.event
  29. class BBLogFormatter(logging.Formatter):
  30. """Formatter which ensures that our 'plain' messages (logging.INFO + 1) are used as is"""
  31. DEBUG3 = logging.DEBUG - 2
  32. DEBUG2 = logging.DEBUG - 1
  33. DEBUG = logging.DEBUG
  34. VERBOSE = logging.INFO - 1
  35. NOTE = logging.INFO
  36. PLAIN = logging.INFO + 1
  37. ERROR = logging.ERROR
  38. WARNING = logging.WARNING
  39. CRITICAL = logging.CRITICAL
  40. levelnames = {
  41. DEBUG3 : 'DEBUG',
  42. DEBUG2 : 'DEBUG',
  43. DEBUG : 'DEBUG',
  44. VERBOSE: 'NOTE',
  45. NOTE : 'NOTE',
  46. PLAIN : '',
  47. WARNING : 'WARNING',
  48. ERROR : 'ERROR',
  49. CRITICAL: 'ERROR',
  50. }
  51. color_enabled = False
  52. BASECOLOR, BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = list(range(29,38))
  53. COLORS = {
  54. DEBUG3 : CYAN,
  55. DEBUG2 : CYAN,
  56. DEBUG : CYAN,
  57. VERBOSE : BASECOLOR,
  58. NOTE : BASECOLOR,
  59. PLAIN : BASECOLOR,
  60. WARNING : YELLOW,
  61. ERROR : RED,
  62. CRITICAL: RED,
  63. }
  64. BLD = '\033[1;%dm'
  65. STD = '\033[%dm'
  66. RST = '\033[0m'
  67. def getLevelName(self, levelno):
  68. try:
  69. return self.levelnames[levelno]
  70. except KeyError:
  71. self.levelnames[levelno] = value = 'Level %d' % levelno
  72. return value
  73. def format(self, record):
  74. record.levelname = self.getLevelName(record.levelno)
  75. if record.levelno == self.PLAIN:
  76. msg = record.getMessage()
  77. else:
  78. if self.color_enabled:
  79. record = self.colorize(record)
  80. msg = logging.Formatter.format(self, record)
  81. if hasattr(record, 'bb_exc_formatted'):
  82. msg += '\n' + ''.join(record.bb_exc_formatted)
  83. elif hasattr(record, 'bb_exc_info'):
  84. etype, value, tb = record.bb_exc_info
  85. formatted = bb.exceptions.format_exception(etype, value, tb, limit=5)
  86. msg += '\n' + ''.join(formatted)
  87. return msg
  88. def colorize(self, record):
  89. color = self.COLORS[record.levelno]
  90. if self.color_enabled and color is not None:
  91. record = copy.copy(record)
  92. record.levelname = "".join([self.BLD % color, record.levelname, self.RST])
  93. record.msg = "".join([self.STD % color, record.msg, self.RST])
  94. return record
  95. def enable_color(self):
  96. self.color_enabled = True
  97. class BBLogFilter(object):
  98. def __init__(self, handler, level, debug_domains):
  99. self.stdlevel = level
  100. self.debug_domains = debug_domains
  101. loglevel = level
  102. for domain in debug_domains:
  103. if debug_domains[domain] < loglevel:
  104. loglevel = debug_domains[domain]
  105. handler.setLevel(loglevel)
  106. handler.addFilter(self)
  107. def filter(self, record):
  108. if record.levelno >= self.stdlevel:
  109. return True
  110. if record.name in self.debug_domains and record.levelno >= self.debug_domains[record.name]:
  111. return True
  112. return False
  113. class BBLogFilterStdErr(BBLogFilter):
  114. def filter(self, record):
  115. if not BBLogFilter.filter(self, record):
  116. return False
  117. if record.levelno >= logging.ERROR:
  118. return True
  119. return False
  120. class BBLogFilterStdOut(BBLogFilter):
  121. def filter(self, record):
  122. if not BBLogFilter.filter(self, record):
  123. return False
  124. if record.levelno < logging.ERROR:
  125. return True
  126. return False
  127. # Message control functions
  128. #
  129. loggerDefaultDebugLevel = 0
  130. loggerDefaultVerbose = False
  131. loggerVerboseLogs = False
  132. loggerDefaultDomains = []
  133. def init_msgconfig(verbose, debug, debug_domains=None):
  134. """
  135. Set default verbosity and debug levels config the logger
  136. """
  137. bb.msg.loggerDefaultDebugLevel = debug
  138. bb.msg.loggerDefaultVerbose = verbose
  139. if verbose:
  140. bb.msg.loggerVerboseLogs = True
  141. if debug_domains:
  142. bb.msg.loggerDefaultDomains = debug_domains
  143. else:
  144. bb.msg.loggerDefaultDomains = []
  145. def constructLogOptions():
  146. debug = loggerDefaultDebugLevel
  147. verbose = loggerDefaultVerbose
  148. domains = loggerDefaultDomains
  149. if debug:
  150. level = BBLogFormatter.DEBUG - debug + 1
  151. elif verbose:
  152. level = BBLogFormatter.VERBOSE
  153. else:
  154. level = BBLogFormatter.NOTE
  155. debug_domains = {}
  156. for (domainarg, iterator) in groupby(domains):
  157. dlevel = len(tuple(iterator))
  158. debug_domains["BitBake.%s" % domainarg] = logging.DEBUG - dlevel + 1
  159. return level, debug_domains
  160. def addDefaultlogFilter(handler, cls = BBLogFilter):
  161. level, debug_domains = constructLogOptions()
  162. cls(handler, level, debug_domains)
  163. #
  164. # Message handling functions
  165. #
  166. def fatal(msgdomain, msg):
  167. if msgdomain:
  168. logger = logging.getLogger("BitBake.%s" % msgdomain)
  169. else:
  170. logger = logging.getLogger("BitBake")
  171. logger.critical(msg)
  172. sys.exit(1)