2009-06-01 1 views
14

今私は、私たちのデータベースにログするために使用されるPythonロギングモジュールの拡張を作成し実装する必要があります。基本的に、私たちは現在、テキストファイルのランダムな不具合にログオンしているいくつかのpythonアプリケーション(すべてがバックグラウンドで実行されています)を持っています。特定のアプリケーションが失敗したかどうかを知ることはほとんど不可能です。Oracleに接続するためのロギング・ハンドラの作成?

問題は、上記のロギングをテキストファイルに移動してOracle DBに移動することです。テーブルはすでに定義されており、どこにログを記録する必要があるのか​​は分かりますが、DBにログする別のロギングハンドラを追加しています。

私はpython 2.5.4とcx_Oracleを使用していますが、一般的にアプリケーションはサービス/デーモンまたはストレートアプリケーションとして実行できます。

私は主に、これについて最善の方法があるかどうか不思議です。いくつかの質問:

  1. 何らかのエラーがこれらのエラーがにログインする必要がありますcx_Oracle、で発生した場合は?もしそれが落ちたら、ロガーをデフォルトのテキストファイルに戻すのが一番良いでしょうか?

  2. 私たちは、printの代わりにsys.stderr/stdout.writeを使用するように強制していました。最悪の場合、印刷が廃止される問題は発生しません。何千ものsys.std呼び出しのすべてをシームレスにロガーにパイプして、ロガーがスラックをピックアップできるようにする方法はありますか?

  3. すべてのログメッセージの後に、スクリプトが自動的にコミットする必要がありますか? (数十秒になるでしょう)

  4. ロギングシステム用の新しいハンドラを実装する最良の方法は何ですか?基本的なHandlerクラスから継承するのは最も簡単なようです。

任意のアイデアや提案が素晴らしいでしょう。

+0

Oracleの外部表定義をファイルにバインドするだけですか?多くの点で、これは両方の世界で最も優れています。ロギング・コードを変更する必要はなく、ファイルをOracle表として扱うことができます。これは、明らかに、テーブル構造にマップできるファイルに一貫した構造がある場合に最適です。 – dpbradley

答えて

20
  1. cx_Oracleでエラーが発生した場合は、これらのファイルをテキストファイルに記録することをお勧めします。
  2. sys.stdoutとsys.stderrをファイルに似たオブジェクトにリダイレクトして、ロガーに書き込まれたものをロガーに記録することができます。
  3. 私はあなたがこれをしない強い理由がない限り、各イベントの後にコミットしたいと思います。あるいは、いくつかのイベントをバッファリングし、それらをすべて1回のトランザクションで頻繁に書き込むことができます。
  4. 以下はmx.ODBCを使用する例ですが、おそらくこれをcx_Oracleにあまり問題なく適用できます。それはPython DB-API 2.0に準拠していることを意味しています。 (ログは、Pythonに追加される前に)

スタンドアロンPythonのログ配布はhttp://www.red-dove.com/python_logging.htmlにあり、Pythonでloggingパッケージは、はるか日までですが、スタンドアロンの分布は有用な例をたくさん持っているテストディレクトリが含まれています派生したハンドラクラスの照会やエラーを報告するために、データベース・ロギングに移動したい場合は、テキストファイルへの書き込みを続けると考えている - 私はそれを「答え」考えていないので、コメントとしてこれを追加する

#!/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") 
関連する問題