pythonロガーモジュールがデータベースにログを記録し、dbがダウンしたときにファイルシステムにフォールバックできるようにする方法を探しています。
つまり、基本的に2つのことです。ロガーにデータベースにログを記録させる方法と、データベースがダウンしたときにログをファイルロギングに落とす方法です。
問題のデータベースにログを送信するhandlerを自分で記述します。失敗した場合は、ロガーのハンドラーリストから削除できます。障害モードに対処するには多くの方法があります。
ねえ...かなりの時間が経過しましたが、最近私は自分のデータベースロガーをPythonで書くことができました。例が見つからなかったので、ここに投稿したいと思いました。多分誰かがこれが役に立つと思うでしょう:) MS SQLで動作します。
データベーステーブルは次のようになります。
CREATE TABLE [db_name].[log](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[log_level] [int] NULL,
[log_levelname] [char](32) NULL,
[log] [char](2048) NOT NULL,
[created_at] [datetime2](7) NOT NULL,
[created_by] [char](32) NOT NULL,
) ON [PRIMARY]
クラス自体:
class LogDBHandler(logging.Handler):
'''
Customized logging handler that puts logs to the database.
pymssql required
'''
def __init__(self, sql_conn, sql_cursor, db_tbl_log):
logging.Handler.__init__(self)
self.sql_cursor = sql_cursor
self.sql_conn = sql_conn
self.db_tbl_log = db_tbl_log
def emit(self, record):
# Set current time
tm = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(record.created))
# Clear the log message so it can be put to db via sql (escape quotes)
self.log_msg = record.msg
self.log_msg = self.log_msg.strip()
self.log_msg = self.log_msg.replace('\'', '\'\'')
# Make the SQL insert
sql = 'INSERT INTO ' + self.db_tbl_log + ' (log_level, ' + \
'log_levelname, log, created_at, created_by) ' + \
'VALUES (' + \
'' + str(record.levelno) + ', ' + \
'\'' + str(record.levelname) + '\', ' + \
'\'' + str(self.log_msg) + '\', ' + \
'(convert(datetime2(7), \'' + tm + '\')), ' + \
'\'' + str(record.name) + '\')'
try:
self.sql_cursor.execute(sql)
self.sql_conn.commit()
# If error - print it out on screen. Since DB is not working - there's
# no point making a log about it to the database :)
except pymssql.Error as e:
print sql
print 'CRITICAL DB ERROR! Logging to database not possible!'
そして使用例:
import pymssql
import time
import logging
db_server = 'servername'
db_user = 'db_user'
db_password = 'db_pass'
db_dbname = 'db_name'
db_tbl_log = 'log'
log_file_path = 'C:\\Users\\Yourname\\Desktop\\test_log.txt'
log_error_level = 'DEBUG' # LOG error level (file)
log_to_db = True # LOG to database?
class LogDBHandler(logging.Handler):
[...]
# Main settings for the database logging use
if (log_to_db):
# Make the connection to database for the logger
log_conn = pymssql.connect(db_server, db_user, db_password, db_dbname, 30)
log_cursor = log_conn.cursor()
logdb = LogDBHandler(log_conn, log_cursor, db_tbl_log)
# Set logger
logging.basicConfig(filename=log_file_path)
# Set db handler for root logger
if (log_to_db):
logging.getLogger('').addHandler(logdb)
# Register MY_LOGGER
log = logging.getLogger('MY_LOGGER')
log.setLevel(log_error_level)
# Example variable
test_var = 'This is test message'
# Log the variable contents as an error
log.error('This error occurred: %s' % test_var)
上記はデータベースとファイルの両方に記録されます。ファイルが必要ない場合-'logging.basicConfig(filename = log_file_path)'行をスキップします。 「log」を使用してログに記録されたすべてのもの-MY_LOGGERとしてログに記録されます。外部エラーが表示された場合(つまり、インポートされたモジュール内など)-「ルート」ロガーもアクティブであり、データベースハンドラーを使用しているため、エラーは「ルート」として表示されます。
Log4mongoライブラリを見たことはありますか? https://pypi.python.org/pypi/log4mongo/ Mongoのハンドルを提供します。フォールバックはありませんが、比較的簡単に追加できます。
私はこれを再び掘り起こしています。
SqlAlchemyを使用した解決策があります(このレシピではピラミッドは必要ありません):
https://docs.pylonsproject.org/projects/pyramid-cookbook/en/latest/logging/sqlalchemy_logger.html
そして、余分なフィールドを追加することでロギングを改善できます。ここにガイドがあります: https://stackoverflow.com/a/17558764/1115187
これが100%正しいかどうかはわかりませんが、2つのハンドラーを使用できます。
DBコミットをtry-except
でラップするだけです。ただし、ファイルにはすべてのログエントリが含まれますが、DBの保存に失敗したエントリだけが含まれることに注意してください。
古い質問ですが、他の人のためにこれをドロップします。 pythonロギングを使用する場合は、2つのハンドラーを追加できます。1つはファイルへの書き込み用、回転ファイルハンドラーです。これは堅牢で、dBが上がっているかどうかに関係なく実行できます。 。もう1つは、pymongo統合など、別のサービス/モジュールに書き込むことができます。
コードまたはjsonからハンドラーをセットアップする方法については、logging.configを調べてください。