我们需要在运行时自定义服务器上的日志级别。我们正在使用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)
我很确定你给出的代码接近于日志模块本身的作者已经想到的东西。
在程序中使用一个单独的线程,在每次日志事件发生时监听配置请求。反过来,日志服务器保存您可以调整的配置文件。更改将在下一次日志事件中被拾取。
Logger模块的原作者可能会在这里为您提供更多的见解,请注意本手册有点过时。Python官方日志文档中有一个配置日志服务器/客户端设置的示例:Logging Cookbook.
而且,当复杂性增加时,这种设置确实会对性能产生轻微的影响。
我编写了一个应用程序来解决这个问题。配置在数据库中,并且可以保存许多配置,在一个可配置的日期/时间,只有一个是活动的。
为了解决更改时重新加载新配置的问题,我创建了3个策略来传播新配置:
- 监听配置模型更改的信号并更新配置(在单进程环境中工作)
- 每分钟用线程检查新配置(像你的代码)
- 侦听配置更改的信号,但通过amqp消息后端传播事件。(这是最优化的解决方案)
检查https://github.com/Yupeek/django-dynamic-logging