前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >两个关于日志文件记录库,拿来吧你~

两个关于日志文件记录库,拿来吧你~

作者头像
用户8949263
发布2022-04-08 13:00:13
4630
发布2022-04-08 13:00:13
举报
文章被收录于专栏:Python数据分析实例

背景:数据解析服务挂了,查看由于日志文件未设置定时清理机制,磁盘空间快满载了,于是手动清理一下日志文件重启服务,作为一名程序员怎么能够忍受时刻担心文件资源占用情况,于是动手开发一个日志定时处理工具。

日志收集与分析是运维过程中十分重要的内容,部署的定时运行或者长期运行的数据解析任务时,出现异常或错误的信息,一般查看日志记录来排查问题并解决Bug,为避免记录文件不断增长对服务器运行产生影响,有必要对存储日志进行定时清除或转存 。本文来介绍一下Python日志相关的处理库的使用方法与技巧!

日志记录是如何生成的?

本文介绍Python 的两个日志记录库:logging内置标准库 和loguru库。

  • logging库采用的是模块化设计,可以设置不同的 handler来进行组合,但是在配置上通常较为繁琐;而且如果不是特别处理,在一些多线程或多进程的场景下使用 logging还会导致日志记录会出现错乱或是丢失的情况。
  • loguru库能够减少繁琐的配置过程还能实现和 logging类似的功能,同时还能保证日志记录的线程进程安全(不用担心日志模块异常导致程序崩溃),又能够和 logging相兼容,并进一步追踪异常也能进行代码回溯。

一、logging模块来记录日志需求

logging.basicConfig(level=logging.DEBUG, #设置日志级别

format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s', #日志格式

datefmt='%Y-%m-%d %H:%M:%S', #时间格式

filename='./test.log', #指定文件位置

filemode='w') #指定写入方式

参数注释:

1)filename:指定的文件名创建FiledHandler,日志将存储到指定的文件夹中。

2)filemode:文件打开方式,默认a。

3)format:指定Handler使用的日志显示格式。常用参数如下:

%(asctime)s字符串形式的当前时间 ;

%(filename)s日志输出函数的模块的文件名;

%(lineno)d %调用日志输出函数的语句所在代码行;

%(levelname)s文本形式的日志级别;

%(message)s用户输出信息;

4)datefmt:指定日期时间格式。

5)level:设置rootlogger的日志级别。

logging模块配置详细介绍可参考官方文档。

实例1:将日志信息记录文件中

默认输出仅显示大于等于Warning级别日志

代码语言:javascript
复制
import logging
logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s",  # 日志的格式
    datefmt=" %Y-%m-%d %H:%M:%S",  # 时间格式
    filename="./test.log",  # 指定文件位置
    filemode="w",
)  #日志信息记录到文件
logging.debug('debug message')  #调试时信息打印
logging.info('info message')    #正常信息记录
logging.warning('warning message')  #发生警告信息,仍能正常工作
logging.error('error message')  #发生错误,部分功能不正常
logging.critical('critical message')   #严重错误,程序已崩溃

输出结果

代码语言:javascript
复制
2021-07-18 23:25:14 loggingdemo.py[line:9] DEBUG debug message
2021-07-18 23:25:14 loggingdemo.py[line:10] INFO info message
2021-07-18 23:25:14 loggingdemo.py[line:11] WARNING warning message
2021-07-18 23:25:14 loggingdemo.py[line:12] ERROR error message
2021-07-18 23:25:14 loggingdemo.py[line:13] CRITICAL critical message

实例2:日志记录到文件+IDE/终端显示

handler日志级别以logger日志级别为基础,低于INFO级别的如DEBUG调试信息均不会在handler中出现。

日志配置信息可直接调用配置文件:logging.config.fileConfig('logging.conf')

代码语言:javascript
复制
import logging
#logger:记录器,应用程序代码能直接使用的接口
#第一步:获取logger名称,名称自定义
logger = logging.getLogger("test2")
print(logger.name)

# 第二步:配置logger
# 1)设置logger的日志级别
logger.setLevel(logging.INFO)

#handler:处理器,将日志记录发送到合适的目的地
#2)设置logger输出位置,一次性可输出到不同位置,创建不同的handler,并分别设置日志级别
# 输出到终端
handler1 = logging.StreamHandler()
handler1.setLevel(logging.DEBUG)
# 输出到文件
handler2 = logging.FileHandler(filename="test2.log", mode="a", encoding="utf-8")
handler2.setLevel(logging.WARNING)

