ログ改善で一番怖いのは、新しいロガーの導入そのものではありません。
アプリケーション中に散った logger.info(...)、logger.warning(...)、logger.exception(...) を巻き込んで、差分が大きくなることです。
ここでは、既存のログ呼び出しを壊さずに、ログ運用の要求だけを後から足す方法を見ます。
呼び出し箇所は資産になる
アプリケーションのログ呼び出しは、最初は軽く書かれます。
logger.info("job started")
logger.warning("retrying request")
logger.exception("failed to import file")
でも時間が経つと、これらは障害調査や監査で使われる資産になります。
だから、ログ運用を強くしたいからといって、呼び出し箇所を全部置き換えるのはかなり重い判断です。
まず考えたいのは、呼び出し側ではなく初期化側に運用方針を寄せられないか、です。ここでいう呼び出し箇所は、アプリケーションコード中にある logger.info(...) や logger.warning(...) の場所を指します。
最初は小さく始める
たとえば、最初は次のような要件だけかもしれません。
- ローカルファイルへ出す
- アプリ名をファイル名に入れる
- 既存の
logger.info(...)に近い形を保つ
実装例として D-SafeLogger を使うと、こう書けます。
from dsafelogger import ConfigureLogger, GetLogger
ConfigureLogger(log_path="./logs", pg_name="MyApp")
logger = GetLogger(__name__)
logger.info("Application started")
配布パッケージ名は d-safelogger、import 名は dsafelogger です。
pip install d-safelogger
運用要求は後から増える
ログに対する要求は、後から増えます。
- JSON Lines 形式にしたい
- 日次でファイルを分けたい
- 環境変数でログレベルを変えたい
- ハッシュや一覧情報ファイルを残したい
- 機微情報を伏せたい
- マルチプロセスの子プロセスのログを集約したい
ここで使っている D-SafeLogger は、アプリケーション側の logging.getLogger() や logger.info(...) をできるだけ保ったまま、ファイル出力側に出力先の切り替え、JSON Lines、ハッシュ、一覧情報ファイル、環境変数による運用時の上書きを追加するためのロガーです。
このとき、アプリ中の呼び出し箇所を触らずに設定を増やせると、移行のリスクが下がります。
from dsafelogger import ConfigureLogger, GetLogger
ConfigureLogger(
log_path="./logs",
pg_name="MyApp",
routing_mode="daily",
structured=True,
enable_hash=True,
)
logger = GetLogger(__name__)
logger.info("Application started")
ここで変わったのは初期化設定です。logger.info(...) はそのままです。
起動時に止めたい設定
ログ設定は、間違っていてもアプリ本体が動いてしまうことがあります。
でも、ログは障害時に見に行くものです。そのときに「実は設定が効いていませんでした」はかなり厳しいです。
自分なら、次のような設定は起動時に落としたいです。
- 構造化出力と独自フォーマッタが衝突している
- 出力先の切り替えなしなのに保存期間の制御を期待している
- ハッシュやアーカイブと出力先の切り替え方針が矛盾している
- 出力先へ書けない
D-SafeLogger はこの方向に寄せています。柔軟さより、早く壊れて気づけることを優先しています。
設定レイヤーを分ける
ログ運用は、コードだけで完結しません。
| レイヤー | 例 | 役割 |
|---|---|---|
| コード | ConfigureLogger(...) |
アプリの既定値 |
| 設定ファイル / dict | INI や dict | 環境ごとの差分 |
| 環境変数 |
D_LOG_LEVEL など |
一時的な運用上書き |
たとえば、一時的に DEBUG を出したいだけなら、コード変更ではなく環境変数で済ませたいです。
ただし、何でも環境変数で変えられるのが正義ではありません。診断モードのように情報量が増えるものは、明示的に有効化する前提で扱うべきです。
この考え方が向くケース
向いているケース:
- 既存の Python の logging 呼び出しがすでにある
- 外部ライブラリも
logging.getLogger()経由でログを出している - ローカルファイルを運用上の成果物として残したい
- 後から JSON Lines、出力先の切り替え、ハッシュなどを追加したい
向かないケース:
- 標準出力 / 標準エラーに出して収集基盤が全部持つ
- ロガーの API を全面的に置き換えたい
- ローカルファイルをそもそも持たない
まとめ
ログ改善で最初に守りたいのは、アプリケーション中に散った呼び出し箇所です。
呼び出しを壊さず、初期化設定でファイルの扱い方や出力形式を育てる。これができると、ログ運用の変更を小さく刻めます。
D-SafeLogger はそのための実装例の一つです。主役はライブラリ名ではなく、呼び出し箇所を守りながら運用要件を足す設計です。
参考
- D-SafeLogger README: https://github.com/nightmarewalker/D-SafeLogger
- Python logging: https://docs.python.org/3/library/logging.html
- Configuration Guide: https://github.com/nightmarewalker/D-SafeLogger/blob/main/examples/02_configuration_guide.md
関連記事
Qiita 連載:
- #1 ログローテーションで active file を rename するの、本当に安全ですか?
- #2 logger.info(...) を書き換えずに、ログ運用だけ変えたい(本記事)
- #3 子プロセスに同じログファイルを開かせる前に考えること
- #4 ログライブラリのベンチマークを「速い順」で読んではいけない
Zenn 連載: