【问题标题】:Creating a logging handler to connect to Oracle? [closed]创建日志处理程序以连接到 Oracle? [关闭]
【发布时间】:2010-10-30 11:20:51
【问题描述】:

所以现在我需要创建并实现 Python 日志记录模块的扩展,用于记录到我们的数据库。基本上,我们有几个 Python 应用程序(它们都在后台运行),它们当前记录到文本文件的随机混杂中。这使得几乎不可能找出某个应用程序是否失败。

给我的问题是将所述日志记录移动到文本文件到 oracle DB。表已经定义好了,需要记录的地方,但现在,我正在考虑添加另一个将记录到数据库的日志处理程序。

我正在使用 python 2.5.4 和 cx_Oracle,应用程序通常可以作为服务/守护程序或直接应用程序运行。

我只是很好奇解决此问题的最佳方法是什么。几个问题:

  1. 如果 cx_Oracle 发生任何错误,应将这些错误记录到哪里?如果它关闭,最好让记录器退回到默认文本文件?

  2. 不久前,我们开始强制人们使用 sys.stderr/stdout.write 而不是 print,所以在最坏的情况下,我们不会遇到 print 被弃用的任何问题。有没有一种方法可以无缝地将所有数千个 sys.std 调用直接通过管道传输到记录器中,并让记录器弥补不足?

  3. 在每条记录的消息之后,脚本是否应该自动执行提交? (每秒会有几十个。)

  4. 为日志系统实现新处理程序的最佳方式是什么?从基本的 Handler 类继承似乎是最简单的。

任何想法/建议都会很棒。

【问题讨论】:

  • 将此添加为评论,因为我不认为它是“答案” - 如果您想转移到数据库日志记录以查询和报告错误,您是否考虑过继续写入文本文件,只是将 Oracle 外部表定义绑定到文件?在很多方面,这是两全其美的方式——您不必修改日志记录代码,并且可以获得将文件视为 Oracle 表的能力。如果可以映射到表结构的文件有一些一致的结构,这显然效果最好。

标签: python oracle logging


【解决方案1】:
  1. 如果 cx_Oracle 出现错误,最好将这些错误记录到文本文件中。
  2. 您可以尝试将 sys.stdout 和 sys.stderr 重定向到类似文件的对象,这些对象将写入它们的内容记录到记录器中。
  3. 我猜你确实想在每个事件之后提交,除非你有充分的理由不这样做。或者,您可以缓冲多个事件并每隔一段时间将它们全部写入一个事务中。
  4. 下面是一个使用 mx.ODBC 的例子,你可以适应 cx_Oracle 没有太多麻烦。我认为它应该符合 Python DB-API 2.0。

独立的 Python 日志记录分发版(在将日志记录添加到 Python 之前)位于 http://www.red-dove.com/python_logging.html,尽管 Python 中的日志记录包是最新的,但独立分发版包含一个测试目录,其中包含许多有用的示例派生处理程序类。

#!/usr/bin/env python
#
# Copyright 2001-2009 by Vinay Sajip. All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of Vinay Sajip
# not be used in advertising or publicity pertaining to distribution
# of the software without specific, written prior permission.
# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# This file is part of the standalone Python logging distribution. See
# http://www.red-dove.com/python_logging.html
#
"""
A test harness for the logging module. An example handler - DBHandler -
which writes to an Python DB API 2.0 data source. You'll need to set this
source up before you run the test.

Copyright (C) 2001-2009 Vinay Sajip. All Rights Reserved.
"""
import sys, string, time, logging

class DBHandler(logging.Handler):
    def __init__(self, dsn, uid='', pwd=''):
        logging.Handler.__init__(self)
        import mx.ODBC.Windows
        self.dsn = dsn
        self.uid = uid
        self.pwd = pwd
        self.conn = mx.ODBC.Windows.connect(self.dsn, self.uid, self.pwd)
        self.SQL = """INSERT INTO Events (
                        Created,
                        RelativeCreated,
                        Name,
                        LogLevel,
                        LevelText,
                        Message,
                        Filename,
                        Pathname,
                        Lineno,
                        Milliseconds,
                        Exception,
                        Thread
                   )
                   VALUES (
                        %(dbtime)s,
                        %(relativeCreated)d,
                        '%(name)s',
                        %(levelno)d,
                        '%(levelname)s',
                        '%(message)s',
                        '%(filename)s',
                        '%(pathname)s',
                        %(lineno)d,
                        %(msecs)d,
                        '%(exc_text)s',
                        '%(thread)s'
                   );
                   """
        self.cursor = self.conn.cursor()

    def formatDBTime(self, record):
        record.dbtime = time.strftime("#%m/%d/%Y#", time.localtime(record.created))

    def emit(self, record):
        try:
            #use default formatting
            self.format(record)
            #now set the database time up
            self.formatDBTime(record)
            if record.exc_info:
                record.exc_text = logging._defaultFormatter.formatException(record.exc_info)
            else:
                record.exc_text = ""
            sql = self.SQL % record.__dict__
            self.cursor.execute(sql)
            self.conn.commit()
        except:
            import traceback
            ei = sys.exc_info()
            traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
            del ei

    def close(self):
        self.cursor.close()
        self.conn.close()
        logging.Handler.close(self)

dh = DBHandler('Logging')
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
logger.addHandler(dh)
logger.info("Jackdaws love my big %s of %s", "sphinx", "quartz")
logger.debug("Pack my %s with five dozen %s", "box", "liquor jugs")
try:
    import math
    math.exp(1000)
except:
    logger.exception("Problem with %s", "math.exp")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    相关资源
    最近更新 更多