news 2026/9/3 7:17:13

日志碎片:仅显示导致错误的日志

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
日志碎片:仅显示导致错误的日志

原文:towardsdatascience.com/log-breadcrumbs-only-show-logs-leading-up-to-an-error-82b9f4c15520

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/a40ff83722411f873098d942f36a4432.png

图片由 Daniel Tseng / Unsplash 提供

在这篇文章中,我们将探讨一种高效记录日志碎片的途径,只显示导致错误的日志。我们将仅使用 Python 的标准日志库来创建一个高效的日志设置,仅在发生异常时捕获调试日志。这种方法提供了对导致问题的步骤的详细视图,同时减少混乱最小化 I/O。让我们开始编码!


为什么记录日志碎片?

当发生错误时,你希望尽可能多地拥有信息,以便引导你找到代码中的问题。记录大量信息在这方面非常有用。

坏处是,所有这些日志都需要被处理。然后需要将它们写入文件或通过 HTTP 发送到端点,这可能会影响你的应用程序或服务器的性能。此外,它可能会使日志变得混乱,使得在发生错误时更难找到相关信息。

面包屑方法“忽略”例如所有debug日志,除非发生错误。这允许你记录大量关于错误的详细信息,同时保持性能和概览在水平。


设置面包屑路径

下面是一个简单的函数,divide,其中包含帮助跟踪其内部行为的调试日志。理想情况下,我们不想每次都看到日志,只想在发生错误时看到,这样我们就可以看到函数尝试除以哪两个数字。

defdivide(a,b):logger.debug(f"Dividing [{a}] by [{b}]")returna/bforvaluein[1,2,3,4,5,6,7,8,9,'not a number',0]:try:logger.debug(f"start dividing..")res=divide(a=10,b=value)exceptExceptionase:logger.error(f"❌An exception occurred:{e}")

前几个值(19)成功进行了除法运算,在这些情况下通常不需要调试日志。

然而,对于像not a number0这样的错误输入,捕获debug日志会提供有价值的上下文。我们的。我们如何回到过去检索日志?

用一行代码将你的 Python 函数转换为装饰器


解决方案概述

要创建面包屑,我们将配置我们的日志记录器以使用两个处理器:

  • StreamHandler:仅显示INFO级别及以上的消息

  • MemoryHandler:临时存储DEBUG消息,并在发生错误时将它们传递给StreamHandler

此设置不会显示DEBUG日志,因为 StreamHandler 被设置为INFO。我们可以临时将DEBUG消息存储在 MemoryHandler 中,当我们检测到错误时,将消息刷新到 StreamHandler。然后,它将显示存储的DEBUG消息。


配置日志记录器

下面是如何使用StreamHandler进行常规输出和MemoryHandler进行缓冲DEBUG日志来配置记录器的示例:

importloggingfromlogging.handlersimportMemoryHandler# Create logger and formatter for a structured log messagelogger=logging.getLogger("my_logger")formatter=logging.Formatter(fmt="%(levelname)-7s ⏱️%(asctime)s 📍 %(funcName)12s:%(lineno)-2s 💌 %(message)s",datefmt="%H:%M:%S")# Configure stream handlerstream_handler=logging.StreamHandler()stream_handler.setLevel(logging.INFO)# Only INFO and above will be displayedstream_handler.setFormatter(formatter)logger.addHandler(stream_handler)# Configure memory handlermemory_handler=MemoryHandler(capacity=100,target=stream_handler,flushLevel=logging.ERROR)memory_handler.setFormatter(formatter)logger.addHandler(memory_handler)

在上述设置中,MemoryHandler可以缓冲最多 100 条日志条目。如果发生错误,我们可以从MemoryHandler刷新日志到StreamHandler,从而得到完整的线索路径。

如何仅用 77MB 使用 Python Bloom 过滤器存储和查询 1 亿项数据


在代码中使用面包屑记录器

下面是配置好的新日志记录器的演示。注意finally块,我们在每次尝试后清除缓冲区,以保持针对每个操作的特定调试日志。

defdivide(a,b):logger.debug(f"Dividing [{a}] by [{b}]")returna/bforvaluein[1,2,3,4,5,6,7,8,9,'not a number',0]:try:logger.debug("Start dividing..")res=divide(a=10,b=value)exceptExceptionase:logger.error(f"❌ An exception occurred:{e}")finally:memory_handler.buffer.clear()# Clear memory after each pass

