TimedRotatingFileHandler 修改 suffix 后 backupCount 设置失效无法自动删除文件

news/2024/9/18 7:44:23/ 标签: linux, 前端, 运维

本文主要分析 TimedRotatingFileHandler 在实际使用中 backupCount 设置未生效的问题。源码分析显示,文件删除依赖于后缀 suffix 的正则匹配,如果自定义了 suffix 格式,必须同步更新 extMatch 的正则表达式(保证正则表达式可以正常匹配到你新格式的日志文件)。

现象

本文为了测试日志轮转删除,将轮转间隔设为秒(S),设置文件的 backupCount 为 5,同时设置新的日志文件后缀格式为 %Y%m%d%H%M%S.log。

示例如下:

import logging
import os
from logging import handlersos.makedirs("./logs", exist_ok=True)def _logging(**kwargs):level = kwargs.pop('level', logging.DEBUG)filename = kwargs.pop('filename', 'default.log')datefmt = kwargs.pop('datefmt', '%Y-%m-%d %H:%M:%S')format = kwargs.pop('format', '[%(asctime)s,%(msecs)d][%(module)s][%(levelname)s] %(message)s')log = logging.getLogger(filename)format_str = logging.Formatter(format, datefmt)th = handlers.TimedRotatingFileHandler(filename=filename, when='S', backupCount=5, encoding="utf-8")th.suffix = "%Y%m%d%H%M%S.log"th.setFormatter(format_str)th.setLevel(level)log.addHandler(th)log.setLevel(level)return logif __name__ == '__main__':logger = _logging(filename="./logs/test.log")logger.info("Hello world")

然而运行几遍以后,发现产生的日志文件个数已经远远超过了设置的 backupCount 的个数,但旧日期的日志文件却始终没有被删除。

原因

查看源码发现,文件删除依赖于suffix 正则匹配。

而 S 秒默认对应的 extMatch 是下面这个:

extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}(\.\w+)?$"

 默认的 extMatch 和新的后缀格式匹配不上,导致没有轮滚删除旧的文件。

解决

原因明了以后,解决方案也就明朗了。

设置新的匹配新日志格式的正则表达式就可以了(因为是初始化以后再进行的 extMatch 替换,所以替换时需要先对正则表达式的字符串用 re.compile 进行编译):

extMatch = re.compile(r"^\d{4}\d{2}\d{2}\d{2}\d{2}\d{2}(\.\w+)?$", re.ASCII)

完整示例如下: 

import logging
import os
import re
from logging import handlersos.makedirs("./logs", exist_ok=True)def _logging(**kwargs):level = kwargs.pop('level', logging.DEBUG)filename = kwargs.pop('filename', 'default.log')datefmt = kwargs.pop('datefmt', '%Y-%m-%d %H:%M:%S')format = kwargs.pop('format', '[%(asctime)s,%(msecs)d][%(module)s][%(levelname)s] %(message)s')log = logging.getLogger(filename)format_str = logging.Formatter(format, datefmt)th = handlers.TimedRotatingFileHandler(filename=filename, when='S', backupCount=5, encoding="utf-8")th.suffix = "%Y%m%d%H%M%S.log"th.extMatch = re.compile(r"^\d{4}\d{2}\d{2}\d{2}\d{2}\d{2}(\.\w+)?$", re.ASCII)th.setFormatter(format_str)th.setLevel(level)log.addHandler(th)log.setLevel(level)return logif __name__ == '__main__':logger = _logging(filename="./logs/test.log")logger.info("Hello world")

这个时候,产生的日志文件就可以正常轮转删除了。

日志脱敏

哈哈,再顺便来个日志脱敏的小函数,可以指定要脱敏的字段,会将对应字段的 value 替换为等长度的 * 字符串。

logger.py

