基于Django + Celery的应用程序的动态(即运行时可配置)日志配置

时间:2013-04-30 22:19:39

标签: python django logging dynamic celery

我们需要在运行时自定义服务器上的日志级别。我们正在使用Django构建SAAS应用程序,并且我们必须能够最终为每个租户启用日志记录。我正在努力寻找最好的方法。

作为第一步,我创建了一种动态更改日志级别(整个应用程序)的方法。我看到没有这样做的例子。我要注意到目前为止一个人是否尝试过这样的事情,我应该注意哪些陷阱。

到目前为止,这是我的代码。感谢是否有人可以阐明我将遇到的具体陷阱。还要了解如何控制每个租户和模块的日志记录,而不是为每个模块创建每个租户的记录器:

import threading
import logging.config
import time
import os
import traceback

class LogConfigWatcher(threading.Thread):
    def __init__(self, storage, location):
        self.last_known_time = None
        self.storage = storage
        self.location = location
        threading.Thread.__init__(self)

    def run(self):
        while True:
            mod_time = os.path.getmtime(self.location)
            if(mod_time != self.last_known_time):
                try:
                    with file(self.location) as f:
                        print("Configuring logging . . .")
                        config = eval(f.read())
                        logging.config.dictConfig(config['handler_config'])
                        logging.config.dictConfig(config['logger_config'])
                    self.last_known_time = mod_time
                except:
                    traceback.print_exc()
                    print "Failed to Configure the log"
                    pass
            time.sleep(5)

class LogConfigHolder(object):
    def __init__(self, storage, location):
        self.storage = storage
        self.location = location

        self.initialize(storage, location)

    def initialize(self, storage, location):
        self.pid = os.getpid()
        print "Starting thread for %s" % self.pid
        self.thread = LogConfigWatcher(storage, location)
        self.thread.setDaemon(True)
        self.thread.start()

    def is_alive(self):
        if os.getpid() != self.pid:
            return False
        return self.thread.isAlive()

    def restart(self):
        if not self.is_alive():
            self.initialize(self.storage, self.location)

2 个答案:

答案 0 :(得分:0)

我很确定您的代码与Logging模块本身的编写者已经想到的相近。

在程序中使用单独的线程,每次发生日志记录事件时都会侦听配置请求。反过来,日志服务器保存您可以调整的配置文件。更改将在下一次记录事件中被选中。

Logger模块的原作者可能会为您提供更多见解here,请注意本手册有点过时。用于日志记录的官方Python文档有一个配置此类日志服务器/客户端设置的示例:Logging Cookbook

而且,随着复杂性的增加,这种设置确实会对性能产生轻微影响。

答案 1 :(得分:0)

我写了一个应用来解决这个问题。配置在数据库中,可以保存许多配置,在可配置的日期/时间只有一个是活动的。

为了解决重新加载新配置的问题,我创建了3个策略来传播新的配置:

  • 收听配置模型更改的信号并更新配置(在单声道处理环境中工作)
  • 每隔几分钟用线程(比如您的代码)检查新配置
  • 侦听配置更改的信号,但通过amqp消息后端传播事件。 (这是最优化的解决方案)。

检查https://github.com/Yupeek/django-dynamic-logging