Динамическая (то есть настройка времени выполнения) Конфигурация журнала для приложения на основе Django + Celery

Нам нужно настроить уровни журналов на сервере во время выполнения. Мы создаем приложение SAAS с использованием Django, и мы должны иметь возможность включить ведение журнала для каждого арендатора. Я пытаюсь найти лучший способ сделать это.

В качестве первого шага я создал способ динамически изменять уровни журналов (для всего приложения). Я вижу, что нет примеров этого. Я уверен, что если кто-то попробовал что-то подобное до сих пор, и каковы подводные камни, за которыми я должен следить.

Вот мой код до сих пор. Цените, если кто-нибудь сможет пролить свет на определенные подводные камни, с которыми я столкнулся. Также оцените любые данные о том, как управлять протоколированием для каждого арендатора и модуля, кроме создания регистратора на каждого арендатора на модуль:

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» .

И, как всегда, когда сложность возрастает, такая настройка имеет небольшое влияние на производительность.

Я написал приложение для решения этой проблемы. конфигурация находится в базе данных, и многие конфигурации могут быть сохранены, причем ровно один активен в настраиваемой дате / времени.

чтобы решить проблему перезагрузки новой конфигурации uppon change, я создал 3 политики для распространения новой конфигурации:

  • прослушать сигнал для изменения конфигурации модели и обновить конфигурацию (работа в режиме mono process env)
  • проверять новую конфигурацию каждые минуты с помощью потока (например, вашего кода)
  • прослушивать сигнал для изменения конфигурации, но распространять событие через сервер сообщений amqp. (это наиболее оптимизированное решение).

проверьте https://github.com/Yupeek/django-dynamic-logging