bedrock.log

This module configures the logger for the application.

Log levels:

  • DEBUG: For debugging purposes
  • INFO: For general information
  • WARN: For warnings
  • ERROR: For errors

Log levels will always print the messages of the levels below them (e.g. INFO will print WARN and ERROR messages too).

The application log level is controlled by a variable (YOUR_APP_LOG_LEVEL). See config for more information.

Usage:

from bedrock.log import log_config
log = log_config("YourModulesNameHere")
log.debug("Hello World!")  # Gets printed if log level is set to `DEBUG`
log.info("Hello World!")   # Gets printed if log level is set to `DEBUG` or `INFO`
log.warn("Hello World!")   # Gets printed if log level is set to `DEBUG`, `INFO` or `WARN`
log.error("Hello World!")  # Gets printed if log level is set to `DEBUG`, `INFO`, `WARN` or `ERROR`
 1"""
 2This module configures the logger for the application.
 3
 4## Log levels:
 5* `DEBUG`: For debugging purposes
 6* `INFO`: For general information
 7* `WARN`: For warnings
 8* `ERROR`: For errors
 9
10Log levels will always print the messages of the levels below them (e.g. `INFO` will print `WARN` and `ERROR` messages too).
11
12The application log level is controlled by a variable (`YOUR_APP_LOG_LEVEL`). See [`config`](./config.html) for more information.
13
14## Usage:
15```python
16from bedrock.log import log_config
17log = log_config("YourModulesNameHere")
18log.debug("Hello World!")  # Gets printed if log level is set to `DEBUG`
19log.info("Hello World!")   # Gets printed if log level is set to `DEBUG` or `INFO`
20log.warn("Hello World!")   # Gets printed if log level is set to `DEBUG`, `INFO` or `WARN`
21log.error("Hello World!")  # Gets printed if log level is set to `DEBUG`, `INFO`, `WARN` or `ERROR`
22```
23"""
24
25import logging  # pragma: no cover
26from bedrock.config import get_config_params, get_prefix  # pragma: no cover
27
28AUDIT_LOG_LEVEL = logging.CRITICAL + 10  # Higher than CRITICAL so is always outputted
29logging.addLevelName(AUDIT_LOG_LEVEL, "AUDIT")
30
31
32class MyLogger(logging.getLoggerClass()):  # pragma: no cover
33    def __init__(self, name, level=logging.NOTSET):
34        super().__init__(name, level)
35
36    def audit(self, msg, *args, **kwargs):
37        if self.isEnabledFor(AUDIT_LOG_LEVEL):
38            self._log(AUDIT_LOG_LEVEL, msg, args, **kwargs)
39
40
41logging.setLoggerClass(MyLogger)
42
43
44def log_config(module: str = "generic"):  # pragma: no cover
45    """
46    Configures the logger for the application & returns it.
47    :param module: Name that will prefix every message
48    :return: The logger
49    """
50    prefix = get_prefix()
51    config = get_config_params()
52    log_level = {
53        'DEBUG': logging.DEBUG,
54        'INFO': logging.INFO,
55        'WARN': logging.WARN,
56        'ERROR': logging.ERROR
57    }
58    logger = logging.getLogger(f'{prefix}-{module}')
59    logging.basicConfig()
60    log_level_option = config["log_level"]
61    try:
62        logger.setLevel(log_level[log_level_option])
63    except:
64        logger.setLevel(log_level["WARN"])
65    return logger
AUDIT_LOG_LEVEL = 60
class MyLogger(logging.Logger):
33class MyLogger(logging.getLoggerClass()):  # pragma: no cover
34    def __init__(self, name, level=logging.NOTSET):
35        super().__init__(name, level)
36
37    def audit(self, msg, *args, **kwargs):
38        if self.isEnabledFor(AUDIT_LOG_LEVEL):
39            self._log(AUDIT_LOG_LEVEL, msg, args, **kwargs)

Instances of the Logger class represent a single logging channel. A "logging channel" indicates an area of an application. Exactly how an "area" is defined is up to the application developer. Since an application can have any number of areas, logging channels are identified by a unique string. Application areas can be nested (e.g. an area of "input processing" might include sub-areas "read CSV files", "read XLS files" and "read Gnumeric files"). To cater for this natural nesting, channel names are organized into a namespace hierarchy where levels are separated by periods, much like the Java or Python package namespace. So in the instance given above, channel names might be "input" for the upper level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels. There is no arbitrary limit to the depth of nesting.

MyLogger(name, level=0)
34    def __init__(self, name, level=logging.NOTSET):
35        super().__init__(name, level)

Initialize the logger with a name and an optional level.

def audit(self, msg, *args, **kwargs):
37    def audit(self, msg, *args, **kwargs):
38        if self.isEnabledFor(AUDIT_LOG_LEVEL):
39            self._log(AUDIT_LOG_LEVEL, msg, args, **kwargs)
def log_config(module: str = 'generic'):
45def log_config(module: str = "generic"):  # pragma: no cover
46    """
47    Configures the logger for the application & returns it.
48    :param module: Name that will prefix every message
49    :return: The logger
50    """
51    prefix = get_prefix()
52    config = get_config_params()
53    log_level = {
54        'DEBUG': logging.DEBUG,
55        'INFO': logging.INFO,
56        'WARN': logging.WARN,
57        'ERROR': logging.ERROR
58    }
59    logger = logging.getLogger(f'{prefix}-{module}')
60    logging.basicConfig()
61    log_level_option = config["log_level"]
62    try:
63        logger.setLevel(log_level[log_level_option])
64    except:
65        logger.setLevel(log_level["WARN"])
66    return logger

Configures the logger for the application & returns it.

Parameters
  • module: Name that will prefix every message
Returns

The logger