cornsnake.util_log

Functions for logging exceptions and setting up logging configurations.

Documentation

  1"""
  2Functions for logging exceptions and setting up logging configurations.
  3
  4[Documentation](http://docs.mrseanryan.cornsnake.s3-website-eu-west-1.amazonaws.com/cornsnake/util_log.html)
  5"""
  6
  7import logging
  8import os
  9import re
 10import typing
 11
 12from . import config
 13from . import util_color
 14
 15# Define the format for log entries
 16# ref https://realpython.com/python-logging/
 17log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
 18
 19
 20def set_log_dir_and_get_path_to_logfile(log_dir: str) -> str:
 21    """
 22    Set the log directory and get the path to the log file.
 23
 24    Args:
 25    log_dir (str): The directory where the log file will be stored.
 26
 27    Returns:
 28    str: The path to the log file.
 29    """
 30    path_to_logfile = os.path.join(log_dir, config.LOG_FILENAME)
 31    logging.basicConfig(
 32        filename=path_to_logfile,
 33        filemode="w",
 34        format=log_format,
 35        level=config.LOGGING_LEVEL,
 36    )
 37    return path_to_logfile
 38
 39
 40def log_exception(e: typing.Any) -> None:
 41    """
 42    Log an exception.
 43    -  Call from inside a Try..Except
 44
 45    Args:
 46    e (Exception): The exception to be logged.
 47    """
 48    # do NOT call util_print here (could be infinite loop)
 49    print(util_color.ERROR_COLOR + "!EXCEPTION!", e, util_color.END_COLORS)
 50    logging.exception("Exception occurred")
 51
 52
 53def getLogger(name_of_module: str) -> logging.Logger:
 54    """
 55    Get a logger with the specified name.
 56
 57    - Call like this: getLogger(__name__) - then we know where did those log entries come from.
 58
 59    Args:
 60    name_of_module (str): The name of the module to create the logger for.
 61
 62    Returns:
 63    Logger: A logger object for the specified module.
 64    """
 65    return logging.getLogger(name_of_module)
 66
 67
 68MASKED = "<masked>"
 69pat = re.compile(r".*[/|\\]Users[/|\\]([A-Za-z.]*)[/|\\]{1}.*", re.M)
 70
 71WINDOWS_SEP = "\\"
 72MAC_SEP = "/"
 73
 74
 75def mask_sensitive_text(text: str) -> str:
 76    """
 77    Mask text that contains a user name.
 78
 79    Examples:
 80    - Windows: C:\\Users\\Bob.Jones\\my-file.txt -> C:\\Users\\<masked>\\my-file.txt
 81    - Mac: /Users/Bob.Jones/my-file.txt -> /Users/<masked>\\my-file.txt
 82    """
 83    try:
 84        sensitive_win = WINDOWS_SEP + "Users" + WINDOWS_SEP
 85        sensitive_mac = MAC_SEP + "Users" + MAC_SEP
 86
 87        if (
 88            sensitive_win in text or sensitive_mac in text
 89        ):  # Both can occur with git on Windows
 90            matches = set(pat.findall(text))
 91
 92            while matches:
 93                for m in matches:
 94                    text = text.replace(m, "<masked>")
 95                matches = set(pat.findall(text))
 96    except ValueError:
 97        pass  # logging code needs to be robust
 98    except RuntimeError:
 99        pass  # logging code needs to be robust
100
101    return text
102
103
104def log_sensitive_info(text: str, logger: logging.Logger) -> None:
105    """
106    Log at info level, masking out any user name in the text.
107    """
108    logger.info(mask_sensitive_text(text))
109
110
111def log_sensitive_warn(text: str, logger: logging.Logger) -> None:
112    """
113    Log at warn level, masking out any user name in the text.
114    """
115    logger.warn(mask_sensitive_text(text))
log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
def set_log_dir_and_get_path_to_logfile(log_dir: str) -> str:
21def set_log_dir_and_get_path_to_logfile(log_dir: str) -> str:
22    """
23    Set the log directory and get the path to the log file.
24
25    Args:
26    log_dir (str): The directory where the log file will be stored.
27
28    Returns:
29    str: The path to the log file.
30    """
31    path_to_logfile = os.path.join(log_dir, config.LOG_FILENAME)
32    logging.basicConfig(
33        filename=path_to_logfile,
34        filemode="w",
35        format=log_format,
36        level=config.LOGGING_LEVEL,
37    )
38    return path_to_logfile

