接口测试 [求助] 项目使用 logging 库打印日志,以天为单位进行日志分割,但有时候日志会打到其他地方

时光走散了故人。 · 2019年12月29日 · 最后由 时光走散了故人。 回复于 2020年01月02日 · 2541 次阅读

背景:

1、采用 logging 库,并设置 when='MIDNIGHT',以天为单位,进行日志分割,前一天的日志会自动加上前一天的日期,最新日志始终会打印到mock-service.log文件中,以下为 log 打印的封装
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/8/8 22:10
# @Author  : 
# @Site    : 
# @File    : Logger.py
# @Software: PyCharm

"""
日志类。通过读取配置文件,定义日志级别、日志文件名、日志格式等。
一般直接把logger import进去
from utils.log import logger
logger.info('test log')
"""
import os
import platform
import logging
from logging.handlers import TimedRotatingFileHandler


class Logger:
    def __init__(self, logger_name='framework'):
        self.logger = logging.getLogger(logger_name)
        logging.root.setLevel(logging.NOTSET)
        if platform.system() == 'Windows':
            # win机器路径
            self.log_path=os.path.join(os.path.dirname(os.path.dirname(__file__)),'log')
        else:
            # 服务器路径
            self.log_path='/log'
        self.log_file_name = 'mock-service.log'  # 日志文件
        self.backup_count = 30  # 保留的日志数量
        # 日志输出级别
        self.console_output_level = 'INFO'
        self.file_output_level = 'INFO'
        # 日志输出格式
        pattern = '%(asctime)s - %(filename)s [Line:%(lineno)d] - %(levelname)s - %(message)s'
        self.formatter = logging.Formatter(pattern)

    def get_logger(self):
        """在logger中添加日志句柄并返回,如果logger已有句柄,则直接返回
        我们这里添加两个句柄,一个输出日志到控制台,另一个输出到日志文件。
        两个句柄的日志级别不同,在配置文件中可设置。
        """
        if not self.logger.handlers:  # 避免重复日志
            console_handler = logging.StreamHandler()
            console_handler.setFormatter(self.formatter)
            console_handler.setLevel(self.console_output_level)
            self.logger.addHandler(console_handler)

            # 每天重新创建一个日志文件,最多保留backup_count份
            # 每天生成的日志文件没有后缀,需要修改源码:TimedRotatingFileHandler类下的doRollover方法-->
            # dfn = self.rotation_filename(self.baseFilename + "." + time.strftime(self.suffix, timeTuple)后面拼接后缀名
            # dfn = self.rotation_filename(self.baseFilename + "." + time.strftime(self.suffix, timeTuple) + ".log")
            file_handler = TimedRotatingFileHandler(filename=os.path.join(self.log_path, self.log_file_name),
                                                    when='MIDNIGHT',
                                                    interval=1,
                                                    backupCount=self.backup_count,
                                                    delay=True,
                                                    encoding='utf-8'
                                                    )
            file_handler.setFormatter(self.formatter)
            file_handler.setLevel(self.file_output_level)
            self.logger.addHandler(file_handler)
        return self.logger

logger = Logger().get_logger()
2、实际调用时,采用导包并设置别名的方式进行 log 打印,以下为实际打印 log 的 demo
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/12/2 10:32
# @Author  : 
# @Site    : 
# @File    : 1.py
# @Software: PyCharm
# @Description:

from util.Logger import logger as log

class test1:
    def log_test(self):
        log.info('log测试')



if __name__ == '__main__':
    t = test1()
    t.log_test()

3、该项目目前部署在 centos7 的一台服务器上面,不过我觉得这个应该和部署在哪里没关系

问题:

1、项目持续在服务器上面运行着,但有时候会发现,日志根本没有打印到mock-service.log文件中,比如下面这个,12 月 29 的调用日志,打到了 27 号的 log 文件中了

有人知道这是什么原因嘛?这个问题困扰了我很久,就是找不到原因,网上也搜索了很多,但最终也没搜索到相关的问题

最佳回复

问题已解决

经几天测试下来已经完美解决这个问题了,解决问题的方式有很多种,logging 库本身是不支持多进程的,但是现在很多第三方库已经针对 logging 进行重写了,通过加锁或其他方式解决了这一问题,在这里推荐一个第三方库,目前我在用的就是这个,concurrent_log

安装方式:

pip3 install concurrent_log

github 地址:

https://github.com/huanghyw/concurrent_log

关于自己对 logging 库重写也是可以的,下面介绍几篇重写的文章

共收到 4 条回复 时间 点赞

为了找到原因,之前有些调用 log 打印是写在 init 方法里面,然后下面的方法用 self.log 进行调用,后面为了解决这个问题,把所有 init 里面的初始化都去掉了,现在我觉得问题可能还是出在调用上,日志封装应该没有问题。现在这个项目有些是类方法在打印日志,有些是封装的函数在打印日志。整个项目是用 flask 框架写的,然后启动 run.py 文件,我觉得可能是出现在了某一个地方的调用一直占用了日志打印的进程,导致后面再调用日志打印的时候打印到了之前的文件中,只是一个猜测,也不知道怎么去验证这个问题

我另一个项目也是同样的调用 log 打印日志,但每天打印的日志都是对的,所以可能还是调用上面出的问题,有人知道该怎么去验证调用是否有问题吗?
下面的截图是另一个项目的,每天的日志都准确的打印到了对应的日志文件中

经过今天的一番查找,很大可能是多线程的问题,正在使用一个第三方库进行验证,如果没问题了,我会在下方追加解决办法,但唯一确认的是 python 的 logging 库是不支持多线程的,所以这里肯定有问题

问题已解决

经几天测试下来已经完美解决这个问题了,解决问题的方式有很多种,logging 库本身是不支持多进程的,但是现在很多第三方库已经针对 logging 进行重写了,通过加锁或其他方式解决了这一问题,在这里推荐一个第三方库,目前我在用的就是这个,concurrent_log

安装方式:

pip3 install concurrent_log

github 地址:

https://github.com/huanghyw/concurrent_log

关于自己对 logging 库重写也是可以的,下面介绍几篇重写的文章

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册