ソフトウェアを開発する上でしっかりと設計しておきたいのがログの出力です。私は以前、運用しているウェブアプリケーションのログ出力のフォーマットが不十分だったため、問題が起きたときに原因の調査ができなかったという苦い経験があります。そのときから、ログの出力の設計について気をつけるようにしています。
この記事ではログの出力を設計する方法について、フォーマットやメッセージの書き方を例をもとに解説します。ログを設計するときの参考になればうれしいです。
Software Design 2023年2月号の中で、ログの設計に関する特集記事を執筆しました。詳しくは、次の記事をご覧ください。
テクニカルライター。元エンジニア。共著で「現場で使えるRuby on Rails 5」を書きました。プログラミング教室を作るのが目標です。
ログ出力の設計指針とは
まず、ログとは「アプリケーションやサーバ、ソフトウェアなどが出力する、時系列に記録されたデータ」のことをいいます。例えばアプリケーションが出力するログやデバッグログ、ウェブサーバのアクセスログやエラーログなどがあります。
これをふまえて、ログ出力の設計指針とは、アプリケーションなどのログの出力をどう設計するかという指針のことをいいます。
ログの種類によって、出力の設計指針は変わってくると思います。この記事では、いろんなログに共通する汎用的な内容として、アプリケーションログの出力を例に設計指針について書いていきます。
ログ出力の設計指針は、開発するソフトウェアによっても変わってきます。重要なことは、チームで指針をもってログ出力を行い、しっかりと運用していくことだと思います。
なぜログを出力するのか
これからログ出力の設計指針について書いていくのですが、そもそもなぜログを出力する必要があるのでしょうか。これは、大きく次の4つがあると考えられます。
- 問題が発生したときに調査するため
- 問題の発生を防ぐため
- データ分析を通してソフトウェアを改善するため
- 監査ログとして利用するため
ひとつずつ見ていきます。
1. 問題が発生したときに調査するため
ウェブアプリケーションを運用していると、サーバがダウンしてしまったり、レスポンスが遅くなったりすることがあります。こういった問題が発生したときに、発生した時間のログを見ることで、原因が分かったりします。
また、ユーザーに問題が起きたときにも役立ちます。ユーザーから問い合わせがあったときに、ユーザーのアカウント情報と突き合わせて調べることで、ユーザーに起きた問題の原因が分かることがあります。
2. 問題の発生を防ぐため
問題が起きていなくても、問題が起きる予兆があったりします。例えば同一のIPアドレスから連続してアクセスを受けることがあります。このときにIPアドレスに対する制限を行うなどすることで、問題の発生を防げることがあります。
3. データ分析をとおしてソフトウェアを改善するため
ログは、ソフトウェアを改善するためにも役立ちます。ユーザーの行動を分析して学習し、機能や施策につなげることでユーザー体験を向上することができます。
4. 監査ログとして利用するため
例えばPCI DSSというセキュリティ基準では、監査ログを最低3ヶ月間は保管しなければならないとしています。ソフトウェアによっては、こうした基準を満たすためにログを出力する必要があったりします。
ログ出力の設計指針
それでは、具体的にどうログ出力を設計すればよいのでしょうか。まず前提として、「ログには読み手がいる」ということを意識します。どういうケースで、どういう読み方を想定しながらログ出力を設計することが重要といえます。
ログ出力は、5W1Hにもとづいて設計するとよいといわれています。例えば、次のような項目をログに出力するようにします。
項目 | 内容 | 備考 |
---|---|---|
時間 | ログを記録した時間 | 年月日時分秒ミリ秒 |
ID | イベントのID | 一連のイベントを関連づけるために必要 |
ログレベル | ログのレベル | INFOやWARNなど |
ユーザー情報 | リクエストしたユーザーの情報 | ユーザーIDやIPアドレスなど |
リクエスト対象 | どこにリクエストしたか | URLなど |
処理内容 | どんな処理を行なったか | 参照や更新、削除など |
処理対象 | なにを処理したか | リソースのIDなど |
処理結果 | 処理した結果どうなったか | 成功または失敗、処理件数など |
メッセージ | その他出力したいこと | - |
ログ出力のメッセージは、できるだけシンプルに書くことで読み手に伝わりやすくなります。また、エラーが発生したときはスタックトレースを出力することで調査しやすくなります。
ログレベル
上で書いた項目の中にログレベルというものがあります。これはINFOやWARNなど、そのログのレベルを表します。
ログ出力にはログレベルを書くケースがほとんどだと思います。ログレベルは、読み手がほしい情報を適切に伝えるために役立ちます。ログレベルには、例えば次のような種類があります。
レベル | 概要 | 説明 |
---|---|---|
FATAL | 致命的なエラー | アプリケーション全体が提供できない |
ERROR | エラー | ユーザーのリクエストが処理できない |
WARN | 警告 | アプリケーションは提供できるが対応が望まれる |
INFO | 情報 | 記録しておくべき情報 |
DEBUG | デバッグ情報 | 動作に関する情報 |
TRACE | トレース情報 | 動作に関する詳細な情報 |
例えば、状況を確認するのに必要な情報をDEBUGレベルにしてしまうと、INFO以上を表示するときに表示されなくなってしまいます。INFOを見るときはどういう状況か、DEBUGを見るときはどういう状況かなど、読み手を想定して適切にログレベルを設定すべきだといえます。
なにを記録するか
ログ出力のフォーマットについては上で書きましたが、具体的にどのようなイベントを記録すればよいのでしょうか。例えば、次のようなイベントについてログに出力します。
- ユーザーが画面上で行うイベント全般
- 認証やサインアウト
- アカウント管理、パスワード変更
- 重要な情報へのアクセス
- エラーが発生したとき
なにを記録しないか
上で記録すべき情報について書きましたが、逆に記録すべきでない情報もあります。主にセキュリティの観点になるのですが、例えば次のような情報は記録すべきでありません。あるいはマスク処理を行う必要があります。
- パスワード
- OAuthなどの認証情報
- 個人情報
ログ出力を設計するときに注意すること
ログは問題が発生したときの調査や問題の予防などに役立ちますが、一方でサーバーに負荷がかかる行為でもあります。ログを出力することでサーバーにパフォーマンス上の問題が起きたときは、出力の設計指針を見直す必要がありそうです。
まとめ
アプリケーションのログを出力することで、問題が起きたときの調査に役立ったり、問題の予防につなげることができます。
ログ出力を設計するときは、読み手がほしい情報を想定して、適切な情報をふくめるとよいですね。ログ出力はサーバーのパフォーマンスに影響するので、サーバの監視もあわせて行うべきといえます。