#formatter:格式化器,输出中日志记录的布局。
# 创建两个格式化器
formatter1 = logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
formatter2 = logging.Formatter("%(asctime)s-%(name)s-%(levelname)s-%(message)s")
# 设置两个handler的格式化器
handler1.setFormatter(formatter1)
handler2.setFormatter(formatter2)
# 为logger添加两个handler
logger.addHandler(handler1)
logger.addHandler(handler2)

#第三步:程序中记录日志
logger.debug("debug message")
logger.info("info message")
logger.warning("warning message")
logger.error("error message")
logger.critical("critical message")

IDE/终端

代码语言:javascript
复制
2021-07-19 22:36:21,128 test2 INFO info message
2021-07-19 22:36:21,128 test2 WARNING warning message
2021-07-19 22:36:21,129 test2 ERROR error message
2021-07-19 22:36:21,129 test2 CRITICAL critical message

test2.log

代码语言:javascript
复制
2021-07-19 22:36:21,128-test2-WARNING-warning message
2021-07-19 22:36:21,129-test2-ERROR-error message
2021-07-19 22:36:21,129-test2-CRITICAL-critical message

实例3:日志滚动输出+IDE/终端显示+自定义文件大小

RotatingFileHandler:将日志文件记录到磁盘文件,可以设置每个日志文件的最大占用空间

代码语言:javascript
复制
import logging
import logging.handlers

def setup_logger(logger_name, level=logging.INFO):
    mylog = logging.getLogger(logger_name)
    mylog.setLevel(level)

    # 日志格式
    formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")

    # IDE/终端输出
    streamHandler = logging.StreamHandler()
    streamHandler.setFormatter(formatter)

    # 滚动文件输出
    # 计算机中各种存储容量的单位都是用字节(Byte)来表示,此外还有KB、MB、GB和TB
    # 1KB = 1024Bytes = 2的10次方Bytes
    # 1MB = 1024KB = 2的20次方Bytes
    # 1GB = 1024MB = 2的30次方Bytes
    # 1TB = 1024GB = 2的40次方Bytes

    # 写入文件,RotatingFileHandler设置每个日志文件的最大占用空间。maxBytes设置文件大小,backupCount设置保留文件个数。
    rotatingHandler = logging.handlers.RotatingFileHandler('logs/mylog.log', maxBytes=5 * 1024 , backupCount=3)
    rotatingHandler.setFormatter(formatter)

    mylog.addHandler(streamHandler)
    mylog.addHandler(rotatingHandler)


if __name__ == '__main__':
    setup_logger('mylog')
    mylog = logging.getLogger('mylog')
    while True:
        mylog.info("file test")

这里主要介绍了handler的StreamHandler和FileHandler子类,logging模块提供非常强大的其他子类,感兴趣的小伙伴可以尝试一下:

TimedRoatatingFileHandler:将日志文件记录到磁盘文件,按固定时间间隔来循环记录日志。

SMTPHandler:可以将日志发送到邮箱;

HTTPHander:使用Get或Post方法向HTTP服务器发送消息

二、loguru模块来记录日志需求

loguru 库已高度封装,logger 本身就是一个实例化对象,可直接调用 logger 类。只需导入使用即可。

代码语言:javascript
复制
#pipenv install loguru
from loguru import logger

当然,loguru 也可像 logging 一样可配置,但更简单化。

使用 add() 方法对 logger 进行简单的配置。

实例1:将日志信息记录文件中

在不指定任何参数时,logger 默认采用 sys.stderr 标准错误输出将日志输出到控制台(console)中;通常 linux 服务器上会以文件留存,添加字符串路径即可。

代码语言:javascript
复制
from loguru import logger
import os

logger.add(os.path.expanduser("testlog.log"))

logger.debug("debug message")
logger.info("info level message")
logger.warning("warning level message")
logger.critical("critical level message")

2021-07-19 23:51:01.808 | DEBUG    | __main__:<module>:9 - debug message
2021-07-19 23:51:01.808 | INFO     | __main__:<module>:10 - info level message
2021-07-19 23:51:01.808 | WARNING  | __main__:<module>:11 - warning level message
2021-07-19 23:51:01.808 | CRITICAL | __main__:<module>:12 - critical level message

当你在 IDE 或终端里运行时,loguru 输出的日志信息带上了不同的颜色样式(schema),十分美观。

如何定期清洗日志文件?

一般数据开发平台已定制好日志管理体系,大型项目,一般通过集成的日志平台或数据库来对日志信息进行存储和留存,便于后续日志分析。一些中小型项目,通常只需要以文件形式留存日志。

一、以文件形式留存日志

