bench_executor.logger

This module contains the Logger class which is responsible for logging. This class is a small wrapper around the Python logging module to automatically configure the loggers and handle unittest logging.

  1#!/usr/bin/env python3
  2
  3"""
  4This module contains the Logger class which is responsible for logging.
  5This class is a small wrapper around the Python logging module to automatically
  6configure the loggers and handle unittest logging.
  7"""
  8
  9import os
 10import sys
 11import logging
 12
 13LOG_FILE_NAME = 'log.txt'
 14LOGGER_FORMAT_FILE = '[%(asctime)s] %(levelname)-8s %(message)-s'
 15LOGGER_FORMAT_CONSOLE = '%(levelname)s: %(message)s'
 16
 17
 18class Logger:
 19    """Log messages to a log file and console."""
 20
 21    def __init__(self, name: str, directory: str, verbose: bool):
 22        """Creates an instance of the Logger class.
 23
 24        During unittests, the `UNITTEST` environment variable is set which
 25        disables the console logger.
 26
 27        Parameters
 28        ----------
 29        name : str
 30            Name of the logger
 31        directory : str
 32            The path to the directory where the logs must be stored.
 33        verbose : bool
 34            Enable verbose logs
 35        """
 36        self._logger = logging.getLogger(name)
 37
 38        # Configure logging level
 39        self._verbose = verbose
 40        level = logging.INFO
 41        if self._verbose:
 42            level = logging.DEBUG
 43        self._logger.setLevel(level)
 44
 45        # Disable default handlers
 46        handlers = self._logger.handlers
 47        for h in handlers:
 48            self._logger.removeHandler(h)
 49
 50        # Configure handlers
 51        directory = os.path.abspath(directory)
 52        os.makedirs(directory, exist_ok=True)
 53        log_file = logging.FileHandler(os.path.join(directory, LOG_FILE_NAME))
 54        log_file.setLevel(logging.DEBUG)
 55        format_file = logging.Formatter(LOGGER_FORMAT_FILE)
 56        log_file.setFormatter(format_file)
 57        self._logger.addHandler(log_file)
 58
 59        # Silence console logging during unittests, logs are available in the
 60        # log file anyway
 61        if os.environ.get('UNITTEST') is None:
 62            log_console = logging.StreamHandler(sys.stderr)
 63            log_console.setLevel(logging.WARNING)
 64            format_console = logging.Formatter(LOGGER_FORMAT_CONSOLE)
 65            log_console.setFormatter(format_console)
 66            self._logger.addHandler(log_console)
 67
 68        level_name = logging.getLevelName(self._logger.level)
 69        self._logger.info(f'Logger ({level_name}) initialized for {name}')
 70
 71    def __del__(self):
 72        """Close any handlers if needed"""
 73        handlers = self._logger.handlers
 74        for h in handlers:
 75            try:
 76                h.close()
 77            except AttributeError:
 78                pass
 79            self._logger.removeHandler(h)
 80
 81    @property
 82    def verbose(self) -> bool:
 83        """Verbose logging enabled.
 84
 85        Returns
 86        -------
 87        verbose : bool
 88            Verbose logging enabled or not.
 89        """
 90        return self._verbose
 91
 92    def debug(self, msg):
 93        """Log a message with level DEBUG."""
 94        self._logger.debug(msg)
 95
 96    def info(self, msg):
 97        """Log a message with level INFO."""
 98        self._logger.info(msg)
 99
