import math import logging from logging.handlers import WatchedFileHandler import datetime as dt import urllib3 from helpers.singleton import singleton @singleton class Logging: """ Creates the logger singleton to be used across the entire project """ logger = None current_step = None start_time = None total_steps = None desc = None verbosity = 0 def __init__(self, logger_name): # disable HTTPS warnings urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) logging.getLogger('urllib3').setLevel(logging.CRITICAL) self.logger = logging.getLogger(logger_name) self.logger.propagate = False def add_stdout_handler(self): """ Create, format & add the handler that will log to standard output """ handler = logging.StreamHandler() handler.setLevel(self.logger.level) formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s', "%Y-%m-%d %H:%M:%S") handler.setFormatter(formatter) self.logger.addHandler(handler) def add_file_handler(self, log_file): """ Create, format & add the handler that will log to the log file """ handler = WatchedFileHandler(log_file) handler.setLevel(self.logger.level) formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s', "%Y-%m-%d %H:%M:%S") handler.setFormatter(formatter) self.logger.addHandler(handler) def init_ticker(self, total_steps=None, desc=None): """ Initialize a ticker. Warning: this method is not independant. Call it only one at a time :param total_steps: number of total step :param desc: description of the ticker """ self.total_steps = total_steps self.start_time = dt.datetime.today().timestamp() self.desc = desc self.current_step = 0 def tick(self): """ Increment the number of tick """ self.current_step += 1 if self.verbosity >= 5: should_log = True else: should_log = self.current_step % max(1, int(math.pow(10, (6 - self.verbosity)))) == 0 or \ self.current_step == self.total_steps if should_log: # avoid a division by zero time_diff = max(float(1), float(dt.datetime.today().timestamp() - self.start_time)) ticks_per_second = "{:,}".format(round(float(self.current_step) / time_diff)) self.logger.info(self.desc + " [" + ticks_per_second + " eps. - " + '{:.2f}' .format(round(float(self.current_step) / float(self.total_steps) * 100, 2)) + "% done" + "]") def print_generic_intro(self, title): """ Display title in log :param title: title to display """ self.logger.info("") self.logger.info("===== " + title + " =====")