Set the log directory and get the path to the log file.

Args: log_dir (str): The directory where the log file will be stored.

Returns: str: The path to the log file.

def log_exception(e: Any) -> None:
41def log_exception(e: typing.Any) -> None:
42    """
43    Log an exception.
44    -  Call from inside a Try..Except
45
46    Args:
47    e (Exception): The exception to be logged.
48    """
49    # do NOT call util_print here (could be infinite loop)
50    print(util_color.ERROR_COLOR + "!EXCEPTION!", e, util_color.END_COLORS)
51    logging.exception("Exception occurred")

Log an exception.

  • Call from inside a Try..Except

Args: e (Exception): The exception to be logged.

def getLogger(name_of_module: str) -> logging.Logger:
54def getLogger(name_of_module: str) -> logging.Logger:
55    """
56    Get a logger with the specified name.
57
58    - Call like this: getLogger(__name__) - then we know where did those log entries come from.
59
60    Args:
61    name_of_module (str): The name of the module to create the logger for.
62
63    Returns:
64    Logger: A logger object for the specified module.
65    """
66    return logging.getLogger(name_of_module)

Get a logger with the specified name.

  • Call like this: getLogger(__name__) - then we know where did those log entries come from.

Args: name_of_module (str): The name of the module to create the logger for.

Returns: Logger: A logger object for the specified module.

MASKED = '<masked>'
pat = re.compile('.*[/|\\\\]Users[/|\\\\]([A-Za-z.]*)[/|\\\\]{1}.*', re.MULTILINE)
WINDOWS_SEP = '\\'
MAC_SEP = '/'
def mask_sensitive_text(text: str) -> str:
 76def mask_sensitive_text(text: str) -> str:
 77    """
 78    Mask text that contains a user name.
 79
 80    Examples:
 81    - Windows: C:\\Users\\Bob.Jones\\my-file.txt -> C:\\Users\\<masked>\\my-file.txt
 82    - Mac: /Users/Bob.Jones/my-file.txt -> /Users/<masked>\\my-file.txt
 83    """
 84    try:
 85        sensitive_win = WINDOWS_SEP + "Users" + WINDOWS_SEP
 86        sensitive_mac = MAC_SEP + "Users" + MAC_SEP
 87
 88        if (
 89            sensitive_win in text or sensitive_mac in text
 90        ):  # Both can occur with git on Windows
 91            matches = set(pat.findall(text))
 92
 93            while matches:
 94                for m in matches:
 95                    text = text.replace(m, "<masked>")
 96                matches = set(pat.findall(text))
 97    except ValueError:
 98        pass  # logging code needs to be robust
 99    except RuntimeError:
100        pass  # logging code needs to be robust
101
102    return text

Mask text that contains a user name.

Examples:

  • Windows: C:\Users\Bob.Jones\my-file.txt -> C:\Users<masked>\my-file.txt
  • Mac: /Users/Bob.Jones/my-file.txt -> /Users/\my-file.txt
def log_sensitive_info(text: str, logger: logging.Logger) -> None:
105def log_sensitive_info(text: str, logger: logging.Logger) -> None:
106    """
107    Log at info level, masking out any user name in the text.
108    """
109    logger.info(mask_sensitive_text(text))

Log at info level, masking out any user name in the text.

def log_sensitive_warn(text: str, logger: logging.Logger) -> None:
112def log_sensitive_warn(text: str, logger: logging.Logger) -> None:
113    """
114    Log at warn level, masking out any user name in the text.
115    """
116    logger.warn(mask_sensitive_text(text))

Log at warn level, masking out any user name in the text.