需要考虑日志的留存、压缩,甚至定期清理,随着系统长时间运行,若向单个文件追加日志记录,当日志内容增长到一定数量级时,将影响外部读取、查找及分析。loguru模块可通过添加关键参数设置满足以上需求。

下面主要介绍3个关键参数:rotation 、compression 和 retention

1)rotation 参数:将日志记录以大小、时间等方式进行分割或划分:

2)compression 参数:压缩日志,传入压缩文件扩展名即可,如 zip、tar、gz等。只要满足 rotation 分割后的日志文件都被直接压缩成了 zip 文件。

代码语言:javascript
复制
import os
from loguru import logger
#指定日志文件存储文件夹
log_dir = os.path.expanduser(r"D:\myProjectfile\logging_demo\logs")

#指定日志文件格式
log_file = os.path.join(LOG_DIR, "file_{time}.log")

#设置rotation参数,以固定文件大小100KB存储文件
logger.add(log_file, rotation = "100KB")

#追加compression参数,压缩文件
#logger.add(log_file, rotation = "100KB",compression="zip")

#日志记录
for n in range(10000):
    logger.info(f"test - {n}")

3)retention参数:对超过一定时间的日志删除

代码语言:javascript
复制
#保持其他不变,只需更改一下代码
logger.add(LOG_FILE, rotation="100KB",retention=1)

当然对 retention 传入整数时,该参数表示的是所有文件的索引,而非要保留的文件数。所以最后我们会看到只有两个时间最近的日志文件会被保留下来,其他都被直接清理掉了。

若日志系统没有设置过滤器处理过期文件,可利用以下函数模块定期调用清理过期文件。

代码语言:javascript
复制
import os
import datetime
#os.walk返回的是一个3个元素的元组 (root, dirs, files) ,分别表示遍历的路径名,该路径下的目录列表和该路径下文件列表
for root,dirs,files in os.walk(r"F:\AutoOps_platform\日志文件\logs",topdown=False):#循环D:\works目录和子目录,该处指定目录即可
    print(files)
    for file in files:
        print(file)
        absPathFile=os.path.join(root,file)
        print(absPathFile)
        now=datetime.datetime.now()
        modefiedTime = datetime.datetime.fromtimestamp(os.path.getmtime(absPathFile))
        diffTime=now-modefiedTime
        if diffTime.days>30:#条件筛选超过30天内的文件
            print(f"{absPathFile:<27s}修改时间[{modefiedTime.strftime('%Y-%m-%d %H:%M:%S')}]  距今[{diffTime.days:3d}天{diffTime.seconds//3600:2d}时{diffTime.seconds%3600//60:2d}]")#打印相关信息
            os.remove(absPathFile)

文件相关操作可参考以往推文:

Python内置的文件夹操作

Python内置十大文件操作

Python文件目录操作就是这么6

二、以数据库形式留存日志

首先需要通过 serialize 参数将其转化成序列化的 json 格式,导入非关系型数据库如 MongoDB中用作后续的日志分析。

代码语言:javascript
复制
from loguru import logger
import os

logger.add(os.path.expanduser(r"F:\AutoOps_platform\日志文件\logs\test.log"), serialize=True)
logger.info("test")

序列号记录如下:

代码语言:javascript
复制
{
    "text": "2021-07-20 19:14:25.399 | INFO     | __main__:<module>:22 - test\n",
    "record": {
        "elapsed": {
            "repr": "0:00:00.071955",
            "seconds": 0.071955},
        "exception": null,
        "extra": {},
        "file": {
            "name": "log_file.py",
            "path": "F:/AutoOps_platform/\u65e5\u5fd7\u6587\u4ef6/log_file.py"},
        "function": "<module>",
        "level": {
                    "icon": "\u2139\ufe0f",
                    "name": "INFO",
                    "no": 20},
        "line": 22,
        "message": "test",
        "module": "log_file",
        "name": "__main__",
        "process": {
            "id": 4712,
            "name": "MainProcess"},
        "thread": {
            "id": 3288,
            "name": "MainThread"},
        "time": {
            "repr": "2021-07-20 19:14:25.399480+08:00",
            "timestamp": 1626779665.39948}}}

本文介绍了日志文件处理常用模块的使用方法,基本能够满足常规脚本开发需求。其他更高级姿势配置部分没有进一步展开,若对这个库感兴趣,建议深入阅读一下其官方文档,更好的运用到实际开发中。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-07-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python数据分析实例 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Python内置的文件夹操作
  • Python内置十大文件操作
  • Python文件目录操作就是这么6
相关产品与服务
日志服务
日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档