直到not a number,我们不会看到任何日志,因为所有前面的值执行时都没有错误。然而,当我们处理not a number时,divide函数会抛出异常,因为我们不能将整数除以字符串。

我们最终进入except块并记录一个ERROR。我们已将MemoryHandler配置为在遇到ERROR时将所有缓冲日志刷新到StreamHandler,这正是本例中将要发生的事情。

最后,我们在finally块中清除缓冲区,以便在开始处理not a number时删除9DEBUG日志。


样本输出

当我们运行最终代码时,只有错误情况的日志会显示调试信息作为线索。以下是完整输出的样子:

# Logs corresponding to 'not a number'ERROR ⏱️17:07:03📍 main:44💌 ❌ An exception occurred:unsupported operandtype(s)for/:'int'and'str'DEBUG ⏱️17:07:03📍 main:41💌 Start dividing..DEBUG ⏱️17:07:03📍 divide:32💌 Dividing[10]by[nota number]# Logs corresponding to 0ERROR ⏱️17:07:03📍 main:44💌 ❌ An exception occurred:division by zero DEBUG ⏱️17:07:03📍 main:41💌 Start dividing..DEBUG ⏱️17:07:03📍 divide:32💌 Dividing[10]by[0]

在这些示例中,MemoryHandler仅在遇到错误时捕获和刷新调试日志,提供了一个清晰的线索路径,提供了关于错误的有价值信息。

用两行代码应用 Python 多进程


结论

通过这种设置,我们通过缓冲调试日志并仅在遇到错误时显示它们,实现了更精简的日志记录过程。这种面包屑式的方法对于性能和日志量管理至关重要的应用程序来说非常理想。MemoryHandler为我们提供了两全其美的解决方案:当我们需要时提供详细的跟踪,当我们不需要时最小化日志量。

希望这篇文章和我希望的一样清晰,如果不是这样,请告诉我我可以做些什么来进一步澄清。同时,查看我关于各种编程相关主题的**其他文章**。

开心编码!

— Mike

P.s: 喜欢我在做的事情吗?关注我!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/3 2:31:45

太强了!SpringBoot + QLExpress打造动态规则引擎!

作为一名后端开发,你是否遇到过这样的场景: 运营同学说:"双11活动规则临时调整,满300减60改成满200减50,能马上上线吗?" 产品经理说:"风控策略需要微调一下,这个规则…

作者头像 李华
网站建设 2026/9/2 22:09:52

基于Arduino智能家居环境监测系统

3 系统需求分析 3.1 可行性分析 3.1.1 技术可行性 分析实现基于 Arduino 智能家居环境监测系统所需技术是否成熟、可获取。比如 Arduino 平台开源且资料丰富,有大量现成的函数库可调用,像读取传感器数据、控制执行设备等功能都有成熟实现方式&#xf…

作者头像 李华
网站建设 2026/9/2 22:09:13

失落的乡土:《阿凡达》与《乡土中国》的跨时空深度对话

失落的乡土:《阿凡达》与《乡土中国》的跨时空深度对话 在詹姆斯卡梅隆的《阿凡达》中,潘多拉星球上那片荧光闪烁、万物互联的雨林,常被视作一个纯粹的幻想乌托邦。然而,若将这部科幻巨制与费孝通先生1947年写就的社会学经典《乡…

作者头像 李华
网站建设 2026/9/2 22:59:07

解锁飞行焊接:电芯顶盖封口的高效与精准密码

飞行焊接技术原理剖析 在电芯顶盖封口工艺的不断演进中,飞行焊接技术崭露头角,成为提升生产效率与焊接质量的关键力量。飞行焊接,又称激光飞行焊接(Laser Fly Welding),其核心在于打破了传统逐点焊接的效率瓶颈,实现了 “边移动边焊接” 的创新模式。 传统的焊接方式,…

作者头像 李华
网站建设 2026/9/2 22:09:59

Python+hadoop+spark商品数据分析及预测系统 机器学习 预测算法预测销量

1、项目介绍 技术栈:python语言、Django框架、Echarts可视化、机器学习随机森林预测算法预测销量、爬虫、HTML Python 商品数据分析及预测系统介绍 本 Python 商品数据分析及预测系统,以 Python 语言为开发核心,依托 Django 框架搭建稳定后端…

作者头像 李华