使用mod_python时Python日志模块表现不同
我们遇到了一个麻烦的问题,发现当在我们的服务器上使用mod_python时,Python的日志模块表现得和预期不一样。而在命令行、Django的runserver命令或者mod_wsgi中执行相同的代码时,表现是正常的:
import logging
logger = logging.getLogger('site-errors')
logging.debug('logger=%s' % (logger.__dict__))
logging.debug('logger.parent=%s' % (logger.parent.__dict__))
logger.error('some message that is not logged.')
接下来我们看到的日志是:
2009-05-28 10:36:43,740,DEBUG,error_middleware.py:31,[logger={'name': 'site-errors', 'parent': <logging.RootLogger instance at 0x85f8aac>, 'handlers': [], 'level': 0, 'disabled': 0, 'manager': <logging.Manager instance at 0x85f8aec>, 'propagate': 1, 'filters': []}]
2009-05-28 10:36:43,740,DEBUG,error_middleware.py:32,[logger.parent={'name': 'root', 'parent': None, 'handlers': [<logging.StreamHandler instance at 0x8ec612c>, <logging.handlers.RotatingFileHandler instance at 0x8ec616c>], 'level': 10, 'disabled': 0, 'propagate': 1, 'filters': []}]
从中可以看出,子日志记录器'site-errors'没有设置任何处理器或级别。
日志的配置是在settings.py文件中完成的:
MONITOR_LOGGING_CONFIG = ROOT + 'error_monitor_logging.conf'
import logging
import logging.config
logging.config.fileConfig(MONITOR_LOGGING_CONFIG)
if CONFIG == CONFIG_DEV:
DB_LOGLEVEL = logging.INFO
else:
DB_LOGLEVEL = logging.WARNING
第二个问题是,我们在与error_middleware.py同一文件夹中的__init__.py里添加了一个自定义处理器:
import logging
from django.conf import settings
from db_log_handler import DBLogHandler
handler = DBLogHandler()
handler.setLevel(settings.DB_LOGLEVEL)
logging.root.addHandler(handler)
但是在日志中看不到这个自定义处理器!
如果有人知道问题出在哪里,请告诉我们!如果需要更多信息,请随时询问。这肯定会帮助我们解决问题。
3 个回答
这个问题用mod_wsgi是解决不了的。
我发现把所有的配置放在一个文件里可以解决这个问题。把文件和代码的配置混在一起,似乎会在apache上引发一些问题(无论是用mod_wsgi还是mod_python)。
为了使用自定义的日志处理器和文件配置,我需要做以下几步:
import logging
import logging.config
logging.custhandlers = sitemonitoring.db_log_handler
logging.config.fileConfig(settings.MONITORING_FILE_CONFIG)
在settings.py里我不能导入sitemonitoring.db_log_handler
,所以我得把这段代码放在根目录的urls.py
里。
在配置文件中,我用下面的语句来引用DBLogHandler
:
[handler_db]
class=custhandlers.DBLogHandler()
level=ERROR
args=(,)
附注:注意custhandler
这个“属性”是动态创建的,可以有其他名字。这是使用动态语言的一个好处。
你似乎没有提供所有相关的信息,比如,你的日志配置文件在哪里呢?
你提到:
在命令行、使用django的runserver命令,或者用mod_wsgi执行相同的代码时,行为是正确的。
你没有明确说明你展示的日志输出是来自这些环境中的哪一个,还是来自mod_python的运行。看起来没有问题——在你的代码中,你是把处理器添加到了根节点,而不是' site-errors '这个日志记录器上。你还在处理器上设置了级别,而不是在日志记录器上,所以你不会在日志输出中看到'site-errors'日志记录器的级别,对吧?级别可以在日志记录器和处理器上设置,但它们并不相同,尽管它们以相同的方式过滤事件。
关于自定义处理器的问题,如果你查看日志记录的配置文档,就能很容易理解,见
http://docs.python.org/library/logging.html(搜索“类条目表示”)
这解释了配置文件中描述的任何处理器类都会在日志记录包的命名空间中被eval()。所以,通过将logging.custhandlers绑定到你的自定义处理器模块,然后在配置文件中写上“custhandlers.MyCustomClass”,eval()就会产生预期的结果。你也可以这样做:
logging.sitemonitoring = sitemonitoring
并将处理器类指定为:
sitemonitoring.db_log_handler.DBLogHandler
这样也能正常工作(前提是db_log_handler子包已经被导入)。
顺便说一下,人们有时在settings.py中配置日志时遇到问题,原因是Django的导入机制导致了循环导入的问题。我通常在settings.py中配置日志,效果很好,除非你想导入Django的某些部分(例如在django.db中——因为应用的导入逻辑在django.db中,如果你在settings.py中尝试导入django.db.x,就可能会遇到循环导入的问题)。
在 settings.py
文件中配置日志可能不是个好主意。
我们在根目录的 urls.py
文件中配置日志,这样似乎效果更好。我还没有深入研究 Django 的源代码,所以不太清楚具体原因,但对我们来说这样做很有效。我建议在这里添加一些自定义的处理程序。
另外,仔细看看 mod_wsgi。它的表现似乎比 mod_python 要好很多。