summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2022-02-16 09:46:46 -0600
committerRichard Purdie <richard.purdie@linuxfoundation.org>2022-02-17 17:51:03 +0000
commitdac63330e6879a0354449c8ad52f09a888d49d27 (patch)
tree5cbb15b2c582ace3677836bdf0614e614c853e24
parent2e20effe31a904c1aa0172291124ebdcf0889598 (diff)
downloadpoky-dac63330e6879a0354449c8ad52f09a888d49d27.tar.gz
bitbake: msg: Add bb.warnonce() and bb.erroronce() log methods
This adds a log level and logging function call to use it where the warning or error will only be displayed once, regardless of how many times the message is logged. This has to be done either in the cooker or on the UI side. I've opted for the UI side since display control is really a UI issue but it uses a common library filter function to enable it which can be reused elsewhere. The knotty message displayed as the build summary is tweaked to make sense when the numbers won't match since it will still count the number of times it was logged and this is probably helpful for debugging in some cases so I've deliberately left it that way. (Bitbake rev: 7bd40e3003a043e3cb7efc276681054b563b5e7b) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> Signed-off-by: Joshua Watt <JPEWhacker@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/bb/__init__.py13
-rw-r--r--bitbake/lib/bb/msg.py32
-rw-r--r--bitbake/lib/bb/ui/knotty.py14
3 files changed, 51 insertions, 8 deletions
diff --git a/bitbake/lib/bb/__init__.py b/bitbake/lib/bb/__init__.py
index e01b8d5256..269f65edce 100644
--- a/bitbake/lib/bb/__init__.py
+++ b/bitbake/lib/bb/__init__.py
@@ -71,6 +71,13 @@ class BBLoggerMixin(object):
71 def verbnote(self, msg, *args, **kwargs): 71 def verbnote(self, msg, *args, **kwargs):
72 return self.log(logging.INFO + 2, msg, *args, **kwargs) 72 return self.log(logging.INFO + 2, msg, *args, **kwargs)
73 73
74 def warnonce(self, msg, *args, **kwargs):
75 return self.log(logging.WARNING - 1, msg, *args, **kwargs)
76
77 def erroronce(self, msg, *args, **kwargs):
78 return self.log(logging.ERROR - 1, msg, *args, **kwargs)
79
80
74Logger = logging.getLoggerClass() 81Logger = logging.getLoggerClass()
75class BBLogger(Logger, BBLoggerMixin): 82class BBLogger(Logger, BBLoggerMixin):
76 def __init__(self, name, *args, **kwargs): 83 def __init__(self, name, *args, **kwargs):
@@ -157,9 +164,15 @@ def verbnote(*args):
157def warn(*args): 164def warn(*args):
158 mainlogger.warning(''.join(args)) 165 mainlogger.warning(''.join(args))
159 166
167def warnonce(*args):
168 mainlogger.warnonce(''.join(args))
169
160def error(*args, **kwargs): 170def error(*args, **kwargs):
161 mainlogger.error(''.join(args), extra=kwargs) 171 mainlogger.error(''.join(args), extra=kwargs)
162 172
173def erroronce(*args):
174 mainlogger.erroronce(''.join(args))
175
163def fatal(*args, **kwargs): 176def fatal(*args, **kwargs):
164 mainlogger.critical(''.join(args), extra=kwargs) 177 mainlogger.critical(''.join(args), extra=kwargs)
165 raise BBHandledException() 178 raise BBHandledException()
diff --git a/bitbake/lib/bb/msg.py b/bitbake/lib/bb/msg.py
index 291b38ff7f..512ec1f5c1 100644
--- a/bitbake/lib/bb/msg.py
+++ b/bitbake/lib/bb/msg.py
@@ -30,7 +30,9 @@ class BBLogFormatter(logging.Formatter):
30 PLAIN = logging.INFO + 1 30 PLAIN = logging.INFO + 1
31 VERBNOTE = logging.INFO + 2 31 VERBNOTE = logging.INFO + 2
32 ERROR = logging.ERROR 32 ERROR = logging.ERROR
33 ERRORONCE = logging.ERROR - 1
33 WARNING = logging.WARNING 34 WARNING = logging.WARNING
35 WARNONCE = logging.WARNING - 1
34 CRITICAL = logging.CRITICAL 36 CRITICAL = logging.CRITICAL
35 37
36 levelnames = { 38 levelnames = {
@@ -42,7 +44,9 @@ class BBLogFormatter(logging.Formatter):
42 PLAIN : '', 44 PLAIN : '',
43 VERBNOTE: 'NOTE', 45 VERBNOTE: 'NOTE',
44 WARNING : 'WARNING', 46 WARNING : 'WARNING',
47 WARNONCE : 'WARNING',
45 ERROR : 'ERROR', 48 ERROR : 'ERROR',
49 ERRORONCE : 'ERROR',
46 CRITICAL: 'ERROR', 50 CRITICAL: 'ERROR',
47 } 51 }
48 52
@@ -58,7 +62,9 @@ class BBLogFormatter(logging.Formatter):
58 PLAIN : BASECOLOR, 62 PLAIN : BASECOLOR,
59 VERBNOTE: BASECOLOR, 63 VERBNOTE: BASECOLOR,
60 WARNING : YELLOW, 64 WARNING : YELLOW,
65 WARNONCE : YELLOW,
61 ERROR : RED, 66 ERROR : RED,
67 ERRORONCE : RED,
62 CRITICAL: RED, 68 CRITICAL: RED,
63 } 69 }
64 70
@@ -121,6 +127,23 @@ class BBLogFilter(object):
121 return True 127 return True
122 return False 128 return False
123 129
130class LogFilterShowOnce(logging.Filter):
131 def __init__(self):
132 self.seen_warnings = set()
133 self.seen_errors = set()
134
135 def filter(self, record):
136 msg = record.msg
137 if record.levelno == bb.msg.BBLogFormatter.WARNONCE:
138 if record.msg in self.seen_warnings:
139 return False
140 self.seen_warnings.add(record.msg)
141 if record.levelno == bb.msg.BBLogFormatter.ERRORONCE:
142 if record.msg in self.seen_errors:
143 return False
144 self.seen_errors.add(record.msg)
145 return True
146
124class LogFilterGEQLevel(logging.Filter): 147class LogFilterGEQLevel(logging.Filter):
125 def __init__(self, level): 148 def __init__(self, level):
126 self.strlevel = str(level) 149 self.strlevel = str(level)
@@ -293,10 +316,17 @@ def setLoggingConfig(defaultconfig, userconfigfile=None):
293 316
294 # Convert all level parameters to integers in case users want to use the 317 # Convert all level parameters to integers in case users want to use the
295 # bitbake defined level names 318 # bitbake defined level names
296 for h in logconfig["handlers"].values(): 319 for name, h in logconfig["handlers"].items():
297 if "level" in h: 320 if "level" in h:
298 h["level"] = bb.msg.stringToLevel(h["level"]) 321 h["level"] = bb.msg.stringToLevel(h["level"])
299 322
323 # Every handler needs its own instance of the once filter.
324 once_filter_name = name + ".showonceFilter"
325 logconfig.setdefault("filters", {})[once_filter_name] = {
326 "()": "bb.msg.LogFilterShowOnce",
327 }
328 h.setdefault("filters", []).append(once_filter_name)
329
300 for l in logconfig["loggers"].values(): 330 for l in logconfig["loggers"].values():
301 if "level" in l: 331 if "level" in l:
302 l["level"] = bb.msg.stringToLevel(l["level"]) 332 l["level"] = bb.msg.stringToLevel(l["level"])
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
index 484545a684..8b98da1771 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -647,7 +647,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
647 if isinstance(event, logging.LogRecord): 647 if isinstance(event, logging.LogRecord):
648 lastprint = time.time() 648 lastprint = time.time()
649 printinterval = 5000 649 printinterval = 5000
650 if event.levelno >= bb.msg.BBLogFormatter.ERROR: 650 if event.levelno >= bb.msg.BBLogFormatter.ERRORONCE:
651 errors = errors + 1 651 errors = errors + 1
652 return_value = 1 652 return_value = 1
653 elif event.levelno == bb.msg.BBLogFormatter.WARNING: 653 elif event.levelno == bb.msg.BBLogFormatter.WARNING:
@@ -661,10 +661,10 @@ def main(server, eventHandler, params, tf = TerminalFilter):
661 continue 661 continue
662 662
663 # Prefix task messages with recipe/task 663 # Prefix task messages with recipe/task
664 if event.taskpid in helper.pidmap and event.levelno != bb.msg.BBLogFormatter.PLAIN: 664 if event.taskpid in helper.pidmap and event.levelno not in [bb.msg.BBLogFormatter.PLAIN, bb.msg.BBLogFormatter.WARNONCE, bb.msg.BBLogFormatter.ERRORONCE]:
665 taskinfo = helper.running_tasks[helper.pidmap[event.taskpid]] 665 taskinfo = helper.running_tasks[helper.pidmap[event.taskpid]]
666 event.msg = taskinfo['title'] + ': ' + event.msg 666 event.msg = taskinfo['title'] + ': ' + event.msg
667 if hasattr(event, 'fn'): 667 if hasattr(event, 'fn') and event.levelno not in [bb.msg.BBLogFormatter.WARNONCE, bb.msg.BBLogFormatter.ERRORONCE]:
668 event.msg = event.fn + ': ' + event.msg 668 event.msg = event.fn + ': ' + event.msg
669 logging.getLogger(event.name).handle(event) 669 logging.getLogger(event.name).handle(event)
670 continue 670 continue
@@ -875,11 +875,11 @@ def main(server, eventHandler, params, tf = TerminalFilter):
875 for failure in taskfailures: 875 for failure in taskfailures:
876 summary += "\n %s" % failure 876 summary += "\n %s" % failure
877 if warnings: 877 if warnings:
878 summary += pluralise("\nSummary: There was %s WARNING message shown.", 878 summary += pluralise("\nSummary: There was %s WARNING message.",
879 "\nSummary: There were %s WARNING messages shown.", warnings) 879 "\nSummary: There were %s WARNING messages.", warnings)
880 if return_value and errors: 880 if return_value and errors:
881 summary += pluralise("\nSummary: There was %s ERROR message shown, returning a non-zero exit code.", 881 summary += pluralise("\nSummary: There was %s ERROR message, returning a non-zero exit code.",
882 "\nSummary: There were %s ERROR messages shown, returning a non-zero exit code.", errors) 882 "\nSummary: There were %s ERROR messages, returning a non-zero exit code.", errors)
883 if summary and params.options.quiet == 0: 883 if summary and params.options.quiet == 0:
884 print(summary) 884 print(summary)
885 885