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)