formatter:formatter指定了最终日志记录输出的格式。
>>> type(record) <class 'logging.LogRecord'> >>> record.msg 'password=123456 %s %s' >>> record.args ('1', '2') >>> record.created 1697184354.6492243 >>> record.levelname 'INFO' >>> record.name '__main__' >>> record.process 200上面列出了一些LogRecord对象的属性,这些属性大部分也同样是最后格式化日志输出的参数。
class Filter(object): """ Filter instances are used to perform arbitrary filtering of LogRecords. """ def filter(self, record: LogRecord) -> bool: """ Determine if the specified record is to be logged. Returns True if the record should be logged, or False otherwise. If deemed appropriate, the record may be modified in-place. """formatter
class Formatter(object): """ Formatter instances are used to convert a LogRecord to text. """ def format(self, record: LogRecord) -> str: """ Format the specified record as text. The record's attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message. """使用formatter实现明文密码隐藏
import re import logging import logging.config # 堆代码 duidaima.com # 自定义formatter类 class SensitiveFormatter(logging.Formatter): """Formatter that removes sensitive information in urls.""" @staticmethod def _mask_passwd(s) -> str: return re.sub(r'(?<=password=)\S+', r'***', s) def format(self, record) -> str: s = super().format(record) return self._mask_passwd(s) LOGGING_CONFIG = { "version": 1, "formatters": { "default": { "()": SensitiveFormatter, "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s", } }, "handlers": { "console": { "class": "logging.StreamHandler", "formatter": "default", "stream": "ext://sys.stdout" }, }, "loggers": {}, "root": { "level": "DEBUG", "handlers": [ "console", ] } } logging.config.dictConfig(LOGGING_CONFIG) LOG = logging.getLogger(__name__) LOG.info('password=123456') # 2023-10-13 16:58:50,443 - __main__ - INFO - password=***使用filter实现明文密码隐藏
import re import logging import logging.config # 自定义filter类 class SensitiveFilter(logging.Filter): def __init__(self, patterns): super().__init__() self._patterns = patterns def _mask(self, msg): if not isinstance(msg, str): return msg for pattern in self._patterns: msg = re.sub(pattern, r'***', msg) return msg def filter(self, record): record.msg = self._mask(record.msg) if isinstance(record.args, dict): for k in record.args.keys(): record.args[k] = self._mask(record.args[k]) elif isinstance(record.args, tuple): record.args = tuple(self._mask(arg) for arg in record.args) return super().filter(record) LOGGING_CONFIG = { "version": 1, "filters": { "default": { "()": SensitiveFilter, "patterns": [ r'(?<=password=)\S+', ], }, }, "formatters": { "default": { "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s", } }, "handlers": { "console": { "class": "logging.StreamHandler", "formatter": "default", "filters": [ "default", ], "stream": "ext://sys.stdout" }, }, "loggers": {}, "root": { "level": "DEBUG", "handlers": [ "console", ] } } logging.config.dictConfig(LOGGING_CONFIG) LOG = logging.getLogger(__name__) LOG.info('password=123456') # 2023-10-13 16:59:22,545 - __main__ - INFO - password=***