MySQL バックエンドに接続された SQLAlchemy で Pyramid Web フレームワークを使用しています。私がまとめたアプリは機能しますが、強化されたログ記録と例外処理によって、洗練されたものを追加しようとしています。
セッションを次のように使用して、Pyramid サイトの基本的な SQLAlchemy チュートリアルにすべて基づいています。
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
DBSession を使用してクエリを実行するとうまくいきます。データベースに何かを追加してコミットする必要がある場合は、次のようにします。
DBSession.add(myobject)
DBSession.flush()
というわけで新しいIDを取得。
次に、データベースにログを追加したかったので、このチュートリアルに従いました。それはうまくいったようです。私は最初、物事がコミットされるという奇妙なことに遭遇しました.SQLAlchemyがどのように機能しているのかわからなかったので、ログを強制的にコミットするために「transaction.commit()」を「DBSession.flush()」に変更しました(これは対処されています下!)。
次に、明示的にキャッチされなかったものすべてに分かりやすいエラー ページを配置してログに記録できるようにする目的で、カスタムの例外処理を追加したいと考えました。したがって、このドキュメントに基づいて、次のようなエラーハンドラーを作成しました。
from pyramid.view import (
view_config,
forbidden_view_config,
notfound_view_config
)
from pyramid.httpexceptions import (
HTTPFound,
HTTPNotFound,
HTTPForbidden,
HTTPBadRequest,
HTTPInternalServerError
)
from models import DBSession
import transaction
import logging
log = logging.getLogger(__name__)
#region Custom HTTP Errors and Exceptions
@view_config(context=HTTPNotFound, renderer='HTTPNotFound.mako')
def notfound(request):
log.exception('404 not found: {0}'.format(str(request.url)))
request.response.status_int = 404
return {}
@view_config(context=HTTPInternalServerError, renderer='HTTPInternalServerError.mako')
def internalerror(request):
log.exception('HTTPInternalServerError: {0}'.format(str(request.url)))
request.response.status_int = 500
return {}
@view_config(context=Exception, renderer="HTTPExceptionCaught.mako")
def error_view(exc, request):
log.exception('HTTPException: {0}'.format(str(request.url)))
log.exception(exc.message)
return {}
#endregion
だから今私の問題は、例外がキャッチされ、カスタム例外ビューが期待どおりに表示されることです。ただし、例外はデータベースに記録されません。これは、例外が発生すると DBSession トランザクションがロールバックされるためと思われます。そこで、ロギング ハンドラを「transaction.commit」に戻しました。これには、実際に例外ログをデータベースにコミットする効果がありましたが、ログステートメントの後のDBSessionアクションは、「インスタンスがセッションにバインドされていません」というエラーをスローします...これは、transaction.commitの後に理解していることから理にかなっています() セッションがクリアされます。コンソール ログには常に、ログ情報をデータベースに書き込むための SQL ステートメントなど、ログに記録したい内容が正確に表示されます。しかし、transaction.commit() を使用しない限り、例外でコミットしていません。
すっごい....データベースにログを記録するだけでなく、例外をキャッチしてデータベースに正常に記録できるようにするには、どのように設定すればよいでしょうか? ロギングハンドラーに、ある種の別のデータベースセッション/接続/インスタンス/何かを使用して自己完結型にしたい気がしますが、それがどのように機能するかは不明です。
それとも、まったく別の方法でやりたいことを設計する必要がありますか?
編集:私は、コミットログ情報をデータベースに追加することだけに特化した、別のログ固有のセッションを使用することになりました。これは、私が Pyramid コンソール スクリプトをミックスに統合し始めるまで、うまく機能しているように見えました。スクリプト内のセッションとデータベース コミットの問題に遭遇しました。実際の Pyramid Web アプリケーションのように機能するとは限りません。
後から考えると (そして私が今していること)、データベースにログを記録する代わりに、標準のログ記録と FileHandlers (具体的には TimedRotatingFileHandlers) を使用して、ファイル システムにログを記録します。