Django中Logging过滤器绑定Logger失效,需移除Root日志中Django INFO信息
问题:绑定到Logger的日志过滤器无效,无法排除Django日志
自定义了ExcludeDjangoLogsFilter过滤器,用于让root logger忽略Django相关日志(Django日志单独存入django_sys.log)。该过滤器绑定到Handler时正常工作,但绑定到root Logger时,虽能实例化过滤器,但filter方法未执行,无法达到过滤效果。最终目标是从root logger中移除Django的INFO级日志。
自定义过滤器代码
class ExcludeDjangoLogsFilter(logging.Filter): """ Excludes django system logs from logger """ modules_to_exclude = ( "daphne.server", "django", "django.db", "django.server" ) def filter(self, record: logging.LogRecord) -> bool: """ Filters records to exclude from a logging modules with a certain names. """ return not record.name.startswith(self.modules_to_exclude)
当前Logging配置
LOGGING = { "version": 1, "disable_existing_loggers": False, # Filters: "filters": { "info_only": { "()": "logger.logger_filters.InfoOnlyFilter" }, "exclude_django_log": { "()": "logger.logger_filters.ExcludeDjangoLogsFilter" } }, # Formatters' profiles: "formatters": { "base": { "format": "[{asctime}][{levelname}][{name} / {funcName}][{lineno}] {message}", "datefmt": "%d/%m/%Y %H:%M:%S", "style": "{" }, "info": { "format": "[{asctime}][{name} / {funcName}] {message}", "datefmt": "%d/%m/%Y %H:%M:%S", "style": "{" }, "django_sys_format": { "format": "[{asctime}][{levelname} | {name}] {message}", "datefmt": "%d/%m/%Y %H:%M:%S", "style": "{" } }, # handlers: "handlers": { "important_file": { "level": "WARNING", "class": "logging.FileHandler", "formatter": "base", "filename": BASE_DIR / "logger/logs/important.log" }, "info_file": { "level": "INFO", "class": "logging.FileHandler", "formatter": "info", "filters": ["info_only"], "filename": BASE_DIR / "logger/logs/events_info.log", }, "django_file": { "level": "INFO", "class": "logging.FileHandler", "formatter": "django_sys_format", "filename": BASE_DIR / "logger/logs/django_sys.log" } }, # loggers: "loggers": { "root": { "handlers": ["important_file", "info_file"], "level": "INFO", "filters": ["exclude_django_log"], "propagate": True, }, "django": { "handlers": ["django_file"], "level": "INFO", "propagate": True }, } }
问题原因与修复方案
核心问题:过滤器代码兼容性错误
虽然Python 3.3+支持str.startswith(tuple),但低版本Python或日志模块的异常捕获机制,会导致该写法抛出异常后被静默忽略,最终表现为filter方法未执行。此外,当前写法的逻辑覆盖也不够严谨。
1. 修复过滤器的filter方法
改用any()遍历前缀列表,确保所有Python版本兼容且逻辑严谨:
class ExcludeDjangoLogsFilter(logging.Filter): """ Excludes django system logs from logger """ modules_to_exclude = ( "daphne.server", "django", "django.db", "django.server" ) def filter(self, record: logging.LogRecord) -> bool: """ Filters records to exclude from a logging modules with a certain names. """ # 遍历所有需要排除的前缀,匹配任意一个则返回False(排除该日志) return not any(record.name.startswith(prefix) for prefix in self.modules_to_exclude)
2. 优化日志传播逻辑(可选但更高效)
将django logger的propagate设为False,直接切断Django日志向root的传播路径,无需root再过滤,提升日志处理效率:
"loggers": { "root": { "handlers": ["important_file", "info_file"], "level": "INFO", "filters": ["exclude_django_log"], "propagate": True, }, "django": { "handlers": ["django_file"], "level": "INFO", "propagate": False # 关闭传播,避免Django日志流到root }, }
验证效果
修复后重启服务,Django的INFO级日志仅会写入django_sys.log,不会出现在important.log和events_info.log中,root logger仅处理业务相关日志。
内容的提问来源于stack exchange,提问作者Antony_K
相关产品推荐
相关产品推荐

