import logging import re from logging.handlers import TimedRotatingFileHandler # 统一日志格式:含模块名(name)与源码行号,便于 grep 定位 LOG_FORMAT = '%(asctime)s %(name)s:%(lineno)d [%(levelname)s] %(message)s' class SensitiveDataFilter(logging.Filter): """Redact common credentials even when callers log an entire request mapping.""" _assignments = re.compile( r"(?i)(['\"]?(?:api[_-]?key|password|passwd|secret|token|authorization)['\"]?\s*[:=]\s*)" r"(['\"][^'\"]*['\"]|[^,}\s]+)", ) _url_userinfo = re.compile(r"(?i)\b((?:rtsp|rtmp|https?)://)[^/@\s]+@") def filter(self, record): try: rendered = record.getMessage() rendered = self._assignments.sub(r"\1[REDACTED]", rendered) rendered = self._url_userinfo.sub(r"\1[REDACTED]@", rendered) record.msg = rendered record.args = () except Exception: pass return True def CreateLogger(filepath, is_show_console=False,log_debug=False): LOGGER_WHEN = 'd' LOGFILE_BACKUPCOUNT = 3 if log_debug: level = logging.DEBUG else: level = logging.INFO logger = logging.getLogger() logger.setLevel(level) formatter = logging.Formatter(LOG_FORMAT) # 最基础 # fileHandler = logging.FileHandler(filepath, encoding='utf-8') # 指定utf-8格式编码,避免输出的日志文本乱码 # fileHandler.setLevel(level) # fileHandler.setFormatter(formatter) # logger.addHandler(fileHandler) # 时间滚动切分 # when:备份的时间单位,backupCount:备份保存的时间长度 timedRotatingFileHandler = TimedRotatingFileHandler(filepath, when=LOGGER_WHEN, backupCount=LOGFILE_BACKUPCOUNT, encoding='utf-8') timedRotatingFileHandler.setLevel(level) timedRotatingFileHandler.setFormatter(formatter) timedRotatingFileHandler.addFilter(SensitiveDataFilter()) logger.addHandler(timedRotatingFileHandler) # 控制台打印 if is_show_console: streamHandler = logging.StreamHandler() streamHandler.setLevel(level) streamHandler.setFormatter(formatter) streamHandler.addFilter(SensitiveDataFilter()) logger.addHandler(streamHandler) return logger