方法:Python TimedRotatingFileHandle用于多个流程实例和文件?

时间:2016-01-08 15:47:07

标签: python logging rotation

我的新合同让我陷入了沉重的境地。当前系统使用python日志记录模块进行定时日志文件轮换。问题是作为守护程序运行的进程的日志文件是否正确旋转,而完成时创建和销毁的进程实例的另一个日志文件不会旋转。永远。我现在必须找到解决这个问题的方法。在对互联网和python文档进行了2天的研究之后,我只有一半在黑暗中。由于我是记录模块的新手,因此我无法看到问题的答案,因为我可能闭着眼睛看着它!

该过程以:

开始
python /admin/bin/fmlog.py -l 10 -f /tmp/fmlog/fmapp_log.log -d

其中:

-l 10 => DEBUG logging-level
-f ... => Filename to log to for app-instance 
-d => run as daemon

以下显示了我的代码的大量编辑版本:

#!/usr/bin python

from comp.app import app, yamlapp
...
from comp.utils.log4_new import *

# Exceptions handling class
class fmlogException(compException): pass

class fmlog(app):
    # Fmlog application class
    def __init__(self, key, config, **kwargs):
        # Initialise the required variables
        app.__init__(self, key, config, **kwargs)
        self._data = {'sid': self._id}
        ...

    def process(self, tid=None):
        if tid is not None:
            self.logd("Using thread '%d'." % (tid), data=self._data)

        # Run the fmlog process
        self.logi("Processing this '%s'" % (filename), data=self._data)
        ...

    def __doDone__(self, success='Failure', msg='', exception=None):
        ...
        self.logd("Process done!")

if __name__ == '__main__':
    def main():
        with yamlapp(filename=config, cls=fmlog, configcls=fmlogcfg, sections=sections, loglevel=loglevel, \
        logfile=logfile, excludekey='_dontrun', sortkey='_priority', usethreads=threads, maxthreads=max, \
        daemon=daemon, sleep=sleep) as a:
            a.run()

   main()

yamlapp进程(app的子类)被实例化并作为守护进程运行,直到手动停止。此过程将仅创建fmlog类的一个或多个实例,并在需要时调用process()函数(满足某些条件)。如果yamlapp进程以线程模式运行,则每个线程最多可以创建x个实例。

应用程序进程代码:

#!/usr/bin/env python
...
from comp.utils.log4_new import *

class app(comp.base.comp, logconfig, log):
    def __init__(self, cls, **kwargs):
        self.__setdefault__('_configcls', configitem)
        self.__setdefault__('_daemon', True)
        self.__setdefault__('_maxthreads', 5) 
        self.__setdefault__('_usethreads', False)
        ...

        comp.base.comp.__init__(self, **kwargs)
        logconfig.__init__(self, prog(), **getlogkwargs(**kwargs))
        log.__init__(self, logid=prog())

    def __enter__(self):
        self.logi(msg="Starting application '%s:%s' '%d'..." % (self._cls.__name__, \
            self.__class__.__name__, os.getpid()))

        return self

    def ...

    def run(self):
        ...
        if self._usethreads:
            ...

        while True:
            self.logd(msg="Start of run iteration...")
            if not self._usethreads:
                while not self._q.empty():
                    item = self._q.get()
                    try:
                        item.process()

            self.logd(msg="End of run iteration...")
            time.sleep(self._sleep)

日志配置和设置是通过log4_new.py类完成的:

#!/usr/bin/env python

import logging
import logging.handlers
import re

class logconfig(comp):
    def __init__(self, logid, **kwargs):
        comp.__init__(self, **kwargs)
        self.__setdefault__('_logcount', 20)
        self.__setdefault__('_logdtformat', None)
        self.__setdefault__('_loglevel', DEBUG)
        self.__setdefault__('_logfile', None)
        self.__setdefault__('_logformat', '[%(asctime)-15s][%(levelname)5s] %(message)s')
        self.__setdefault__('_loginterval', 'S')
        self.__setdefault__('_logintervalnum', 30)
        self.__setdefault__('_logsuffix', '%Y%m%d%H%M%S')

        self._logid = logid
        self.__loginit__()

    def __loginit__(self):
        format = logging.Formatter(self._logformat, self._logdtformat)

        if self._logfile:
            hnd = logging.handlers.TimedRotatingFileHandler(self._logfile, when=self._loginterval, interval=self._logintervalnum, backupCount=self._logcount)
            hnd.suffix = self._logsuffix
            hnd.extMatch = re.compile(strftoregex(self._logsuffix))
        else:
            hnd = logging.StreamHandler()
        hnd.setFormatter(format)

        l = logging.getLogger(self._logid)
        for h in l.handlers:
            l.removeHandler(h)

        l.setLevel(self._loglevel)
        l.addHandler(hnd)

class log():
    def __init__(self, logid):
        self._logid = logid

    def __log__(self, msg, level=DEBUG, data=None):
        l = logging.getLogger(self._logid)
        l.log(level, msg, extra=data)

    def logd(self, msg, **kwargs):
        self.__log__(level=DEBUG, msg=msg, **kwargs)

    def ...

    def logf(self, msg, **kwargs):
        self.__log__(level=FATAL, msg=msg, **kwargs)

def getlogkwargs(**kwargs):
    logdict = {}
    for key, value in kwargs.iteritems():
        if key.startswith('log'): logdict[key] = value

    return logdict        

日志记录按预期完成:yamlapp(app的子类)的日志写入fmapp_log.log,fmlog的日志写入fmlog.log。 问题是fmapp_log.log按预期旋转,但fmlog.log永远不会旋转。我该如何解决这个问题?我知道进程必须连续运行才能进行旋转,这就是为什么只使用一个记录器的原因。我怀疑必须为fmlog进程创建另一个句柄,当进程退出时,它必须永远不会被销毁。

要求: 应用程序(框架或主要)日志和fmlog(进程)日志必须是不同的文件。 两个日志文件都必须按时间旋转。

希望有人能理解上述内容,并能给我一些指示。

0 个答案:

没有答案