182 lines
5.1 KiB
Python
182 lines
5.1 KiB
Python
import logging
|
|
import os
|
|
import sys
|
|
import traceback
|
|
from colorlog import ColoredFormatter
|
|
|
|
|
|
FORMATTER_STREAM = ColoredFormatter(
|
|
"%(asctime)s %(log_color)s%(levelname)-.1s[%(name)s] %(message)s%(reset)s")
|
|
FORMATTER_FILE = logging.Formatter("%(asctime)s %(levelname)-.1s. %(message)s")
|
|
|
|
VERBOSITY_V = 10
|
|
VERBOSITY_VV = 100
|
|
VERBOSITY_VVV = 1000
|
|
|
|
|
|
def touch(filepath):
|
|
'''
|
|
Behaves similarly as `touch` command in Linux system.
|
|
Creates an empty file.
|
|
'''
|
|
try:
|
|
os.makedirs(os.path.dirname(filepath), exist_ok=True)
|
|
open(filepath, 'a').close()
|
|
return True
|
|
except BaseException:
|
|
pass
|
|
return False
|
|
|
|
|
|
def get_func_name(offset=0):
|
|
"""
|
|
Returns the name of the caller function name.
|
|
Offset counts the recursion - for example, offset=1 means the caller of the caller.
|
|
"""
|
|
return sys._getframe(1+offset).f_code.co_name
|
|
|
|
|
|
class DummyLogger():
|
|
'''
|
|
DummyLogger does not do anything.
|
|
'''
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
def get_verbosity_value(self) -> int:
|
|
return 0
|
|
|
|
def set_verbosity(self, verbosity: int):
|
|
pass
|
|
|
|
def set_log_output_filepath(self, filepath: str, level=logging.DEBUG):
|
|
pass
|
|
|
|
def debugging_on(self):
|
|
pass
|
|
|
|
def debugging_off(self):
|
|
pass
|
|
|
|
def info(self, msg=""):
|
|
pass
|
|
|
|
def error(self, msg=""):
|
|
pass
|
|
|
|
def warn(self, msg=""):
|
|
pass
|
|
|
|
def debug(self, msg="", verbosity=VERBOSITY_V):
|
|
pass
|
|
|
|
def critical(self, msg=""):
|
|
pass
|
|
|
|
|
|
class Logger(DummyLogger):
|
|
'''
|
|
Logger with specific format
|
|
'''
|
|
|
|
def __init__(
|
|
self,
|
|
name: str = "default",
|
|
filepath: str = "",
|
|
verbosity: int = VERBOSITY_V,
|
|
stream_lvl=logging.INFO,
|
|
file_lvl=logging.DEBUG
|
|
):
|
|
self.verbosity = verbosity
|
|
self.logger = logging.getLogger(name)
|
|
self.logger.setLevel(logging.DEBUG)
|
|
|
|
self.__streamHandler = logging.StreamHandler()
|
|
self.__streamHandler.setLevel(stream_lvl)
|
|
self.__streamHandler.setFormatter(FORMATTER_STREAM)
|
|
self.logger.addHandler(self.__streamHandler)
|
|
|
|
self.__fileHandler = None
|
|
if filepath and touch(filepath):
|
|
file_handler = logging.FileHandler(filepath)
|
|
file_handler.setLevel(file_lvl)
|
|
file_handler.setFormatter(FORMATTER_FILE)
|
|
self.__fileHandler = file_handler
|
|
self.logger.addHandler(self.__fileHandler)
|
|
|
|
self.logger.debug("log for {} started".format(name))
|
|
self.logger.info("log output filepath: {}".format(filepath))
|
|
|
|
def get_verbosity_value(self) -> int:
|
|
return self.verbosity
|
|
|
|
def set_verbosity(self, verbosity: int):
|
|
self.verbosity = verbosity
|
|
|
|
def set_log_output_filepath(self, filepath: str, level=logging.DEBUG):
|
|
# remove prior one if any, only one handler would be allowed at a time
|
|
if self.__fileHandler is not None:
|
|
self.logger.removeHandler(self.__fileHandler)
|
|
self.__fileHandler.close()
|
|
if filepath and touch(filepath):
|
|
file_handler = logging.FileHandler(filepath)
|
|
file_handler.setLevel(level)
|
|
file_handler.setFormatter(FORMATTER_FILE)
|
|
self.__fileHandler = file_handler
|
|
self.logger.addHandler(self.__fileHandler)
|
|
|
|
def debugging_on(self):
|
|
self.__streamHandler.setLevel(logging.DEBUG)
|
|
self.logger.info(
|
|
"debug msg printing is on, verbosity: {}".format(self.verbosity))
|
|
|
|
def debugging_off(self):
|
|
self.__streamHandler.setLevel(logging.INFO)
|
|
self.logger.info("debug msg printing is off")
|
|
|
|
def info(self, msg="", verbosity: int = VERBOSITY_V):
|
|
'''
|
|
Showing info message.
|
|
@param msg: the message
|
|
@param verbosity: the higher the number is, the less important it is.
|
|
'''
|
|
if verbosity > self.verbosity:
|
|
return
|
|
self.logger.info("[{}] {}".format(get_func_name(offset=1), msg))
|
|
|
|
def warn(self, msg="", verbosity: int = VERBOSITY_V):
|
|
'''
|
|
Showing warning message.
|
|
@param msg: the message
|
|
@param verbosity: the higher the number is, the less important it is.
|
|
'''
|
|
if verbosity > self.verbosity:
|
|
return
|
|
self.logger.warning("[{}] {}".format(get_func_name(offset=1), msg))
|
|
|
|
def debug(self, msg: str = "", verbosity: int = VERBOSITY_V):
|
|
'''
|
|
Showing debug message.
|
|
@param msg: the message
|
|
@param verbosity: the higher the number is, the less important it is.
|
|
'''
|
|
if verbosity > self.verbosity:
|
|
return
|
|
self.logger.debug("[{}] {}".format(get_func_name(offset=1), msg))
|
|
|
|
def error(self, msg=""):
|
|
'''
|
|
Showing error message.
|
|
@param msg: the message
|
|
'''
|
|
self.logger.error("[{}] {}".format(get_func_name(offset=1), msg))
|
|
self.logger.error(traceback.format_exc())
|
|
|
|
def critical(self, msg=""):
|
|
'''
|
|
Showing critical message.
|
|
@param msg: the message
|
|
'''
|
|
self.logger.critical("[{}] {}".format(get_func_name(offset=1), msg))
|