BerfScene / utils /loggers /base_logger.py
3v324v23's picture
init
2f85de4
raw
history blame
9.59 kB
# python3.7
"""Contains the base class for logging.
Basically, this is an interface bridging the program and the local file system.
A logger is able to log wrapped message onto the screen and a log file.
"""
import logging
__all__ = ['BaseLogger']
class BaseLogger(object):
"""Defines the base logger.
A logger should have the following members:
(1) logger: The logger to record message.
(2) pbar: The progressive bar (shown on the screen only).
(3) pbar_kwargs: The arguments for the progressive bar.
(4) file_stream: The stream to log messages into if needed.
A logger should have the following functions:
(1) log(): The base function to log message.
(2) debug(): The function to log message with `DEBUG` level.
(3) info(): The function to log message with `INFO` level.
(4) warning(): The function to log message with `WARNING` level.
(5) warn(): Same as function `warning()`.
(6) error(): The function to log message with `ERROR` level.
(7) exception(): The function to log message with exception information.
(8) critical(): The function to log message with `CRITICAL` level.
(9) fatal(): Same as function `critical()`.
(10) print(): The function to print the message without any decoration.
(11) init_pbar(): The function to initialize the progressive bar.
(12) add_pbar_task(): The function to add a task to the progressive bar.
(13) update_pbar(): The function to update the progressive bar.
(14) close_pbar(): The function to close the progressive bar.
The logger will record log message both on screen and to file.
Args:
logger_name: Unique name for the logger. (default: `logger`)
logfile: Path to the log file. If set as `None`, the file stream
will be skipped. (default: `None`)
screen_level: Minimum level of message to log onto screen.
(default: `logging.INFO`)
file_level: Minimum level of message to log into file.
(default: `logging.DEBUG`)
indent_space: Number of spaces between two adjacent indent levels.
(default: 4)
verbose_log: Whether to log verbose message. (default: False)
"""
def __init__(self,
logger_name='logger',
logfile=None,
screen_level=logging.INFO,
file_level=logging.DEBUG,
indent_space=4,
verbose_log=False):
self.logger_name = logger_name
self.logfile = logfile
self.screen_level = screen_level
self.file_level = file_level
self.indent_space = indent_space
self.verbose_log = verbose_log
self.logger = None
self.pbar = None
self.pbar_kwargs = None
self.file_stream = None
self.warn = self.warning
self.fatal = self.critical
def __del__(self):
self.close()
def close(self):
"""Closes the logger."""
if self.file_stream is not None:
self.file_stream.close()
@property
def name(self):
"""Returns the class name of the logger."""
return self.__class__.__name__
# Log message.
def wrap_message(self, message, indent_level=0):
"""Wraps the message with indent."""
if message is None:
message = ''
assert isinstance(message, str)
assert isinstance(indent_level, int) and indent_level >= 0
if message == '':
return ''
return ' ' * (indent_level * self.indent_space) + message
def _log(self, message, **kwargs):
"""Logs wrapped message."""
raise NotImplementedError('Should be implemented in derived class!')
def _debug(self, message, **kwargs):
"""Logs wrapped message with `DEBUG` level."""
raise NotImplementedError('Should be implemented in derived class!')
def _info(self, message, **kwargs):
"""Logs wrapped message with `INFO` level."""
raise NotImplementedError('Should be implemented in derived class!')
def _warning(self, message, **kwargs):
"""Logs wrapped message with `WARNING` level."""
raise NotImplementedError('Should be implemented in derived class!')
def _error(self, message, **kwargs):
"""Logs wrapped message with `ERROR` level."""
raise NotImplementedError('Should be implemented in derived class!')
def _exception(self, message, **kwargs):
"""Logs wrapped message with exception information."""
raise NotImplementedError('Should be implemented in derived class!')
def _critical(self, message, **kwargs):
"""Logs wrapped message with `CRITICAL` level."""
raise NotImplementedError('Should be implemented in derived class!')
def _print(self, *messages, **kwargs):
"""Prints wrapped message without any decoration."""
raise NotImplementedError('Should be implemented in derived class!')
def log(self, message, indent_level=0, is_verbose=False, **kwargs):
"""Logs message.
The message is wrapped with indent, and will be disabled if `is_verbose`
is set as `True`.
"""
if is_verbose and not self.verbose_log:
return
message = self.wrap_message(message, indent_level=indent_level)
self._log(message, **kwargs)
def debug(self, message, indent_level=0, is_verbose=False, **kwargs):
"""Logs message with `DEBUG` level.
The message is wrapped with indent, and will be disabled if `is_verbose`
is set as `True`.
"""
if is_verbose and not self.verbose_log:
return
message = self.wrap_message(message, indent_level=indent_level)
self._debug(message, **kwargs)
def info(self, message, indent_level=0, is_verbose=False, **kwargs):
"""Logs message with `INFO` level.
The message is wrapped with indent, and will be disabled if `is_verbose`
is set as `True`.
"""
if is_verbose and not self.verbose_log:
return
message = self.wrap_message(message, indent_level=indent_level)
self._info(message, **kwargs)
def warning(self, message, indent_level=0, is_verbose=False, **kwargs):
"""Logs message with `WARNING` level.
The message is wrapped with indent, and will be disabled if `is_verbose`
is set as `True`.
"""
if is_verbose and not self.verbose_log:
return
message = self.wrap_message(message, indent_level=indent_level)
self._warning(message, **kwargs)
def error(self, message, indent_level=0, is_verbose=False, **kwargs):
"""Logs message with `ERROR` level.
The message is wrapped with indent, and will be disabled if `is_verbose`
is set as `True`.
"""
if is_verbose and not self.verbose_log:
return
message = self.wrap_message(message, indent_level=indent_level)
self._error(message, **kwargs)
def exception(self, message, indent_level=0, is_verbose=False, **kwargs):
"""Logs message with exception information.
The message is wrapped with indent, and will be disabled if `is_verbose`
is set as `True`.
"""
if is_verbose and not self.verbose_log:
return
message = self.wrap_message(message, indent_level=indent_level)
self._exception(message, **kwargs)
def critical(self, message, indent_level=0, is_verbose=False, **kwargs):
"""Logs message with `CRITICAL` level.
The message is wrapped with indent, and will be disabled if `is_verbose`
is set as `True`.
"""
if is_verbose and not self.verbose_log:
return
message = self.wrap_message(message, indent_level=indent_level)
self._critical(message, **kwargs)
def print(self, *messages, indent_level=0, is_verbose=False, **kwargs):
"""Prints message without any decoration.
The message is wrapped with indent, and will be disabled if `is_verbose`
is set as `True`.
"""
if is_verbose and not self.verbose_log:
return
new_messages = []
for message in messages:
new_messages.append(
self.wrap_message(message, indent_level=indent_level))
self._print(*new_messages, **kwargs)
# Progressive bar.
def init_pbar(self, leave=False):
"""Initializes the progressive bar.
Args:
leave: Whether to leave the trace of the progressive bar.
(default: False)
"""
raise NotImplementedError('Should be implemented in derived class!')
def add_pbar_task(self, name, total, **kwargs):
"""Adds a task to the progressive bar.
Args:
name: Name of the added task.
total: Total number of steps (samples) contained in the task.
**kwargs: Additional arguments.
Returns:
Task ID.
"""
raise NotImplementedError('Should be implemented in derived class!')
def update_pbar(self, task_id, advance=1):
"""Updates the progressive bar.
Args:
task_id: ID of the task to update.
advance: Number of steps advanced onto the target task. (default: 1)
"""
raise NotImplementedError('Should be implemented in derived class!')
def close_pbar(self):
"""Closes the progress bar."""
raise NotImplementedError('Should be implemented in derived class!')