Flask + sqlalchemy расширенная регистрация

Я нашел несколько других постов на эту тему, но ни одна из них не работала для меня, поэтому я хотел обратиться и посмотреть, сможет ли кто-нибудь объяснить, как правильно получить / перенаправить / установить обработчики на некоторых регистраторах, присутствующих в Flask / Werkzeurg / sqlalchemy.

Исследования до этого не смогли ответить на мой вопрос:

https://github.com/pallets/flask/issues/1359

http://flask.pocoo.org/docs/dev/logging/

https://gist.github.com/ibeex/3257877

Мои конфигурации:

main.py

    ...

    def init_app():
    """ Runs prior to app launching, contains initialization code """

    # set logging level
    if not os.path.exists(settings.LOG_DIR):
        os.makedirs(settings.LOG_DIR)

    # default level
    log_level = logging.CRITICAL

    if settings.ENV == 'DEV':
        log_level = logging.DEBUG
    elif settings.ENV == 'TEST':
        log_level = logging.WARNING
    elif settings.ENV == 'PROD':
        log_level = logging.ERROR

    log_formatter = logging.Formatter("[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s")
    api_logger = logging.getLogger()
    api_handler = TimedRotatingFileHandler(
            settings.API_LOG_FILE,
            when='midnight',
            backupCount=10
        )
    api_handler.setLevel(log_level)
    api_handler.setFormatter(log_formatter)
    api_logger.addHandler(api_handler)
    logging.getLogger('werkzeug').addHandler(api_handler)


    db_logger = logging.getLogger('sqlalchemy')
    db_handler = TimedRotatingFileHandler(
            settings.DB_LOG_FILE,
            when='midnight',
            backupCount=10
        )
    db_handler.setLevel(log_level)
    db_handler.setFormatter(log_formatter)
    db_logger.addHandler(db_handler)
    logging.getLogger('sqlalchemy.engine').addHandler(db_handler)
    logging.getLogger('sqlalchemy.dialects').addHandler(db_handler)
    logging.getLogger('sqlalchemy.pool').addHandler(db_handler)
    logging.getLogger('sqlalchemy.orm').addHandler(db_handler)



# add endpoints

...


if __name__ == '__main__':
    init_app()
    app.run(host='0.0.0.0', port=7777)

Я попытался захватить и изменить настройки на регистраторах несколькими различными способами, но я все равно получаю вывод отладки werkzeug на консоль, а не мои журналы, я вижу, что журналы создаются, но не похоже, что регистраторы действительно выводят им:

api.log (форматировщик написал ему)

2018-02-15 12:03:03,944] {/usr/local/lib/python3.5/dist-packages/werkzeug/_internal.py:88} WARNING -  * Debugger is active!

db.log (пусто)

Любое понимание этого будет высоко ценится!

ОБНОВИТЬ

Мне удалось заставить регистратор werkzeug работать с использованием длинной версии, кажется, что показанные сокращенные вызовы функций возвращали нулевые объекты. Регистратор sqlalchemy все еще выводит на консоль. Может ли конфигурация движка переопределить мой обработчик файлов?

main.py

...

# close current file handlers
for handler in copy(logging.getLogger().handlers):
    logging.getLogger().removeHandler(handler)
    handler.close()
for handler in copy(logging.getLogger('werkzeug').handlers):
    logging.getLogger('werkzeug').removeHandler(handler)
    handler.close()
for handler in copy(logging.getLogger('sqlalchemy.engine').handlers):
    logging.getLogger('sqlalchemy.engine').removeHandler(handler)
    handler.close()
for handler in copy(logging.getLogger('sqlalchemy.dialects').handlers):
    logging.getLogger('sqlalchemy.dialects').removeHandler(handler)
    handler.close()
for handler in copy(logging.getLogger('sqlalchemy.pool').handlers):
    logging.getLogger('sqlalchemy.pool').removeHandler(handler)
    handler.close()
for handler in copy(logging.getLogger('sqlalchemy.orm').handlers):
    logging.getLogger('sqlalchemy.orm').removeHandler(handler)
    handler.close()


# create our own custom handlers
log_formatter = logging.Formatter("[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s")
api_handler = TimedRotatingFileHandler(
        settings.API_LOG_FILE,
        when='midnight',
        backupCount=10
    )
api_handler.setLevel(log_level)
api_handler.setFormatter(log_formatter)
logging.getLogger().setLevel(log_level)
logging.getLogger().addHandler(api_handler)
logging.getLogger('werkzeug').setLevel(log_level)
logging.getLogger('werkzeug').addHandler(api_handler)


db_handler = TimedRotatingFileHandler(
        settings.DB_LOG_FILE,
        when='midnight',
        backupCount=10
    )
db_handler.setLevel(log_level)
db_handler.setFormatter(log_formatter)
logging.getLogger('sqlalchemy.engine').addHandler(db_handler)
logging.getLogger('sqlalchemy.engine').setLevel(log_level)
logging.getLogger('sqlalchemy.dialects').addHandler(db_handler)
logging.getLogger('sqlalchemy.dialects').setLevel(log_level)
logging.getLogger('sqlalchemy.pool').addHandler(db_handler)
logging.getLogger('sqlalchemy.pool').setLevel(log_level)
logging.getLogger('sqlalchemy.orm').addHandler(db_handler)
logging.getLogger('sqlalchemy.orm').setLevel(log_level)

database.py

...
engine = create_engine(getDBURI(), echo="debug", echo_pool=True, pool_recycle=10)

ОТВЕТ

Для дальнейшего использования, если кто-то столкнется с этой проблемой, конфигурация движка sqlalchemy echo=True|'debug' переопределит ваши регистраторы. Исправлена ​​проблема, меняющая конфигурацию двигателя на:

engine = create_engine(getDBURI(), echo_pool=True, pool_recycle=10)

И тогда все заработало как шарм. Ура!:D

1 ответ

Решение

Насколько я понимаю, ваша файловая конфигурация журнала для werkzeug на самом деле работает => она выводит в api.log

Обработчик журнала базы данных также работает (файл создается и т. Д.), Но не выводится. Вероятно, это связано с тем, что уровень логирования этих регистраторов по умолчанию равен Error. Вам нужно установить их вручную на более низком уровне, как это:

logging.getLogger('sqlalchemy.engine').setLevel(logging.DEBUG)
logging.getLogger('sqlalchemy.dialects').setLevel(logging.DEBUG)
logging.getLogger('sqlalchemy.pool').setLevel(logging.DEBUG)
logging.getLogger('sqlalchemy.orm').setLevel(logging.DEBUG)

Вероятно, что werkzeug все еще выводит на консоль, возможно, потому что всегда определен корневой логгер. Прежде чем добавлять новые обработчики, вы должны сделать следующее, чтобы удалить все обработчики журнала:

    for handler in copy(logging.getLogger().handlers):
        logging.getLogger().removeHandler(handler)
        handler.close()  # clean up used file handles

Затем вы также можете назначить обработчик журнала приложения в качестве корневого обработчика журнала с помощью

logging.getLogger().addHandler(api_handler)

Если это не корневой регистратор, а только регистратор werkzeug, для которого определен консольный регистратор по умолчанию, вы также можете просто удалить все обработчики из регистратора werkzeug, прежде чем добавлять свои:

    for handler in copy(logging.getLogger('werkzeug').handlers):
        logging.getLogger('werkzeug').removeHandler(handler)
        handler.close()  # clean up used file handles
    logging.getLogger('werkzeug').addHandler(api_handler)
Другие вопросы по тегам