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()