Пользовательский python логинг обработчик постоянно - PullRequest
0 голосов
/ 23 марта 2020

Я сталкиваюсь с какой-то проблемой зацикливания, пытаясь реализовать регистрацию в моем проекте с помощью пользовательского обработчика, поэтому я ищу помощь. У меня есть некоторый опыт программирования, но я довольно плохо знаком с python, поэтому, возможно, я все неправильно понял.

Как показано ниже, я получаю "RecursionError". Я также приложил усеченную копию ошибки и код в конце этого поста.

Заранее спасибо!

Error:

Traceback (most recent call last):
  File "app.py", line 18, in <module>
    logger.debug('debug message!')
  File "/usr/lib/python3.8/logging/__init__.py", line 1422, in debug
    self._log(DEBUG, msg, args, **kwargs)
  File "/usr/lib/python3.8/logging/__init__.py", line 1577, in _log
    self.handle(record)
  File "/usr/lib/python3.8/logging/__init__.py", line 1587, in handle
    self.callHandlers(record)
  File "/usr/lib/python3.8/logging/__init__.py", line 1649, in callHandlers
    hdlr.handle(record)
  File "/usr/lib/python3.8/logging/__init__.py", line 950, in handle
    self.emit(record)
  File "/app/python/logger_handlers.py", line 27, in emit
    requests.post(self.url, headers = header, data = json.dumps(payload))
[...truncated...]
RecursionError: maximum recursion depth exceeded in comparison
# app.py
import logging
import my_module
from logger_handlers import CustomHandler

logging.getLogger("requests").disabled = True

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# Custom handler
custom_handler = CustomHandler(url = 'http://some_url.com/api/1/log')
custom_handler.setLevel(logging.DEBUG)
custom_handler.setFormatter(formatter)
logger.addHandler(custom_handler)

# Log to root handler
logger.debug('debug message!')

# Run a function in a different module that also has a logger defined 
my_module.run()
# my_module.py
import logging

log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler())

def run():
    log.debug('A message from A Module')
# logger_handlers.py
import logging
import requests
import json

from socket import gethostname, gethostbyname

class CustomHandler(logging.Handler):

    def __init__(self, *args, **kwargs):
        super().__init__()
        self.url = kwargs['url']

    def emit(self, record):
        message = self.format(record)
        header = {"content-type": "application/json"}
        payload = {
            "token":None,
            "client_version":"",
            "parameters": {
                "source": "Host: {} ({}), Module: {}, {}".format(gethostname(), gethostbyname(gethostname()), record.filename, record.funcName),
                "severity": record.levelname,
                "message": message
            }
        }
        requests.post(self.url, headers = header, data = json.dumps(payload))

ОБНОВЛЕНИЕ (2020-04-03):

Используя этот фрагмент, я смог идентифицировать все регистраторы, которые мне пришлось отключить, чтобы избежать l oop:

for key in logging.Logger.manager.loggerDict:
    print(key)

I затем используйте это, чтобы отключить их:

logging.getLogger("urllib3.util.retry").disabled = True
logging.getLogger("urllib3.util").disabled = True
logging.getLogger("urllib3").disabled = True
logging.getLogger("urllib3.connection").disabled = True
logging.getLogger("urllib3.response").disabled = True
logging.getLogger("urllib3.connectionpool").disabled = True
logging.getLogger("urllib3.poolmanager").disabled = True
logging.getLogger("requests").disabled = True

Не очень красиво, но это работает. Пожалуйста, не стесняйтесь комментировать, если вы думаете, что этот метод имеет существенный недостаток.

Ответы [ 2 ]

0 голосов
/ 23 марта 2020

При выполнении запроса с модулем запросов создаются журналы. Некоторые из регистратора requests, а также из других используемых библиотек. Например, модуль urllib также имеет регистратор, который создает журналы. Эти журналы распространяются вверх по иерархии журналов и попадают в регистратор root. Регистратор root также имеет ваш обработчик и, таким образом, снова выполнит q-запрос, создавая больше журналов, которые заканчиваются на регистраторе root.

Добавляйте ваш обработчик только в регистраторы, которые запрашивают журналы, не распространяющиеся к.

0 голосов
/ 23 марта 2020

В вашем скрипте app.py просто передайте name в качестве параметра имени для getLogger (). Итак,

logger = logging.getLogger(__name__)
...