エラーレポートの管理¶
サイトを公開している場合、DEBUG
設定は常にオフにしておかなければなりません。これにより、サーバー動作は高速になり、エラーページによって明らかになるアプリケーションの詳細が悪意あるユーザーに漏れるのを防ぎます。
しかし、 DEBUG
を False
にセットして実行すると、サイトによって生成されるエラーが見られなくなります――表示されるのは万人向けのエラーページだけです。そこで、本番サイトで起きたエラーを追跡するために、Django ではこれらのエラーに関する詳細なレポートを作成するように設定できます。
E メールのレポート¶
サーバーエラー¶
DEBUG
が False
であるとき、コードがハンドリングされない例外を起こして内部サーバーエラーが起きると (厳密には、500 以上の HTTP ステータスコードを持つ全てのレスポンスが返ってくると)、Django は ADMINS
設定のリストに含まれるユーザーにメールを送信します。これにより、管理者はすぐにエラーの通知を受け取ることができます。メールには、ADMINS
はエラーの説明、Python のトレースバック全体、エラーを引き起こした HTTP リクエストの詳細について書かれています。
注釈
メールを送信するために、Django はメールサーバーへの接続方法をいくつか設定する必要があります。最低限 EMAIL_HOST
と、おそらく EMAIL_HOST_USER
と EMAIL_HOST_PASSWORD
を指定する必要がありますが、メールサーバーの設定によっては他の設定も必要かもしれません。メール関連の設定の一覧は Django の設定のドキュメント を参照してください。
デフォルトでは、 Django は root@localhost からメールを送信します。しかし、メールプロバイダによっては、このアドレスからのメールを全て拒否します。別の送信者アドレスを使うには、 SERVER_EMAIL
設定を変更してください。
この動作を有効にするには、受信者のメールアドレスを ADMINS
設定に含めます。
参考
サーバーエラーのメールはロギングフレームワークを使って送信されるので、 ロギングの設定をカスタマイズする ことで動作を変更できます。
404 エラー¶
Django は、リンク切れに関するエラー (404 "page not found" エラー) をメールで送信するように設定することもできます。Django は以下の場合に 404 エラーに関するメールを送ります:
DEBUG
がFalse
のとき;MIDDLEWARE
設定にdjango.middleware.common.BrokenLinkEmailsMiddleware
が含まれているとき。
これらの条件が満たされると、Django はあなたのコードが 404 を発生させ、そのリクエストがリファラを持っている場合、 MANAGERS
設定にリストされているユーザにメールを送ります。リファラを持たない 404 にはわざわざメールを送りません。それは大抵、壊れた URL を入力したユーザか、壊れた Web ボットです。また、リファラがリクエストされた URL と同じ場合の 404 も無視します。
注釈
BrokenLinkEmailsMiddleware
は、 LocaleMiddleware
や FlatpageFallbackMiddleware
のような 404 エラーを検出する他のミドルウェアよりも前に表示する必要があります。これを MIDDLEWARE
設定の一番上に置いてください。
特定の 404 を報告しないように Django に指示するには、 IGNORABLE_404_URLS
設定をいじります。これはコンパイルされた正規表現オブジェクトのリストでなければなりません。例えば:
import re
IGNORABLE_404_URLS = [
re.compile(r"\.(php|cgi)$"),
re.compile(r"^/phpmyadmin/"),
]
この例では、 .php
または .cgi
で終わる URL への 404 は報告されません。また、 /phpmyadmin/
で始まるURLも報告されません。
以下は、ブラウザやクローラがよくリクエストする従来の URL を除外する方法の例です:
import re
IGNORABLE_404_URLS = [
re.compile(r"^/apple-touch-icon.*\.png$"),
re.compile(r"^/favicon\.ico$"),
re.compile(r"^/robots\.txt$"),
]
(これらは正規表現なので、ピリオドの前にバックスラッシュを入れてエスケープしていることに注意してください)
django.middleware.common.BrokenLinkEmailsMiddleware
の動作をさらにカスタマイズしたい場合(例えば、ウェブクローラからのリクエストを無視したい場合など)は、サブクラスを作成し、そのメソッドをオーバーライドしてください。
参考
404エラーはロギングフレームワークを使って記録されます。デフォルトではこれらのログレコードは無視されますが、ハンドラを書いて ロギングを適切に設定する ことで、エラー報告に使うことができます。
エラーレポートをフィルタリングする¶
警告
機密データのフィルタリングは難しい問題であり、機密データがエラーレポートに漏れないことを保証することはほとんど不可能です。したがって、エラーレポートは信頼できるチームメンバーのみが利用できるようにし、インターネット上で暗号化されていないエラーレポートを送信することは避けるべきです(電子メールなど)。
機密情報のフィルタリング¶
エラーレポートはエラーのデバッグにとても役立つので、通常は、エラーに関する関連情報をできるだけ多く記録しておくと便利です。例えば、デフォルトでは Django は発生した例外の full traceback や、各 traceback frame のローカル変数、 HttpRequest
の 属性 を記録します。
しかし、例えばユーザのパスワードやクレジットカード番号のように、ある種の情報は機密性が高すぎるため、記録するのが適切でない場合があります。そこで Django では、 DEBUG
ドキュメントで説明されているように、機密性が高そうな設定をフィルタリングすることに加えて、本番環境 (つまり、 DEBUG
が False
に設定されている場合) でエラーレポートからフィルタリングされる情報を制御するのに役立つ関数デコレータを提供しています。 sensitive_variables()
と sensitive_post_parameters()
です。
-
sensitive_variables
(*variables)[ソース]¶ コード内の関数(ビューまたは通常のコールバック)が機密情報を含む可能性のあるローカル変数を使用している場合、
sensitive_variables
デコレータを使用することで、それらの変数の値がエラーレポートに含まれないようにすることができます:from django.views.decorators.debug import sensitive_variables @sensitive_variables("user", "pw", "cc") def process_info(user): pw = user.pass_word cc = user.credit_card_number name = user.name ...
上記の例では、
user
、pw
、cc
の値は非表示になり、エラーレポートではアスタリスク (*******
) に置き換えられますが、name
変数の値は公開されます。関数のすべてのローカル変数をエラーログから徹底的に隠す場合は、引数なしで
sensitive_variables
デコレーターを使います:@sensitive_variables() def my_function(): ...
複数のデコレータを使うとき
非表示にしたい変数が関数の引数でもある場合 (例えば、次の例では '
user
') 、そしてデコレートされた関数に複数のデコレーターがある場合は、@sensitive_variables
をデコレーターチェインの先頭に置くようにしてください。こうすることで、関数の引数が他のデコレータに渡される際に、その引数を隠すことができます:@sensitive_variables("user", "pw", "cc") @some_decorator @another_decorator def process_info(user): ...
Changed in Django 5.0:async
関数のラップをサポートしました。
-
sensitive_post_parameters
(*parameters)[ソース]¶ もしビューの 1 つが
HttpRequest
オブジェクトをPOST parameters
で受け取った場合、機密情報が含まれている可能性があるので、sensitive_post_parameters
デコレータを使って、エラーレポートにそのパラメータの値が含まれないようにすることができます:from django.views.decorators.debug import sensitive_post_parameters @sensitive_post_parameters("pass_word", "credit_card_number") def record_user_profile(request): UserProfile.create( user=request.user, password=request.POST["pass_word"], credit_card=request.POST["credit_card_number"], name=request.POST["name"], ) ...
上の例では、
pass_word
とcredit_card_number
のPOSTパラメータの値は隠され、エラーレポート内のリクエストの表現ではアスタリスク (*******
) に置き換えられますが、name
パラメータの値は公開されます。エラーレポートでリクエストの全てのPOSTパラメータを徹底的に隠す場合は、 引数なしで
sensitive_post_parameters
デコレータを使います:@sensitive_post_parameters() def my_view(request): ...
特定の
django.contrib.auth.views
のビュー (auth
admin 内のlogin
,password_reset_confirm
,password_change
,auth
admin のadd_view
とuser_change_password
) のエラーレポートから、すべての POST パラメータが徹底的にフィルタされ、ユーザパスワードのような機密情報の漏洩を防ぎます。Changed in Django 5.0:async
関数のラップをサポートしました。
カスタムエラーレポート¶
sensitive_variables()
と sensitive_post_parameters()
がすることは、それぞれ、装飾された関数にセンシティブな変数名をアノテートし、HttpRequest
オブジェクトにセンシティブな POST パラメータ名をアノテートするだけです。実際のフィルタリングは Django のデフォルトのエラーレポートフィルタ ( django.views.debug.SafeExceptionReporterFilter
) で行われます。このフィルタはデコレータのアノテーションを使い、エラーレポートが生成される際に、対応する値をアスタリスク (*******
) に置き換えます。このデフォルトの動作を上書きしたり、サイト全体でカスタマイズしたい場合は、独自のフィルタクラスを定義し、 DEFAULT_EXCEPTION_REPORTER_FILTER
設定でそれを使うように Django に指示する必要があります:
DEFAULT_EXCEPTION_REPORTER_FILTER = "path.to.your.CustomExceptionReporterFilter"
また、 HttpRequest
の exception_reporter_filter
属性を指定することで、任意のビューで使用するフィルタをより細かく制御できます:
def my_view(request):
if request.user.is_authenticated:
request.exception_reporter_filter = CustomExceptionReporterFilter()
...
カスタムフィルタクラスは django.views.debug.SafeExceptionReporterFilter
を継承し、以下の属性とメソッドをオーバーライドする必要があります:
-
class
SafeExceptionReporterFilter
[ソース]¶ -
cleansed_substitute
¶ センシティブな値を置換する文字列値。デフォルトでは、センシティブな変数の値をアスタリスク (
*******
) で置き換えます。
センシティブな設定や
request.META
にマッチする正規表現オブジェクト。デフォルトでは下記です:import re re.compile(r"API|TOKEN|KEY|SECRET|PASS|SIGNATURE|HTTP_COOKIE", flags=re.IGNORECASE)
-
is_active
(request)[ソース]¶ get_post_parameters()
とget_traceback_frame_variables()
のフィルタリングを有効にする場合はTrue
を返します。デフォルトではDEBUG
がFalse
の場合に有効になります。DEBUG
のドキュメントにあるように、センシティブなrequest.META
の値は常に、センシティブな設定値とともにフィルタリングされることに注意してください。
-
get_post_parameters
(request)[ソース]¶ フィルタリングされた POST パラメータの辞書を返します。センシティブな値は
cleansed_substitute
で置換されます。
-
get_traceback_frame_variables
(request, tb_frame)[ソース]¶ 与えられたトレースバックフレームのローカル変数のフィルタリングされた辞書を返します。センシティブな値は
cleansed_substitute
で置き換えられます。
-
フィルタリングの他にエラーレポートをカスタマイズする必要がある場合は、 DEFAULT_EXCEPTION_REPORTER
設定を定義することでカスタムエラーレポータークラスを指定できます:
DEFAULT_EXCEPTION_REPORTER = "path.to.your.CustomExceptionReporter"
例外レポーターは例外レポートデータをコンパイルし、テキストまたはHTMLとして適切にフォーマットする責任があります。(例外報告レポーターは、例外レポートデータを作成する際に DEFAULT_EXCEPTION_REPORTER_FILTER
を使用します)。
カスタムレポータークラスは django.views.debug.ExceptionReporter
を継承する必要があります。
-
class
ExceptionReporter
[ソース]¶ -
html_template_path
[ソース]¶ 例外の HTML 表現をレンダリングするテンプレートへの絶対ファイルシステムパスを表す
pathlib.Path
を返すプロパティです。デフォルトは Django が提供するテンプレートです。
-
text_template_path
[ソース]¶ pathlib.Path
を返すプロパティで、例外のプレーンテキスト表現をレンダリングするテンプレー トへのファイルシステムの絶対パスを表します。デフォルトは Django が提供するテンプレートです。
-
get_traceback_data
()[ソース]¶ トレースバック情報を含む辞書を返します。
これは、例えば例外レポートをカスタマイズするための主な拡張ポイントです。例えば下記のようにします:
from django.views.debug import ExceptionReporter class CustomExceptionReporter(ExceptionReporter): def get_traceback_data(self): data = super().get_traceback_data() # ... remove/add something here ... return data
-
フィルタクラスと同様に、 HttpRequest
の exception_reporter_class
属性を指定することで、任意のビューで使用する例外レポータークラスを制御できます:
def my_view(request):
if request.user.is_authenticated:
request.exception_reporter_class = CustomExceptionReporter()
...