在编码Python相当一段时间后,今天我需要做一些应该很简单的事情,但是花了将近半个小时的时间才能弄清楚它,结果也不是预期的。
内容
一个简单的问题
有必要根据环境变量将日志级别设置为数据库连接时,问题就会出现。作为ORM,该项目使用peewee,这使我们能够利用Python的标准日志记录LIB拦截Peewee日志流并进行一些操纵,例如更改流的日志级别。
根据Peewee的doc,当需要将所有查询打印到stderr时,我们只需要实现以下内容。
import logging
logger = logging.getLogger('peewee')
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.DEBUG)
那生产呢?
一旦我读取了将其部署到生产的代码,例如错误,例如,将更加适用于显示数据库中不必要的信息。
必须仔细设置日志以将应用程序安全风险保持在最低限度,因为带有太多信息的日志级别可以公开数据库的结构和敏感数据。
光在隧道的尽头
选择解决此问题的方法是将一个环境变量添加到名为db_log_level的.ENV文件,这样,该应用程序的应用程序可能会根据环境的debug和误差级别而有所不同。
接下来,我们需要一种方法来将一些metaprogramming应用于动态致电logging.debug,因为日志级别的应用程序正在采用时,随着事实来自env(“ db_log_level”)。
。为此,我们可以使用内置的getattr(…)函数,该功能将返回对象的命名属性的值,其中名称必须是字符串。了解此功能,让我们看看我们的代码现在的外观。
import logging
from os import get_env
level = get_env("DB_LOG_LEVEL", "DEBUG")
logger = logging.getLogger("peewee")
logger.addHandler(logging.StreamHandler())
logger.setLevel(getattr(logging, level))
i还添加了一个验证,该验证检查get_env(...)
函数返回的值是否与log levels present in the logging library相匹配,该函数显示以下实现。
import logging
from os import get_env
"""
---------------------------------------------------------------------------
Database logging
--------------------------------------------------------------------------
Database logging will define when and how log info will be shown while
interacting with the database. Accepted log levels are CRITICAL, ERROR,
WARNING, INFO, DEBUG and NOTSET.
"""
LOG_LEVELS = [
"CRITICAL",
"FATAL",
"ERROR",
"WARNING",
"WARN",
"INFO",
"DEBUG",
"NOTSET",
]
LOG_LEVEL = get_env("DB_LOG_LEVEL", "DEBUG")
if LOG_LEVEL not in LOG_LEVELS:
raise Exception(f"DatabaseLogError: Log level '{LOG_LEVEL}' not defined")
logger = logging.getLogger("peewee")
logger.addHandler(logging.StreamHandler())
logger.setLevel(getattr(logging, LOG_LEVEL))
logging.DEBUG
使用元编程来解决此问题,允许我们动态访问对象logging
的属性,将有效的日志级传递到logger.setLevel(...)
函数中。
我是巴西工程师杰克·米拉斯
快乐编码!