- はじめに
- ベストプラクティス 1. logging.basicConfigではなくLoggerインスタンスを使う
- ベストプラクティス 2. ログレベルの使い分けを明確化
- ベストプラクティス 3. タイムスタンプとモジュール名を必ず記録
- ベストプラクティス 4. ファイル出力とコンソール出力を併用
- ベストプラクティス 5. ローテーションでログ肥大化を防ぐ
- ベストプラクティス 6. 環境変数でログレベルを切り替え
- ベストプラクティス 7. 例外ログはlogger.exceptionで
- ベストプラクティス 8. JSON形式でログを構造化
- ベストプラクティス 9. 外部サービス連携(Slack, Sentryなど)
- ベストプラクティス 10. 設定ファイル(YAML/JSON)で管理
- まとめ
はじめに
Pythonのlogging
モジュールは強力ですが、「結局どう使えばいいの?」と迷う人は少なくありません。
特にチーム開発や本番運用では、適切なロギング戦略を取らないとエラーの特定が遅れる・ログが読みにくい・不要な情報で肥大化するといった問題が発生します。
この記事では、Pythonのloggingを使いこなすためのベストプラクティス10選を、実務で使えるサンプルコード付きで解説します。
ベストプラクティス 1. logging.basicConfigではなくLoggerインスタンスを使う
多くの入門記事でlogging.basicConfig()
が紹介されますが、本格的な開発ではモジュールごとに専用のLoggerを作成する方が管理しやすいです。
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(name)s: %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
ポイント:
__name__
でモジュール名をログに自動付与- 他モジュールとのログ設定の衝突を防げる
ベストプラクティス 2. ログレベルの使い分けを明確化
ログレベルの基準をチーム内で統一しましょう。
レベル | 用途例 |
---|---|
DEBUG | 開発・デバッグ用詳細情報 |
INFO | 正常動作の記録(処理完了、開始など) |
WARNING | 想定外だが動作継続可能な状態 |
ERROR | 処理が失敗したがアプリ継続可能 |
CRITICAL | アプリの停止を伴う重大エラー |
ベストプラクティス 3. タイムスタンプとモジュール名を必ず記録
実運用では、いつ・どこで・何が起きたかが分かるログが重要です。
formatter = logging.Formatter(
'%(asctime)s [%(levelname)s] %(name)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
ベストプラクティス 4. ファイル出力とコンソール出力を併用
開発時はコンソール、本番ではファイルに保存することが多いです。両方に同時出力も可能。
file_handler = logging.FileHandler('app.log')
file_handler.setFormatter(formatter)
logger.addHandler(handler) # コンソール
logger.addHandler(file_handler) # ファイル
ベストプラクティス 5. ローテーションでログ肥大化を防ぐ
RotatingFileHandler
を使えば、ログファイルが一定サイズを超えると自動でローテーションできます。
from logging.handlers import RotatingFileHandler
rot_handler = RotatingFileHandler('app.log', maxBytes=5_000_000, backupCount=5)
rot_handler.setFormatter(formatter)
logger.addHandler(rot_handler)
ベストプラクティス 6. 環境変数でログレベルを切り替え
本番と開発でログ量を変えたい場合は、環境変数で制御。
import os
log_level = os.getenv('LOG_LEVEL', 'INFO').upper()
logger.setLevel(getattr(logging, log_level))
ベストプラクティス 7. 例外ログはlogger.exceptionで
例外スタックトレースを自動で記録できます。
try:
1 / 0
except ZeroDivisionError:
logger.exception("ゼロ除算エラーが発生しました")
ベストプラクティス 8. JSON形式でログを構造化
機械的に解析しやすいログは運用効率を上げます。
import json
class JsonFormatter(logging.Formatter):
def format(self, record):
log_obj = {
'time': self.formatTime(record),
'level': record.levelname,
'name': record.name,
'message': record.getMessage()
}
return json.dumps(log_obj)
json_handler = logging.StreamHandler()
json_handler.setFormatter(JsonFormatter())
logger.addHandler(json_handler)
ベストプラクティス 9. 外部サービス連携(Slack, Sentryなど)
エラーをリアルタイム通知することで復旧が早まります。
例:Slack Webhookで通知するカスタムHandler。
ベストプラクティス 10. 設定ファイル(YAML/JSON)で管理
コードに直接書かず、logging.config.dictConfig
で設定を読み込むと柔軟に変更可能。
まとめ
- ログは後から原因追跡するための生命線
- 統一ルールと自動化で、チーム全体の運用負荷を下げられる
basicConfig
から卒業し、モジュール単位のLoggerと設定ファイル管理へ移行すべき
📌 おすすめ図解(生成可能)
- ログレベル別の運用フロー図
- ログ出力先構成図(コンソール・ファイル・外部サービス)
- RotatingFileHandlerの仕組み図
もし希望があれば、この内容に図解付きの完全版を作って、
SEOメタディスクリプションや見出しタグ最適化もできます。
次は、この記事を図解付きに拡張しますか?
それともブログ投稿用のSEO最適化HTML版にしますか?
コメント