[elbe-devel] [PATCH 02/32] log.py - New logging system

dion at linutronix.de dion at linutronix.de
Fri Jun 14 22:13:16 CEST 2019


From: Olivier Dion <dion at linutronix.de>

The new ELBE logging system will be using the Python standard
_logging_ module.

The _logging_ module is line oriented and module oriented.  What it
means is that seperated modules should have seperated _logger_ object.

This is not working well with ELBE.  Thus, the _logging_ module has
being wrapped in "log.py".

* Block message

  Logged message are format in _block_.  A block is composed of 3
  parts.

    - Header (optional)
    - Message
    - Footer (optional)

  Headers are underline by '=' and footers are overline by '-'.

  A block's message can also be marked to be verbatim.  In that case,
  the message is enclosed by ">>>>>\n" and "<<<<<".

** Example

   ```````````````````````````````````````````````````````````````````
   log.debug("My very very very long message\n", verbatim=True,
             header="This is a header",
             footer="Here's my footer")
   ```````````````````````````````````````````````````````````````````

   Will result in the following message to be log:
   ```````````````````````````````````````````````````````````````````
   This is a header
   ================
   >>>>>
   My very very very long message
   <<<<<
   ----------------
   Here's my footer
   ```````````````````````````````````````````````````````````````````

* Log Level

  There's not difference between log levels.  At least not in the
  formating of a message.  Log levels exist only to filter different
  messages.

* Redirection

  There's 3 modes of redirection of the logged messages.  Only one of
  them can be choose at a time.

** File

   Using 'log.new(filename)', the log object will create a new 'file
   handler' at 'filename'.  All consequent messages send to that log
   will be write to 'filename'.  'log::new' is often used when opening
   a project, since it's at this moment that we know the build
   directory of that project.

** Stdout

   Using 'log.stdout()' will redirect all further messages to the
   default 'stream handler' of the process.

** Null

   Using 'log.null()' will redirect all further messages to
   "/dev/null".

* elbe-report

  The 'log' object is reserved for logging to "log.txt".  To log to
  the "elbe-report.txt", use the 'report' object.

** Example

   ``````````````````````````````````````````````````````````````````
   from elbepack.log import log, report
   log.new("/var/cache/elbe/buildir-id/log.txt")
   report.stdout()
   log.info("This will log to log.txt")
   report.info("This will log to stdout")
   report.new("/var/cache/elbe/buildir-id/elbe-report.txt")
   report.critical("This will log to elbe-report.txt")
   ``````````````````````````````````````````````````````````````````

Signed-off-by: Olivier Dion <dion at linutronix.de>
---
 elbepack/log.py | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)
 create mode 100644 elbepack/log.py

diff --git a/elbepack/log.py b/elbepack/log.py
new file mode 100644
index 00000000..6188e163
--- /dev/null
+++ b/elbepack/log.py
@@ -0,0 +1,105 @@
+# ELBE - Debian Based Embedded Rootfilesystem Builder
+# Copyright (c) 2019 Olivier Dion <dion at linutronix.de>
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+import os
+import logging
+import logging.config
+
+raw_fmt = logging.Formatter("\n%(message)s")
+
+class log:
+
+    log = None
+    filename = None
+    handler = None
+
+    @classmethod
+    def fmt_footer(cls, footer, c):
+        if footer:
+            return "\n%s\n%s" % ((c * len(footer)), footer)
+        return ""
+
+    @classmethod
+    def fmt_header(cls, header, c, end="\n"):
+        if header:
+            return "%s\n%s%s" % (header, (c * len(header)), end)
+        return ""
+
+    @classmethod
+    def fmt_msg(cls, msg, header, footer, verbatim):
+        if verbatim:
+            msg = ">>>>>\n%s<<<<<" % msg
+        return "%s%s%s" % (cls.fmt_header(header, '='),
+                           msg,
+                           cls.fmt_footer(footer, '-'))
+
+    @classmethod
+    def new(cls, filename):
+        cls.filename = filename
+        cls.log = logging.getLogger(cls.__name__)
+        cls.log.setLevel(logging.DEBUG)
+        cls.log.propagate = False
+        if cls.handler is not None:
+            cls.log.removeHandler(cls.handler)
+        cls.handler = logging.FileHandler(cls.filename)
+        cls.handler.setFormatter(raw_fmt)
+        cls.log.addHandler(cls.handler)
+
+    @classmethod
+    def stdout(cls):
+        cls.filename = "STDOUT"
+        cls.log = logging.getLogger(cls.__name__)
+        cls.log.setLevel(logging.DEBUG)
+        cls.log.propagate = False
+        if cls.handler is not None:
+            cls.log.removeHandler(cls.handler)
+        cls.handler = logging.StreamHandler()
+        cls.log.addHandler(cls.handler)
+
+    @classmethod
+    def null(cls):
+        cls.filename = "/dev/null"
+        cls.log = logging.getLogger(cls.__name__)
+        cls.log.setLevel(logging.DEBUG)
+        cls.log.propagate = False
+        if cls.handler is not None:
+            cls.log.removeHandler(cls.handler)
+        cls.handler = logging.FileHandler("/dev/null")
+        cls.log.addHandler(cls.handler)
+
+    @classmethod
+    def h1(cls, header):
+        cls.info("%s" % (log.fmt_header(header, '=', end="")))
+
+    @classmethod
+    def h2(cls, header, msg=""):
+        cls.info("%s" % (log.fmt_header(header, '-', end="")))
+
+    @classmethod
+    def debug(cls, msg, header="", footer="", verbatim=False):
+        cls.log.debug(cls.fmt_msg(msg, header, footer, verbatim))
+
+    @classmethod
+    def info(cls, msg, header="", footer="", verbatim=False):
+        cls.log.info(cls.fmt_msg(msg, header, footer, verbatim))
+
+    @classmethod
+    def warning(cls, msg, header="", footer="", verbatim=False):
+        cls.log.warning(cls.fmt_msg(msg, header, footer, verbatim))
+
+    @classmethod
+    def error(cls, msg, header="", footer="", verbatim=False):
+        cls.log.error(cls.fmt_msg(msg, header, footer, verbatim))
+
+    @classmethod
+    def critical(cls, msg, header="", footer="", verbatim=False):
+        cls.log.critical(cls.fmt_msg(msg, header, footer, verbatim))
+
+    @classmethod
+    def exception(cls, msg, header="", footer="", verbatim=False):
+        cls.log.exception(cls.fmt_msg(msg, header, footer, verbatim))
+
+class report(log):
+    pass
-- 
2.11.0




More information about the elbe-devel mailing list