python logging日誌記錄並異步發送

需求: 將日誌記錄異步發送到指定服務地址

實現思路:新建一個隊列,將logging的http 發送任務放入隊列中。啓動一個線程監控隊列情況,並從隊列依次取任務發送。從而將日誌記錄和日誌發送分離開,日誌發送與業務功能代碼解耦,提高運行速率。 

import pytz
import logging
from logging.handlers import RotatingFileHandler
from logging.handlers import QueueHandler
from logging.handlers import QueueListener
from logging import Handler
import os
from datetime import datetime

HOST = 'https://www.leontom.com'   # 日誌接收的域名
PATH = '/log'                      # 日誌接收path


# --------------------------------------------log queue------------------------
class SlackQueueHandler(QueueHandler):
    """日誌隊列"""
    def __init__(self, queue=None):
        QueueHandler.__init__(self, queue)

    def prepare(self, record):
        """
        Override the method to allow the formatter to work.
        """
        record.msg = self.format(record)
        record.args = None
        record.exc_info = None
        return record


class SlackQueueListener(QueueListener, Handler):
    """日誌隊列監聽者,異步發送日誌"""
    def __init__(self, queue=None):
        QueueListener.__init__(self, queue)
        Handler.__init__(self)

        secure = True if HOST.startswith('https://') else False
        self.HttpHandler = TestHTTPHandler(HOST, url=PATH, method="POST", secure=secure)

    def handle(self, record):
        """
        Override the QueueListener.handle method with the Handler.handle
        method
        """
        Handler.handle(self, record)

    def emit(self, record):
        # msg = self.format(record)
        self.HttpHandler.emit(record)
# --------------------------------------------log queue------------------------


class TestHTTPHandler(logging.handlers.HTTPHandler):
    """HTTP Log日誌發送"""
    def __init__(self, host, url, method="POST", secure=False, credentials=None, context=None, report_id=None):
        super().__init__(host, url, method=method, secure=secure, credentials=credentials, context=context)
        self.report_id = report_id

    def mapLogRecord(self, record):
        """發送內容"""
        tz = pytz.timezone('Asia/Shanghai')
        asctime = datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
        if hasattr(record,'name') and hasattr(record, 'message'):
            data = {"asctime":asctime, "name": record.name, "message":record.message}
        else:
            data = {"asctime":asctime, "name": 'requests', "message": str(record)}
        record_ = '%(asctime)s | %(name)s | %(message)s' % dict(data)
        record_msg = {'record': record_}
        print('----record msg----{}'.format(record_msg))
        return record_msg


class TestLogger():
    def __init__(self, filePath, fileName):
        self.filePath = filePath                     # 存放文件的路徑
        self.fileName = fileName                     # 存放文件的名字
        # self.BACK_UP_COUNT = 5000                  # 文件分割上限數
        # self.MAX_LOG_BYTES = 1024 * 1024 * 10      # 單個文件最大記錄數10M
        self.create_handler()                        # 初始化創建日誌handler
        self.create_logger()                         # 初始化創建Logger

    def create_handler(self):
        """建立handler"""
        self.handler = RotatingFileHandler(filename=os.path.join(self.filePath, self.fileName),
                                           # maxBytes=self.MAX_LOG_BYTES,
                                           # backupCount=self.BACK_UP_COUNT,
                                           delay=1
                                           )
        formatter = logging.Formatter('%(asctime)s | %(name)s | %(message)s')         # 設定輸出格式
        # formatter.converter = time.gmtime                                           # 時間轉換
        self.handler.setFormatter(formatter)                                          # 格式加載到handler
        secure = True if HOST.startswith('https://') else False
        log_host = HOST.replace('https://', '').replace('http://', '')
        self.http_handler = TestHTTPHandler(host=log_host, url=PATH, secure=secure)   # 域名不帶http:// , secure=False 表示http, secure=True 表示https 請求

    def create_logger(self):
        """建立Logger"""
        self.mylogger = logging.getLogger('testlog')

    def log(self, msg):
        self.mylogger.info(msg)
        self.http_handler.emit(record=msg)


if __name__ == '__main__':
    logger = TestLogger(filePath='./', fileName='test1.logs')
    logger.log('---test msg---')

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章