【Python基础】日志工具介绍及使用
日志的主要功能
日志不是软件功能的必需品,但是对于软件开发和维护具有至关重要的作用,其主要的作用在于:
- 问题追踪和调试:
当程序出现错误或异常行为时,日志可以提供关于何时以及在哪里发生问题的详细信息,对于识别、隔离和修复错误很有帮助。 - 审计和合规性:
提供详细的操作记录,用于证明系统是否符合规定。 - 系统监控和预警:
通过分析日志,了解系统的运行状态,如服务的使用情况、性能瓶颈等;当检测到异常模式或潜在问题时,日志可以用于触发警报。 - 业务分析:
记录了系统的所有活动,可以用于分析用户行为、业务趋势等。 - 安全性:
在安全事件发生后,日志可以提供关于攻击者如何进入系统、他们做了什么等信息,对于进行事后分析和改进系统安全性非常重要。 - 故障恢复:
如果系统出现故障,日志可以帮助理解故障发生前的系统状态,从而有助于数据恢复。
良好的日志实践可以提高软件的可靠性、可维护性和安全性。
不过,需要注意的是,过度日志记录可能会对系统性能产生影响,因此还需要合理平衡日志的详细程度和系统性能。
日志工具有哪些
- logging---Python标准库
- loguru---最流行的三方日志框架
- structlog---结构化日志
- logbook---一个很酷的日志库
- python-json-logger---json格式日志
logging---Python标准库
与大多数编程语言不同,Python 在其标准库中包含了一个功能齐全的日志框架。该日志记录解决方案有效地满足了库和应用程序开发人员的需求,并包含了以下严重性级别:DEBUG、INFO、WARNING、ERROR 和 CRITICAL。有了默认日志记录器,无需任何前期设置,您就可以立即开始记录日志。
loguru---最流行的三方日志框架
- 简单易用:只需导入loguru并调用相应的函数即可,无需复杂的配置。
- 自动格式化:自动为日志消息添加时间戳、日志级别等信息,减少编写日志记录代码的工作量,并使日志更加易于阅读和分析。
- 强大的日志级别控制:根据需要输出不同级别的日志,更好地控制日志的详细程度,可轻松调整日志级别。
- 输出目标灵活性:日志消息可输出到多个目标,如控制台、文件、网络等。
- 异常追踪:自动捕获和记录异常信息,并将其与日志消息一起输出,帮助用户快速定位和解决问题。
- 彩色输出支持:在控制台输出中添加颜色,使日志更易于阅读和区分。
- 上下文管理:可自定义上下文信息添加到日志消息中,有助于更好地理解和分析日志,特别是在处理复杂系统和多线程环境时。
structlog---结构化日志
结构化日志输出与传统的文本日志相比,可以提供更丰富、更易于解析和处理的信息。
- 结构化日志记录:可使用Python字典来记录日志,方便添加各种类型的数据(如字符串、数字、异常对象等)到日志中,并使这些数据在后续处理时仍然保持其原始结构和类型。
- 灵活的配置:根据需要选择不同的日志输出格式、处理器和渲染器。例如,用户可以将日志输出到控制台、文件、网络等不同的目标,也可以使用JSON、CSV等常用格式来输出日志。
- 与标准库兼容:与Python的标准库logging兼容,用户可以轻松地将现有的logging代码迁移到structlog,或者同时使用这两个库。
- 性能优化:在性能上进行了优化,尽量减少日志记录对程序性能的影响。
- 扩展性强:具有良好的扩展性,方便地添加自定义的处理器和渲染器,以实现特定的日志处理需求。
- 易于使用:API设计得简洁明了,使得用户可以快速上手并有效地使用它。
logbook---一个很酷的日志库
- 更简洁的API:相较于logging模块的复杂API,logbook提供了更简洁、易用的API。
- 更好的默认设置:logbook的默认设置比logging更合理。
- 上下文感知记录:logbook可以方便地记录上下文信息,如请求ID、用户ID等。而标准库logging模块则需要额外配置才能实现类似功能。
- 灵活的日志处理器:logbook支持多种日志处理器,可以轻松地将日志发送到文件、控制台、邮件、数据库等。
- 性能优化:logbook在性能上经过优化,相较于logging模块,其对应用程序的性能影响较小。
- 集成异常追踪:logbook会自动集成异常的堆栈追踪信息,无需手动添加。而logging模块则需要通过配置来实现此功能。
- 线程和进程安全:logbook是线程和进程安全的,可以在多线程或多进程环境中安全地使用,而logging模块在多线程环境下可能需要额外的同步措施。
- 易于扩展和定制:logbook的设计使得它易于扩展和定制。
python-json-logger---json格式日志
- JSON格式日志记录:将日志记录为JSON格式,易于解析和存储。同时,也方便与其他系统和服务进行集成。
- 可配置的日志格式:根据需要配置日志格式,包含各种字段和信息,如时间戳、日志级别、线程名称等。
- 多个日志处理器支持:可以将日志输出到不同的目标,如文件、控制台、远程服务器等。
- 异步日志记录:支持异步日志记录,意味着可以在后台线程中处理日志记录任务,避免阻塞主线程的执行。
- 上下文信息添加:可以在日志记录时添加额外的上下文信息,如用户ID、请求ID等。
- 灵活的过滤和级别控制:灵活的过滤和级别控制机制。根据需要设置不同的日志级别,并定义过滤器来筛选需要记录的日志消息。
- 与标准库兼容:与Python标准库的logging模块兼容。
以上区别及选择
- loguru,它适用于需要简单、轻量级和易于使用的日志功能的场景。
若你的项目是小型到中型的规模,日志需求比较简单,且开发者也不想花费过多时间在日志配置上,那么,loguru是一个很好的选择,它提供了合理的默认配置。 - structlog,它适用于需要高度结构化日志的场景。
如果你的项目是大型、分布式系统或微服务的架构,其中日志需要在多个组件和服务之间进行传递和处理,那么,structlog是一个很好的选择。 - logbook,它适用于需要高度灵活和可配置日志功能的场景。
如果你的项目是中型到大型的规模,其中需要对日志进行更精细的控制和管理,或者需要替换标准库logging并寻求更多功能和改进性能的项目来说,logbook是一个很好的选择。 - python-json-logger,它适用于需要以JSON格式记录日志的场景。
如果你的项目需要将日志与其他系统或服务进行集成(特别是那些使用JSON作为数据交换格式),或者说随时需要对日志进行分析、监控或审计时,python-json-logger是一个很好的选择。
loguru使用
日志打印
from loguru import logger
# 日志级别
logger.debug("====test====")
logger.info("====test====")
logger.success("====test====")
logger.warning("====test====")
logger.error("====test====")
logger.critical("====test====")
执行结果:
logger.add参数说明
- sink
- 可以传入类file对象,如sys.stderr或者open('test.log', 'w')。
- 可以传入文件路径str或pathlib,如示例代码中的写入日志文件路径。路径可以使用一些附加参数对其进行参数化,如test_{time}.log,{time}即时间参数,创建文件时文件名称中会加入时间。
- 可以传入像lambda这样的可调用函数的简单函数,如lambda msg:print(msg)。这允许完全由用户偏好和需求定义日志记录过程。
- 可以是使用async def语句定义的异步协程函数。该函数返回的协程对象将使用loop.create_task()添加到事件循环中。在使用complete()结束循环之前,应该等待这些任务。
- 也支持传入logging模块的Handler,如FileHandler、StreamHandler等,Loguru记录会自动转换为日志模块预期的结构。
- level:发送到sink的日志消息的最低日志级别,即输出的最低日志级别。
- format:定义日志的输出格式。
- filter:过滤日志。
- colorize:终端日志输出的颜色。
- serializer:bool值,输出日志时是否先格式化成JSON数据格式。
- backtrace:bool值,是否进行异常跟踪(即backtrace信息记录)。
- diagnose:bool值,异常跟踪是否应显示变量值以简化调试。在生产中应将其设置为False,以避免泄漏敏感数据。
- enqueue:bool值,日志消息输出之前是否先通过多进程安全队列,多进程多线程运行写入日志时需用到,避免日志记录丢失或混乱。
- catch:bool值,是否自动捕获接收器处理日志消息时发生的错误。如果为True,则在sys上显示异常消息。
日志输出文件
logger.add("./log/test.log")
滚动日志
# rotation参数设置每天12:00会创建一个新的文件(原来文件重命名,生成新文件)
logger.add("./log/test.log", rotation="14:00")
# 按内容大小滚动
logger.add("./log/test.log", rotation="1 MB")
# 按10天进行滚动
logger.add("file_X.log", retention="10 days")
# 按一周进行滚动
logger.add("file_3.log", rotation="1 week")
# 日志压缩(如果你不想删除原有日志文件,Loguru支持将日志直接压缩)
logger.add("file_Y.log", compression="zip")
处理器、日志格式化、日志过滤
logger.add(sys.stderr, format="{time} {level} {message}", filter="__main__", level="DEBUG")
- sys.stderr 为处理器输出位置,可换成文件
- filter 过滤模块名,如login.py文件中日志,模块名写:login
- level 过滤日志等级
自定义内容及颜色
# <green></green> 标签中间的文字将会被标记为绿色
logger.add(sys.stdout, colorize=True, format="<green>{time}</green> <level>{message}</level>")
进行结构化日志记录
logger.add(sys.stderr, serialize=True) # 控制台输出序列化日志信息便于后续配置引用
# 根据上面的序列化参数,进行配置日志输出结构
logger.add(sys.stderr, format="{time:YYYY-MM-DD HH:mm:ss}|{level}|{module}:{line}|processId:{process}|threadId:{thread}: {message}")
支持Backtrace(回溯)
对于日志而言,没有错误堆栈的日志是没有灵魂的。Loguru 允许显示整个堆栈信息来帮助你发现问题(包括变量)。
logger.add("out.log", backtrace=True, diagnose=True) # 默认可不填写此参数,需要注意内容泄露
def func(a, b):
return a / b
def nested(c):
try:
func(5, c)
except ZeroDivisionError:
logger.exception("What?!")
nested(0)
运行结果:
@logger.catch(装饰器)
使用catch()装饰器/上下文管理器来解决,它确保任何错误都正确地传播到记录器。
@logger.catch
def my_function(x, y, z):
# An error? It's caught anyway!
return 1 / (x + y + z)
my_function()
异步、线程安全、多进程安全
Loguru 默认情况下是线程安全的,但它不是多进程安全的。不过如果你需要多进程/异步记录日志,它也能支持,只需要添加一个enqueue 参数
logger.add("somefile.log", enqueue=True)
与标准日志记录完全兼容
希望将内置日志记录用作 Loguru 接收器
handler = logging.handlers.SysLogHandler(address=('localhost', 514))
logger.add(handler)
需要将 Loguru 消息传播到标准日志记录
class PropagateHandler(logging.Handler):
def emit(self, record: logging.LogRecord) -> None:
logging.getLogger(record.name).handle(record)
logger.add(PropagateHandler(), format="{message}")
想要拦截发送到 Loguru 接收器的标准日志记录消息
class InterceptHandler(logging.Handler):
def emit(self, record: logging.LogRecord) -> None:
# Get corresponding Loguru level if it exists.
level: str | int
try:
level = logger.level(record.levelname).name
except ValueError:
level = record.levelno
# Find caller from where originated the logged message.
frame, depth = inspect.currentframe(), 0
while frame and (depth == 0 or frame.f_code.co_filename == logging.__file__):
frame = frame.f_back
depth += 1
logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)
邮件告警
Loguru 可以和强大的邮件通知模块 notifiers 库结合使用,以在程序意外失败时接收电子邮件,或发送许多其他类型的通知。
import notifiers
params = {
"username": "you@gmail.com",
"password": "abc123",
"to": "dest@gmail.com"
}
# 初始化时发送一封邮件
notifier = notifiers.get_notifier("gmail")
notifier.notify(message="The application is running!", **params)
# 发生Error日志时,发邮件进行警报
from notifiers.logging import NotificationHandler
handler = NotificationHandler("gmail", defaults=params)
logger.add(handler, level="ERROR")
loguru更多方法
============================= 提升自己 ==========================
进群交流、获取更多干货, 请关注微信公众号:
> > > 咨询交流、进群,请加微信,备注来意:sanshu1318 (←点击获取二维码)
> > > 学习路线+测试实用干货精选汇总:
https://www.cnblogs.com/upstudy/p/15859768.html
> > > 【自动化测试实战】python+requests+Pytest+Excel+Allure,测试都在学的热门技术:
https://www.cnblogs.com/upstudy/p/15921045.html
> > > 【热门测试技术,建议收藏备用】项目实战、简历、笔试题、面试题、职业规划:
https://www.cnblogs.com/upstudy/p/15901367.html
> > > 声明:如有侵权,请联系删除。
============================= 升职加薪 ==========================
更多干货,正在挤时间不断更新中,敬请关注+期待。
进群交流、获取更多干货, 请关注微信公众号:
> > > 咨询交流、进群,请加微信,备注来意:sanshu1318 (←点击获取二维码)
> > > 学习路线+测试实用干货精选汇总:
https://www.cnblogs.com/upstudy/p/15859768.html
> > > 【自动化测试实战】python+requests+Pytest+Excel+Allure,测试都在学的热门技术:
https://www.cnblogs.com/upstudy/p/15921045.html
> > > 【热门测试技术,建议收藏备用】项目实战、简历、笔试题、面试题、职业规划:
https://www.cnblogs.com/upstudy/p/15901367.html
> > > 声明:如有侵权,请联系删除。
============================= 升职加薪 ==========================
更多干货,正在挤时间不断更新中,敬请关注+期待。