有测试问题请微信联系作者,备注来意(点击此处添加)
240
一名普通的测试打工人;专注自动化测试技术研究、实践、总结、分享、交流。
用我多年的经历,给大家带来更多实用的干货。
人若有志,就不会在半坡停止。

【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更多方法

官方文档:https://github.com/Delgan/loguru
【loguru日志库】

posted @ 2024-02-03 16:06  三叔测试笔记  阅读(941)  评论(0编辑  收藏  举报
返回顶部 跳转底部