import copy
import json
import logging
import os
import re
import traceback
from logging import handlersos.makedirs("./logs", exist_ok=True)def _logging(**kwargs):level = kwargs.pop('level', logging.DEBUG)filename = kwargs.pop('filename', 'default.log')datefmt = kwargs.pop('datefmt', '%Y-%m-%d %H:%M:%S')format = kwargs.pop('format', '[%(asctime)s,%(msecs)d][%(module)s][%(levelname)s] %(message)s')log = logging.getLogger(filename)format_str = logging.Formatter(format, datefmt)th = handlers.TimedRotatingFileHandler(filename=filename, when='S', backupCount=5, encoding="utf-8")th.suffix = "%Y%m%d%H%M%S.log"th.extMatch = re.compile(r"^\d{4}\d{2}\d{2}\d{2}\d{2}\d{2}(\.\w+)?$", re.ASCII)th.setFormatter(format_str)th.setLevel(level)log.addHandler(th)log.setLevel(level)return logdef do_desensitization(data, flags: list):data = copy.copy(data)try:if not isinstance(data, str):data = json.dumps(data, ensure_ascii=False)  # 非字符串类型数据都先统一转 json 字符串处理for flag in flags:match_pattern = f'([\'|\"]{flag}[\'|\"].*?:.*?[\'|\"](.*?)[\'|\"])'res = re.findall(match_pattern, data)for item in res:full_match = item[0]  # 获取全匹配结果value_match = item[1]  # 获取 value 匹配结果value_desensitization = '*' * len(value_match)  # 构造等长字符串full_match_desensitization = full_match.replace(value_match, value_desensitization)  # 脱敏替换data = data.replace(full_match, full_match_desensitization)  # 脱敏替换return dataexcept Exception as e:traceback.print_exc()return dataif __name__ == '__main__':logger = _logging(filename="./logs/test.log")logger.info("Hello world")data = {'name': "Looking", "key": "value", 'test': {"name": "test name", "new_key": "new_value"}}result = do_desensitization(data, ["name", "key"])logger.info(result)

test.log

[2024-09-12 19:06:08,24][logger][INFO] Hello world
[2024-09-12 19:06:08,25][logger][INFO] {"name": "*******", "key": "*****", "test": {"name": "*********", "new_key": "new_value"}}


http://www.ppmy.cn/news/1524732.html

相关文章

RK3568平台开发系列讲解(LCD篇)Framebuffer开发

🚀返回专栏总目录 文章目录 一、FrameBuffer 应用编程二、LCD 基础2.1、分辨率2.2、像素格式2.3、LCD 成像步骤2.4、LCD 屏幕时序2.4.1、行显示时序2.4.2、帧显示时序三、FrameBuffer 操作步骤四、LCD 应用编程实验沉淀、分享、成长,让自己和他人都能有所收获!😄 line di…

性能测试:Locust使用介绍(三)

配置 Locust的配置,可以通过三种方式进行。第一种是命令行执行选项,第二种是将配置写到环境变量中,第三种是通过配置文件进行配置。 命令行选项 locust --helpUsage: locust [options] [UserClass ...]常用选项:-h, --help 显示…

VSCode 创建Python 项目(最简单,最少步骤,无痛从pycharm迁移项目)

第一步:下载 下载地址:https://code.visualstudio.com/docs/?dvwin64user 第二步:配置 2.1:VsCode设置中文 按住键盘上的“CtrlShiftP”组合键,打开命令面板。 在命令面板中输入“Configure Display Language”。点击…

LSS可视化分析

1 完整 2 去掉plt.imshow(img_show) 3 去掉plt.axis(‘off’) 4 去掉plt.annotate(cams_text[img_id].replace(‘_’, ’ ), (0.01, 0.92), xycoords=‘axes fraction’)

【自然语言处理】第二章现代语言学基础

【自然语言处理】第二章现代语言学基础 文章目录 【自然语言处理】第二章现代语言学基础1. 语言学与人类的语言1.1 现代语言学的源起及学科分支概况1.2 人类语言的符号性与层级性2. 语言系统及其知识模型2.1 语音系统2.2 词汇系统2.3 句法系统2.4 语义系统2.5 语用系统3. 语言的…

1、https的全过程

目录 一、概述二、SSL过程如何获取会话秘钥1、首先认识几个概念:2、没有CA机构的SSL过程:3、没有CA机构下的安全问题4、有CA机构下的SSL过程 一、概述 https是非对称加密和对称加密的过程,首先建立https链接需要经过两轮握手: T…

SpringMVC基于注解使用:JSON

01-json处理--介绍 json数据格式回顾: 在pom.xml导入依赖 在web.xml里面导入配置文件 ResponseBody 注解是将返回值作为文本返回到客户端了而不是字符串了 当我们想返回bean对象的json数据的时候我们需要先导入jackson依赖在pom.xml里面 然后创建User类&#xff0c…

分享一个基于微信小程序的医院挂号就诊一体化平台uniapp医院辅助挂号应用小程序设计(源码、调试、LW、开题、PPT)

