> -----Original Message----- > From: Bruce Richardson <bruce.richard...@intel.com> > Sent: Thursday, September 8, 2022 10:31 AM > To: Juraj Linkeš <juraj.lin...@pantheon.tech> > Cc: tho...@monjalon.net; david.march...@redhat.com; > ronan.rand...@intel.com; honnappa.nagaraha...@arm.com; > ohily...@iol.unh.edu; lijuan...@intel.com; dev@dpdk.org > Subject: Re: [PATCH v4 3/9] dts: add basic logging facility > > On Fri, Jul 29, 2022 at 10:55:44AM +0000, Juraj Linkeš wrote: > > The logging module provides loggers distinguished by two attributes, a > > custom format and a verbosity switch. The loggers log to both console > > and more verbosely to files. > > > > Signed-off-by: Owen Hilyard <ohily...@iol.unh.edu> > > Signed-off-by: Juraj Linkeš <juraj.lin...@pantheon.tech> > > Few small comments inline below. > > Thanks, > /Bruce > > > --- > > dts/framework/__init__.py | 3 + > > dts/framework/logger.py | 124 > ++++++++++++++++++++++++++++++++++++++ > > 2 files changed, 127 insertions(+) > > create mode 100644 dts/framework/__init__.py create mode 100644 > > dts/framework/logger.py > > > > diff --git a/dts/framework/__init__.py b/dts/framework/__init__.py new > > file mode 100644 index 0000000000..3c30bccf43 > > --- /dev/null > > +++ b/dts/framework/__init__.py > > @@ -0,0 +1,3 @@ > > +# SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2022 > > +PANTHEON.tech s.r.o. > > +# > > diff --git a/dts/framework/logger.py b/dts/framework/logger.py new > > file mode 100644 index 0000000000..920ce0fb15 > > --- /dev/null > > +++ b/dts/framework/logger.py > > @@ -0,0 +1,124 @@ > > +# SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2010-2014 > > +Intel Corporation # Copyright(c) 2022 PANTHEON.tech s.r.o. > > +# Copyright(c) 2022 University of New Hampshire # > > + > > +import logging > > +import os.path > > +from typing import TypedDict > > + > > +""" > > +DTS logger module with several log level. DTS framework and TestSuite > > +log will saved into different log files. > > +""" > > +verbose = False > > +date_fmt = "%d/%m/%Y %H:%M:%S" > > Please use Year-month-day ordering for dates, since it's unambiguous - as well > as being an ISO standard date format. (ISO 8601) >
Ack. > > +stream_fmt = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" > > + > > + > > +class LoggerDictType(TypedDict): > > + logger: "DTSLOG" > > + name: str > > + node: str > > + > > + > > +# List for saving all using loggers > > +global Loggers > > +Loggers: list[LoggerDictType] = [] > > + > > + > > +def set_verbose() -> None: > > + global verbose > > + verbose = True > > + > > Is there a need for a clear_verbose() or "set_not_verbose()" API? > No, this is used with a comman-line option or env variable which just sets it once and that's it. > > + > > +class DTSLOG(logging.LoggerAdapter): > > + """ > > + DTS log class for framework and testsuite. > > + """ > > + > > + node: str > > + logger: logging.Logger > > + sh: logging.StreamHandler > > + fh: logging.FileHandler > > + verbose_handler: logging.FileHandler > > + > > + def __init__(self, logger: logging.Logger, node: str = "suite"): > > + global log_dir > > + > > + self.logger = logger > > + self.logger.setLevel(1) # 1 means log everything > > + > > + self.node = node > > + > > + # add handler to emit to stdout > > + sh = logging.StreamHandler() > > + sh.setFormatter(logging.Formatter(stream_fmt, date_fmt)) > > + > > + sh.setLevel(logging.DEBUG) # file handler default level > > + global verbose > > + if verbose is True: > > + sh.setLevel(logging.DEBUG) > > + else: > > + sh.setLevel(logging.INFO) # console handler defaultlevel > > The global should be defined at the top of the function. > Looks like some of the setlevel calls are unnecessary; two should be enough > rather than three. For example: > > sh.setLevel(logging.INFO) > if verbose: > sh.setLevel(logging.DEGUG) > Ack. > > + > > + self.logger.addHandler(sh) > > + self.sh = sh > > + > > + if not os.path.exists("output"): > > + os.mkdir("output") > > + > > + fh = logging.FileHandler(f"output/{node}.log") > > + fh.setFormatter( > > + logging.Formatter( > > + fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s", > > + datefmt=date_fmt, > > + ) > > + ) > > + > > + fh.setLevel(1) # We want all the logs we can get in the file > > + self.logger.addHandler(fh) > > + self.fh = fh > > + > > + # This outputs EVERYTHING, intended for post-mortem debugging > > + # Also optimized for processing via AWK (awk -F '|' ...) > > + verbose_handler = logging.FileHandler(f"output/{node}.verbose.log") > > + verbose_handler.setFormatter( > > + logging.Formatter( > > + > fmt="%(asctime)s|%(name)s|%(levelname)s|%(pathname)s|%(lineno)d|%(funcN > ame)s|" > > + "%(process)d|%(thread)d|%(threadName)s|%(message)s", > > + datefmt=date_fmt, > > + ) > > + ) > > + > > + verbose_handler.setLevel(1) # We want all the logs we can get in > > the file > > + self.logger.addHandler(verbose_handler) > > + self.verbose_handler = verbose_handler > > + > > + super(DTSLOG, self).__init__(self.logger, > > + dict(node=self.node)) > > + > > + def logger_exit(self) -> None: > > + """ > > + Remove stream handler and logfile handler. > > + """ > > + for handler in (self.sh, self.fh, self.verbose_handler): > > + handler.flush() > > + self.logger.removeHandler(handler) > > + > > + > > +def getLogger(name: str, node: str = "suite") -> DTSLOG: > > + """ > > + Get logger handler and if there's no handler for specified Node will > > create > one. > > + """ > > + global Loggers > > + # return saved logger > > + logger: LoggerDictType > > + for logger in Loggers: > > + if logger["name"] == name and logger["node"] == node: > > + return logger["logger"] > > + > > + # return new logger > > + dts_logger: DTSLOG = DTSLOG(logging.getLogger(name), node) > > + Loggers.append({"logger": dts_logger, "name": name, "node": node}) > > + return dts_logger > > Looking through this patch alone, I see the "verbose" global only seems to be > used to set the log-level in the logger init function. If this is the only > use of it > across all the patches in the set, it may be more readable to change the > variable > from a "verbose" flag, to instead being a log-level one. That way your global > define is: > > log_level = logging.INFO > > and set_verbose() becomes: > > global log_level > log_level = logging.DEBUG > > thereby removing the branch from you logging init fn. > > NOTE: I have not yet had the chance to review the rest of the series, so if > verbose is used elsewhere, please ignore this comment. > It isn't. It's used solely to enable more logging, so I'll move the code around to achieve what you outlined. > > -- > > 2.30.2 > >