Python多程式記錄日誌

阿債發表於2012-05-15

 

用gevent(或封裝了gevent的gunicore)啟動python程式,會出現多個獨立程式同時寫一個日誌檔案,

可以觀察到有日誌部分丟失:一個程式日誌沒寫完,另一個程式把日誌覆蓋在同一行的後面;有些日誌甚至完全丟失。

用mlogging包可以解決多程式寫日誌的問題,沒有發現不完整的日誌,是否丟失日誌有待進一步檢測。

下面是一個在python程式中記錄重要資訊,以便以後解析統計的函式

 

 

# -*- coding: utf-8 -*-

import os.path
import logging
from mlogging import FileHandler_MP, TimedRotatingFileHandler_MP
from functools import partial


class LevelFilter(logging.Filter):

    def __init__(self, level, *args, **kwargs):
        #super(LevelFilter, self).__init__(*args, **kwargs)
        self.level = level

    def filter(self, record):
        return record.levelno == self.level


def init_info_logger(name, logging_dir):
    logging_file = os.path.join(logging_dir, name+".log")
    handler = TimedRotatingFileHandler_MP(logging_file, "midnight", 1)
    handler.setFormatter( logging.Formatter(
        "%(asctime)s %(levelname)-8s %(name)-20s %(message)s", #設定日誌格式,固定寬度便於解析
        datefmt = "%Y-%m-%d %H:%M:%S" #設定asctime時間格式
    ))
    handler.suffix = "%Y%m%d"
    #只記錄INFO級別資訊,拋棄上面的WARNING、ERROR、CRITICAL幾個級別
    handler.addFilter( LevelFilter(logging.INFO) )

    logger = logging.getLogger(name)
    logger.setLevel(logging.INFO)
    #有些Python版本會報錯KeyError,找不到clientip或user,這裡用一個短橫(-)做預設值
    extra={"clientip":"-", "user":"-"}
    #exc_info是出錯時的Debug詳細回溯資訊,這裡禁止記錄,只記錄錯誤資訊這一行
    setattr(logger, "info", partial(logger.info, exc_info=False, extra=extra))
    logger.addHandler( handler )
    return logger


def init_error_logger(logging_dir):
    logging_file = os.path.join(logging_dir, "errors.log")
    handler = FileHandler_MP(logging_file)
    handler.setFormatter( logging.Formatter(
        "%(asctime)s %(levelname)-8s %(message)s", #設定日誌格式,固定寬度便於解析
        datefmt = "%Y-%m-%d %H:%M:%S" #設定asctime時間格式
    ))

    logger = logging.getLogger()
    logger.setLevel(logging.WARNING)
    #有些Python版本會報錯KeyError,找不到clientip或user,這裡用一個短橫(-)做預設值
    extra={"clientip":"-", "user":"-"}
    #exc_info是出錯時的Debug詳細回溯資訊
    setattr(logger, "critical", partial(logger.critical, exc_info=True, extra=extra))
    setattr(logger, "error", partial(logger.error, exc_info=True, extra=extra))
    setattr(logger, "warning", partial(logger.warning, exc_info=True, extra=extra))
    logger.addHandler( handler )
    return logger


if __name__ == "__main__":
    logger = init_info_logger("test", "./")
    logger.debug("低階別的DEBUG,不會記錄。")
    logger.info("哈哈哈,這才是我想要的資訊,請記下來。")
    logger.error("高階別的ERROR,也被過濾掉。")


相關文章