💕💕作者:计算机源码社 💕💕个人简介:本人 八年开发经验,擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等,大家有这一块的问题可以一起交流&…

前端开发的单例设计模式

一、什么是单例模式 单例模式(Singleton Pattern)是一种常见的设计模式,它确保在整个应用程序的生命周期中,一个类只能创建一个实例。无论你在代码的任何地方尝试创建该类的新实例,它都会返回已经存在的唯一实例。这在…

计算机网络分层结构解析:OSI与TCP/IP模型

文章目录 计算机网络分层结构解析:OSI与TCP/IP模型一、引言二、OSI七层模型1、模型介绍1.1、层次功能 2、模型特点 三、TCP/IP四层模型1、模型介绍1.1、层次功能 2、模型特点 四、总结 计算机网络分层结构解析:OSI与TCP/IP模型 一、引言 计算机网络的分…

【前端UI框架】VUE ElementUI 离线文档 可不联网打开

【前端UI框架】VUE ElementUI 离线文档 可不联网打开 Element - The worlds most popular Vue UI framework Element - The worlds most popular Vue UI framework 离线文档下载地址 https://download.csdn.net/download/G971005287W/89742895 文档制作 第一步: 克隆源代码 …

oceanbase(ob)基于备份集搭建备租户方式

一、搭建备租户方式(基于备份的方式) 注意事项:要有一个源端OB集群和目标端OB集群。 1、新建主租户(如果原来有主租户可是省略) #创建unit create resource unit ut_2c2g max_cpu2, memory_size2G, max_iops10000,l…

网络安全实训七(MSF与CS互相连接)

1 MSF连接CS 1.1 生成木马上传到/var/www/html中 1.2 开启apache服务 1.3 设置监听模组并运行 1.4 在靶机上打开网页运行木马 1.5 kali机中获取反弹的shell 1.6 运行CS服务器 1.7 windows端作为客户端连接CS 1.8 新建一个监听器 1.9 返回kali机中使用载荷注入模块,…

【Linux网络】详解TCP协议(1)

🎉博主首页: 有趣的中国人 🎉专栏首页: Linux网络 🎉其它专栏: C初阶 | C进阶 | 初阶数据结构 小伙伴们大家好,本片文章将会讲解 TCP协议 的相关内容。 如果看到最后您觉得这篇文章写得不错&am…

前端开发的观察者模式

什么是观察者设计模式 观察者模式(Observer Pattern)是前端开发中常用的一种设计模式。它定义了一种一对多的依赖关系,使得当一个对象的状态发生改变时,其所有依赖对象都能收到通知并自动更新。观察者模式广泛应用于事件驱动的系…

如何在 Visual Studio Code 中反编译具有正确行号的 Java 类?

优质博文:IT-BLOG-CN 问题 我在 macOS 中使用 vscode 版本 1.92.2,并安装了Java 扩展包v0.29.0。当我打开command click或right click->Go to definition一个没有源代码的类时,vscode 会使用 FernFlower 反编译器打开 .class 文件。但…

python-古籍翻译

题目描述 小理跑到外星人的图书馆去读书。有一本外星古籍,里面的内容是用八进制写成的;但小理只能处理十六进制的数据。请你帮忙写一个翻译软件,帮小理把八进制串翻译成十六进制串。 输入 仅一行,一个八进制字符串 s&#xff0…

Linux下进程间的通信--信号量

前言: 资源竞争: 资源竞争(Race Condition)是多线程或多进程环境中的一种常见问题,它发生在多个进程或线程并发访问和修改同一资源(如内存位置、文件、数据库记录等)时,而最终结果…

Aloudata AIR :国内首个 Data Fabric 逻辑数据平台

AIR 的寓意是“极致轻盈的数据交付”:A - Adaptive 自适应,I - Integration 集成,R - Resilience 弹性 News:Aloudata AIR 发布 作为国内首个 Data Fabric 逻辑数据平台,Aloudata AIR 通过自研的数据虚拟化技术&#…

中秋限定 | AI创意数字月饼(附关键词)

中秋节快到啦,给大家分享一波透明的数字月饼设计 这样的月饼可以永久保存,再也不用担心浪费了啦 AI绘画工具:https://qianlu.cc/?sEmGaur . 核心关键词: Chinese mooncakes (中式月饼) gradient transluc…