100    def warning(self, msg):
101        """Log a message with level WARNING."""
102        self._logger.warning(msg)
103
104    def error(self, msg):
105        """Log a message with level ERROR."""
106        self._logger.error(msg)
class Logger:
 19class Logger:
 20    """Log messages to a log file and console."""
 21
 22    def __init__(self, name: str, directory: str, verbose: bool):
 23        """Creates an instance of the Logger class.
 24
 25        During unittests, the `UNITTEST` environment variable is set which
 26        disables the console logger.
 27
 28        Parameters
 29        ----------
 30        name : str
 31            Name of the logger
 32        directory : str
 33            The path to the directory where the logs must be stored.
 34        verbose : bool
 35            Enable verbose logs
 36        """
 37        self._logger = logging.getLogger(name)
 38
 39        # Configure logging level
 40        self._verbose = verbose
 41        level = logging.INFO
 42        if self._verbose:
 43            level = logging.DEBUG
 44        self._logger.setLevel(level)
 45
 46        # Disable default handlers
 47        handlers = self._logger.handlers
 48        for h in handlers:
 49            self._logger.removeHandler(h)
 50
 51        # Configure handlers
 52        directory = os.path.abspath(directory)
 53        os.makedirs(directory, exist_ok=True)
 54        log_file = logging.FileHandler(os.path.join(directory, LOG_FILE_NAME))
 55        log_file.setLevel(logging.DEBUG)
 56        format_file = logging.Formatter(LOGGER_FORMAT_FILE)
 57        log_file.setFormatter(format_file)
 58        self._logger.addHandler(log_file)
 59
 60        # Silence console logging during unittests, logs are available in the
 61        # log file anyway
 62        if os.environ.get('UNITTEST') is None:
 63            log_console = logging.StreamHandler(sys.stderr)
 64            log_console.setLevel(logging.WARNING)
 65            format_console = logging.Formatter(LOGGER_FORMAT_CONSOLE)
 66            log_console.setFormatter(format_console)
 67            self._logger.addHandler(log_console)
 68
 69        level_name = logging.getLevelName(self._logger.level)
 70        self._logger.info(f'Logger ({level_name}) initialized for {name}')
 71
 72    def __del__(self):
 73        """Close any handlers if needed"""
 74        handlers = self._logger.handlers
 75        for h in handlers:
 76            try:
 77                h.close()
 78            except AttributeError:
 79                pass
 80            self._logger.removeHandler(h)
 81
 82    @property
 83    def verbose(self) -> bool:
 84        """Verbose logging enabled.
 85
 86        Returns
 87        -------
 88        verbose : bool
 89            Verbose logging enabled or not.
 90        """
 91        return self._verbose
 92
 93    def debug(self, msg):
 94        """Log a message with level DEBUG."""
 95        self._logger.debug(msg)
 96
 97    def info(self, msg):
 98        """Log a message with level INFO."""
 99        self._logger.info(msg)
100
101    def warning(self, msg):
102        """Log a message with level WARNING."""
103        self._logger.warning(msg)
104
105    def error(self, msg):
106        """Log a message with level ERROR."""
107        self._logger.error(msg)

Log messages to a log file and console.

Logger(name: str, directory: str, verbose: bool)
22    def __init__(self, name: str, directory: str, verbose: bool):
23        """Creates an instance of the Logger class.
24
25        During unittests, the `UNITTEST` environment variable is set which
26        disables the console logger.
27
28        Parameters
29        ----------
30        name : str
31            Name of the logger
32        directory : str
33            The path to the directory where the logs must be stored.
34        verbose : bool
35            Enable verbose logs
36        """
37        self._logger = logging.getLogger(name)
38
39        # Configure logging level
40        self._verbose = verbose
41        level = logging.INFO
42        if self._verbose:
43            level = logging.DEBUG
44        self._logger.setLevel(level)
45
46        # Disable default handlers
47        handlers = self._logger.handlers
48        for h in handlers:
49            self._logger.removeHandler(h)
50
51        # Configure handlers
52        directory = os.path.abspath(directory)
53        os.makedirs(directory, exist_ok=True)
54        log_file = logging.FileHandler(os.path.join(directory, LOG_FILE_NAME))
55        log_file.setLevel(logging.DEBUG)
56        format_file = logging.Formatter(LOGGER_FORMAT_FILE)
57        log_file.setFormatter(format_file)
58        self._logger.addHandler(log_file)
59
60        # Silence console logging during unittests, logs are available in the
61        # log file anyway
62        if os.environ.get('UNITTEST') is None:
63            log_console = logging.StreamHandler(sys.stderr)
64            log_console.setLevel(logging.WARNING)
65            format_console = logging.Formatter(LOGGER_FORMAT_CONSOLE)
66            log_console.setFormatter(format_console)
67            self._logger.addHandler(log_console)
68
69        level_name = logging.getLevelName(self._logger.level)
70        self._logger.info(f'Logger ({level_name}) initialized for {name}')

Creates an instance of the Logger class.

During unittests, the UNITTEST environment variable is set which disables the console logger.

Parameters
  • name (str): Name of the logger
  • directory (str): The path to the directory where the logs must be stored.
  • verbose (bool): Enable verbose logs
verbose: bool

Verbose logging enabled.

Returns
  • verbose (bool): Verbose logging enabled or not.
def debug(self, msg):
93    def debug(self, msg):
94        """Log a message with level DEBUG."""
95        self._logger.debug(msg)

Log a message with level DEBUG.

def info(self, msg):
97    def info(self, msg):
98        """Log a message with level INFO."""
99        self._logger.info(msg)

Log a message with level INFO.

def warning(self, msg):
101    def warning(self, msg):
102        """Log a message with level WARNING."""
103        self._logger.warning(msg)

Log a message with level WARNING.

def error(self, msg):
105    def error(self, msg):
106        """Log a message with level ERROR."""
107        self._logger.error(msg)

Log a message with level ERROR.