【踩坑記錄】記錄一次使用Python logging庫多進程打印日誌的填坑過程

背景:

  • 項目使用Python自帶的logging庫來打印日誌
  • 項目部署在一臺Centos7的機器上
  • 項目採用gunicorn多進程部署

過程:

一、LOG日誌代碼封裝:

採用logging庫,並設置when='MIDNIGHT',以天爲單位,進行日誌分割,前一天的日誌會自動加上前一天的日期,最新日誌始終會打印到mock-service.log文件中,如下爲log打印的封裝html

#!/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()

二、調用LOG封裝

實際調用時,採用導包並設置別名的方式進行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()

三、項目部署環境

該項目目前部署在centos7的一臺服務器上面,不過我以爲這個應該和部署在哪裏不要緊

四、出現的問題(坑,大坑)

項目持續在服務器上面運行着,但有時候會發現,日誌根本沒有打印到mock-service.log文件中,好比下面這個,12月29的調用日誌,打到了27號的log文件中了
python

解決思路:

一、第一次嘗試:

爲了找到緣由,以前有些調用log打印是寫在init方法裏面,而後下面的方法用self.log進行調用,後面爲了解決這個問題,把全部init裏面的初始化都去掉了,如今我以爲問題可能仍是出在調用上,日誌封裝應該沒有問題。如今這個項目有些是類方法在打印日誌,有些是封裝的函數在打印日誌。整個項目是用flask框架寫的,而後啓動run.py文件,我以爲多是出如今了某一個地方的調用一直佔用了日誌打印的進程,致使後面再調用日誌打印的時候打印到了以前的文件中,只是一個猜想,也不知道怎麼去驗證這個問題git

二、第二次嘗試

通過再一次的百度、谷歌查找,發現Python的這個自帶的logging庫是不支持多進程的,後面查到可經過以下方式進行解決這個問題github

關於logging庫不支持多進程的文章:
https://juejin.im/post/5bc2bd3a5188255c94465d31
https://zhuanlan.zhihu.com/p/29557920shell

  • 自行對logging庫重寫,以解決該問題
  • 經過別人已封裝好的第三方庫

我選擇第二種方式,不重複造輪子,通過一番對比,最終選擇了這個第三方庫concurrent_log,詳細的可去github倉庫查看,而且做者對重寫後的代碼進行了測試,證實已解決多線程、多進程的問題flask

安裝方式:

pip3 install concurrent_log

github地址:

https://github.com/huanghyw/concurrent_logcentos

關於本身對logging庫重寫也是能夠的,下面介紹幾篇重寫的文章

  • https://www.cnblogs.com/restran/p/4743840.html
  • https://www.jianshu.com/p/d874a05edf19
相關文章
相關標籤/搜索