先週投稿したOneToOneFieldの裏側で発行されているSQLを確認する の中でSQLをログ出力できるようにしていました。
そこについて、コピペで動いた!状態だったので、脱却するために調べました。
結論
DjangoではPythonのlogging
を利用しています。
logging.config.dictConfig
をベースにした設定値を記述しているようでした。
コピペで動いていた設定値について
まず、先週は割愛していたLOGGING
の内容を転記します。
LOGGING = { 'version': 1, 'handlers': { 'console': { 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'level': 'DEBUG', 'propagate': False }, }, }
60:Django ORMでどんなSQLが発行されているか気にしよう より引用しています。
定数 LOGGING
そもそもの定数値について。 リファレンスのページはこちら。
https://docs.djangoproject.com/en/5.0/ref/settings/#logging
前提として、Djangoにはデフォルトのログ設定がされています。
何も設定していない場合、例えばrunserver
実行時にログが出ると思いますが、以下のリンク先の標準設定によってログ出力の内容が定義されています。
https://github.com/django/django/blob/main/django/utils/log.py#L18-L64
定数LOGGINGを設定することで、このログ設定を上書きするようになっている、という状態でした。
ref
詳細の内容については以下リンクに書かれています。
https://docs.djangoproject.com/en/5.0/ref/logging/
例えば、loggers
では django.db.backends
の設定がされていましたが、この内容についても書かれていて、SQLがDEBUGレベルで取得できることが分かります。
Messages relating to the interaction of code with the database. For example, every application-level SQL statement executed by a request is logged at the DEBUG level to this logger.
https://docs.djangoproject.com/en/5.0/ref/logging/#loggers
topics
また、概要について記述された以下のページが存在します。
https://docs.djangoproject.com/en/5.0/topics/logging/
ここでは、以下の4つについて触れていて、全体像がわかるように解説されています。
- Logger
- Handlers
- Filters
- Formatters
個人的にも最初、「それっぽい設定がされてあるのは分かるんだけど・・・」と思ったので、Djangoのloggingについて大まかに知るためには、まずここを読んだら良さそうでした(概要ですしね)。
それ以外にはversion
という値についても記述がありました。
Identifies the configuration as being in ‘dictConfig version 1’ format. At present, this is the only dictConfig format version.
dictConfig
はPythonのlogging.config.dictConfig
のことで、以下のdictConfig
のリファレンスにも書かれている内容がDjangoリファレンスでも書かれていることが確認できました。
version - to be set to an integer value representing the schema version. The only valid value at present is 1, but having this key allows the schema to evolve while still preserving backwards compatibility.
https://docs.python.org/3/library/logging.config.html#dictionary-schema-details
個人的には2, 3なども設定出来るかなと思ってましたが、これは設定できません。
ちなみに、設定した場合 ValueError
が発生します。
Watching for file changes with StatReloader Exception in thread django-main-thread: Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/threading.py", line 1073, in _bootstrap_inner self.run() File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/threading.py", line 1010, in run self._target(*self._args, **self._kwargs) File "/Users/tatsuya/djangoTaskApp/venv/lib/python3.12/site-packages/django/utils/autoreload.py", line 64, in wrapper fn(*args, **kwargs) File "/Users/tatsuya/djangoTaskApp/venv/lib/python3.12/site-packages/django/core/management/commands/runserver.py", line 125, in inner_run autoreload.raise_last_exception() File "/Users/tatsuya/djangoTaskApp/venv/lib/python3.12/site-packages/django/utils/autoreload.py", line 87, in raise_last_exception raise _exception[1] File "/Users/tatsuya/djangoTaskApp/venv/lib/python3.12/site-packages/django/core/management/__init__.py", line 394, in execute autoreload.check_errors(django.setup)() File "/Users/tatsuya/djangoTaskApp/venv/lib/python3.12/site-packages/django/utils/autoreload.py", line 64, in wrapper fn(*args, **kwargs) File "/Users/tatsuya/djangoTaskApp/venv/lib/python3.12/site-packages/django/__init__.py", line 19, in setup configure_logging(settings.LOGGING_CONFIG, settings.LOGGING) File "/Users/tatsuya/djangoTaskApp/venv/lib/python3.12/site-packages/django/utils/log.py", line 76, in configure_logging logging_config_func(logging_settings) File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/logging/config.py", line 912, in dictConfig dictConfigClass(config).configure() File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/logging/config.py", line 516, in configure raise ValueError("Unsupported version: %s" % config['version']) ValueError: Unsupported version: 2
howto
ref, topics以外にhowtoページも存在します。
https://docs.djangoproject.com/en/5.0/howto/logging/
色々な設定方法についての解説がありますが、ここでは他のページで見られなかった propagate
について解説されています。
これは定義したロガーの親に伝播させるかどうかの設定が出来るようなので、特定の子ロガーだけのログ処理を実行させるようなケースに設定出来るようでした。
内部ではPythonのloggingを利用している
dictConfig
のくだりでlogging.config.dictConfig
だと、少し触れましたが、loggingはPythonの標準組み込みライブラリのlogging が内部的に利用されています。
そのため、class
で設定する logging.StreamHandler
などはDjango側で定義されたクラスもありますが、ベースは logging.handlers
になるようでした。
e.g. https://docs.python.org/ja/3/library/logging.handlers.html#logging.StreamHandler
調べてみて
内部で何を利用しているか?というところの理解が大事だなーと思いました。調べていく上で、謎の設定値が少しずつ読み解けました。
logging
もそこまで詳しく無いので調べたい気持ちもありますが、全てを調べるには時間が足りないので一旦このくらいで。
他にも以下ページにはログ出力する方法とかも書かれていて、ケースに応じて利用できると良さそうだなと思いました。