Source code for smif.cli.log

import datetime
import logging
import logging.config
from collections import OrderedDict


# Make profiling methods available through the logger
[docs] def profiling_start(self, operation, key): time_placeholder = datetime.time(0, 0) level = sum( log[1]["stop"] == time_placeholder for log in logging.Logger._profile.items() ) logging.Logger._profile[(operation, key)] = { "start": datetime.datetime.now(), "stop": time_placeholder, "level": level, }
[docs] def profiling_stop(self, operation, key): logging.Logger._profile[(operation, key)]["stop"] = datetime.datetime.now()
[docs] def summary(self, *args, **kws): if self.isEnabledFor(logging.INFO): summary = [] columns = [30, 80, 12] column = ( "{:" + str(columns[0]) + "s}" + "{:" + str(columns[1]) + "s}" + "{:" + str(columns[2]) + "s}" ) level_width = ( max([profile["level"] for profile in logging.Logger._profile.values()]) * 2 ) total_width = sum(columns) + level_width # header summary.append( ("{:*^" + str(total_width) + "s}").format(" Modelrun time profile ") ) summary.append(column.format("Function", "Operation", "Duration [hh:mm:ss]")) summary.append("*" * total_width) # body for profile in logging.Logger._profile.keys(): # calculate time diff profile_data = logging.Logger._profile[profile] diff = profile_data["stop"] - profile_data["start"] s = diff.total_seconds() time_spent = "{:02d}:{:02d}:{:05.2f}".format( int(s // 3600), int(s % 3600 // 60), s % 60 ) # trunctuate long lines if len(profile[0]) > columns[0] - 2: func = profile[0][: columns[0] - 3] + ".." else: func = profile[0] if len(profile[1]) > columns[1] - 2: op = profile[1][: columns[1] - 3] + ".." else: op = profile[1] summary.append( profile_data["level"] * "| " + column.format(func, op, time_spent) ) # footer summary.append("*" * total_width) for entry in summary: self._log(logging.INFO, entry, args)
[docs] def setup_logging(loglevel): config = { "version": 1, "formatters": { "default": { "format": "%(asctime)s %(name)-12s: %(levelname)-8s %(message)s" }, "message": {"format": "\033[1;34m%(levelname)-8s\033[0m %(message)s"}, }, "handlers": { "file": { "class": "logging.FileHandler", "level": "DEBUG", "formatter": "default", "filename": "smif.log", "mode": "a", "encoding": "utf-8", }, "stream": { "class": "logging.StreamHandler", "formatter": "message", "level": "DEBUG", }, }, "root": {"handlers": ["file", "stream"], "level": "DEBUG"}, # disable_existing_loggers defaults to True, which causes problems with class/module # -specific loggers, especially in unit tests when this method might be called multiple # times "disable_existing_loggers": False, } if loglevel is None: config["root"]["level"] = logging.WARNING elif loglevel == 1: config["root"]["level"] = logging.INFO else: config["root"]["level"] = logging.DEBUG logging.config.dictConfig(config) logging.debug("Debug logging enabled.")
logging.Logger.profiling_start = profiling_start logging.Logger.profiling_stop = profiling_stop logging.Logger.summary = summary logging.Logger._profile = OrderedDict()