[bitbake-devel,08/15] bitbake: lib/bb/msg.py: Add helper to set logging config

Submitted by Joshua Watt on March 9, 2020, 4:33 p.m. | Patch ID: 170901

Details

Message ID 20200309163353.15362-9-JPEWhacker@gmail.com
State New
Headers show

Commit Message

Joshua Watt March 9, 2020, 4:33 p.m.
Adds a helper function to setup the structure logging information in
bitbake. The helper function takes a default configuration and an
optional path to a user config file that can be merged into the default.

Signed-off-by: Joshua Watt <JPEWhacker@gmail.com>
---
 bitbake/lib/bb/msg.py | 93 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)

Patch hide | download patch | download mbox

diff --git a/bitbake/lib/bb/msg.py b/bitbake/lib/bb/msg.py
index cab079e333..6259af037f 100644
--- a/bitbake/lib/bb/msg.py
+++ b/bitbake/lib/bb/msg.py
@@ -13,6 +13,7 @@  Message handling infrastructure for bitbake
 import sys
 import copy
 import logging
+import logging.config
 from itertools import groupby
 import bb
 import bb.event
@@ -227,3 +228,95 @@  def has_console_handler(logger):
             if handler.stream in [sys.stderr, sys.stdout]:
                 return True
     return False
+
+def setLoggingConfig(defaultconfig, userconfigfile=None):
+    logconfig = copy.deepcopy(defaultconfig)
+
+    if userconfigfile:
+        with open(userconfigfile, 'r') as f:
+            if userconfigfile.endswith('.yml') or userconfigfile.endswith('.yaml'):
+                import yaml
+                userconfig = yaml.load(f)
+            elif userconfigfile.endswith('.json') or userconfigfile.endswith('.cfg'):
+                import json
+                userconfig = json.load(f)
+            else:
+                raise BaseException("Unrecognized file format: %s" % userconfigfile)
+
+            if userconfig.get('bitbake_merge', True):
+                # Merge config with the default config
+                if userconfig.get('version') != logconfig['version']:
+                    raise BaseException("Bad user configuration version. Expected %r, got %r" % (logconfig['version'], userconfig.get('version')))
+
+                # Set some defaults to make merging easier
+                userconfig.setdefault("loggers", {})
+
+                # If a handler, formatter, or filter is defined in the user
+                # config, it will replace an existing one in the default config
+                for k in ("handlers", "formatters", "filters"):
+                    logconfig.setdefault(k, {}).update(userconfig.get(k, {}))
+
+                seen_loggers = set()
+                for name, l in logconfig["loggers"].items():
+                    # If the merge option is set, merge the handlers and
+                    # filters. Otherwise, if it is False, this logger won't get
+                    # add to the set of seen loggers and will replace the
+                    # existing one
+                    if l.get('bitbake_merge', True):
+                        ulogger = userconfig["loggers"].setdefault(name, {})
+                        ulogger.setdefault("handlers", [])
+                        ulogger.setdefault("filters", [])
+
+                        # Merge lists
+                        l.setdefault("handlers", []).extend(ulogger["handlers"])
+                        l.setdefault("filters", []).extend(ulogger["filters"])
+
+                        # Replace other properties if present
+                        if "level" in ulogger:
+                            l["level"] = ulogger["level"]
+
+                        if "propagate" in ulogger:
+                            l["propagate"] = ulogger["propagate"]
+
+                        seen_loggers.add(name)
+
+                # Add all loggers present in the user config, but not any that
+                # have already been processed
+                for name in set(userconfig["loggers"].keys()) - seen_loggers:
+                    logconfig["loggers"][name] = userconfig["loggers"][name]
+
+            else:
+                # Replace the entire default config
+                logconfig = userconfig
+
+    # Convert all level parameters to integers in case users want to use the
+    # bitbake defined level names
+    for h in logconfig["handlers"].values():
+        if "level" in h:
+            h["level"] = bb.msg.stringToLevel(h["level"])
+
+    for l in logconfig["loggers"].values():
+        if "level" in l:
+            l["level"] = bb.msg.stringToLevel(l["level"])
+
+    logging.config.dictConfig(logconfig)
+
+    # The user may have specified logging domains they want at a higher debug
+    # level than the standard.
+    for name, l in logconfig["loggers"].items():
+        if not name.startswith("BitBake."):
+            continue
+
+        if not "level" in l:
+            continue
+
+        curlevel = bb.msg.loggerDefaultDomains.get(name)
+        # Note: level parameter should already be a int because of conversion
+        # above
+        newlevel = int(l["level"])
+        if curlevel is None or newlevel < curlevel:
+            bb.msg.loggerDefaultDomains[name] = newlevel
+
+        # TODO: I don't think that setting the global log level should be necessary
+        #if newlevel < bb.msg.loggerDefaultLogLevel:
+        #    bb.msg.loggerDefaultLogLevel = newlevel