ウェブアプリケーション運用に必要な基本的なログについて
はじめに
アプリケーションを運用する上で、適切なログ出力を行うことは非常に重要です。 ログを残すことで、システム上で何が起こったかが明確になるので、この情報を用いた適切な調査を行えるようになります。
過去に発注者向けの記事として、アプリケーションログ・サーバーログについてを説明した記事を公開していますが、この記事はより開発者向けのログ内容について説明します。
【発注者向け】システム開発が濃いめのWebサイト制作では、必ずプログラマーにアプリケーションログを残すように伝えないと後で痛い目に合う。
ログの種類
ログとは、システムやアプリケーションが動作する際に記録される情報のことです。ウェブアプリケーションを運用する上で、ログはシステムの挙動を把握し、問題発生時の調査やトラブルシューティングに不可欠な要素となります。
ウェブアプリケーションは多くの要素が連携して動作しているため、記録されるログの種類も多岐にわたります。例えば、アプリケーションの動作を記録するアプリケーションログ、ユーザーのリクエストを記録するアクセスログ、エラーの発生を記録するエラーログ、システムの重要な操作を記録する監査ログなどがあります。 それぞれのログには異なる役割があり、その用途のログがまとめて出力されることが多いです。
ログが適切に記録されていないと、問題が発生した際に何が起こっていたのかを把握できません。その結果、原因の特定が困難になり、さらには、そもそも問題が発生していたかどうかすら判断できない場合もあります。逆に、適切にログを取得し分析することで、障害対応の迅速化、セキュリティ対策の強化、パフォーマンス改善など、多くのメリットを得ることができます。
上記で挙げたログ以外にも、利用しているデータベースやキャッシュシステムのログ、アプリケーションを動作しているサーバーのログ、外部のサービスを利用した際のログなど、数多くのログがありますが、本記事では、先に挙げたアプリケーションログ、アクセスログ、エラーログ、監査ログに加えて、バッチログについてを解説していきます。
アプリケーションログ
アプリケーションログとは、その名の通りアプリケーションの動作状況を記録するものです。このログを出力することで、プログラム上でどのコードが実行されているのかを確認したり、その際にどのようなパラメータが渡されているのかを把握することができます。また、エラー発生時にどのような問題が起こったのかを記録する目的でもよく利用されます。
多くのプログラミング言語やフレームワークでは、ログ出力のための仕組みが標準で提供されています。例えば、Python では標準ライブラリの logging モジュールを利用してフレームワークごとにログ出力の設定が可能ですし、PHP の Laravel では Monolog を使用してログ出力を行います。以下のようなコードを記載することで、ログを出力できます。
// PHP の Monolog を利用したログ出力の例
Log::info(“ここに記載した内容がログに出力されます。 引数は {$arg} です”);
アプリケーションログには、開発者が必要と感じたさまざまな情報を記録できます。しかし、例えば「開発環境ではパラメータの正しさを確認したいが、本番環境ではログの出力回数が多くノイズになるため不要」といったケースや、「エラー発生時の情報は常に記録すべき」といったケースなど、記録すべきログの種類には違いがあります。これに対応するため、ログ出力の仕組みでは、出力時にログレベルを設定することが一般的です。
代表的なログレベルとして、error、warning、info、debug などがあります。アプリケーションの実行時にログレベルを指定することで、特定のレベル以上のログのみを出力できるようになります。つまり、ログ出力のコードはそのまま残したまま、環境に応じて必要なログ出力のみを行うことが可能になります。
具体的な環境別の設定を考えてみると、開発環境では debug レベルで動作させてすべてのログを記録し、本番環境では warning レベルで動作させ、重要な情報のみを記録するといった運用が可能になります。これにより、環境に応じた適切なログ管理を行うことができます。
アプリケーションログを取り扱う際の注意点として、ログを過剰に記録するとコンピュータリソースに大きな負荷をかける可能性がある点が挙げられます。そのため、特に本番環境では、先述したログレベルを適切に設定し、重要な情報のみを出力することが求められます。 また、ログにはユーザーの個人情報が含まれる可能性があるため、慎重に扱う必要があります。個人情報を直接ログに出力することは避け、必要に応じてマスキングやハッシュ化を施す、もしくはユーザーを識別するための ID のみを出力するなど、ログを見ただけでは個人情報が特定できないように工夫することが重要です。これにより、万が一ログが外部に漏洩した場合でも、プライバシーリスクを最小限に抑えることができます。
アクセスログ/エラーログ
この文脈でのアクセスログとエラーログは、正確にはウェブサーバーアプリケーションが出力する2種類のログを指します。ウェブアプリケーションを運用する際には、サーバー上に Apache や Nginx などのウェブサーバーアプリケーションを導入することが一般的です。これらのアプリケーションは、「どのリソースにアクセスされたか」を示すアクセスログと、「ウェブサーバーでの処理中に問題が発生した」ことを示すエラーログを出力します。
アクセスログにはユーザーのリクエスト内容が記録されます。 具体的には、どの URL にアクセスされたのか、どの IP アドレスからリクエストが送信されたのか、レスポンスのステータスコードが何か、といった情報が記録されます。一方、エラーログには、サーバーで発生したエラーや警告が記録され、設定のミスやサーバー内部の問題を特定するために利用されます。 これらのログを適切に管理することで、ウェブアプリケーションの動作状況を正確に把握し、障害対応やセキュリティ対策を適切に行うことができます。
ただし、レンタルサーバーで PHP を利用する場合、エラーログの扱いには注意が必要です。レンタルサーバーでは PHP の設定に制限があることが多く、error_log 関数の出力先としてウェブサーバーのエラーログが指定されていることが多いです。そのため、レンタルサーバー環境では PHP のエラーログがサーバーのエラーログと同じ場所に記録され、アプリケーションログのように取り扱われる場合があります。 その結果、レンタルサーバーのみで開発を行っている人は、「アプリケーションログ」という概念を意識しないまま開発を進めている可能性があります。しかし、アクセスログ・エラーログとアプリケーションログは本質的に異なる用途で利用されるものであり、適切に区別することが重要です。
監査ログ
監査ログとは、アプリケーションの利用者がどのような処理を行ったのかを記録するログであり、アプリケーションの機能の一部として実装されます。監査ログの主な目的は、「誰が、いつ、どのような処理を行ったのか」 を記録することで、アプリケーション上のデータに対する意図しない操作や改ざんが行われていないことを検証・保証することです。
特に会計関連のソフトウェアや金融システムでは、この機能は極めて重要とされています。これらのシステムでは、不正防止やコンプライアンス遵守の観点から、取引履歴やデータ変更履歴を詳細に記録し、後から追跡できるようにする必要があります。また、監査ログはシステム管理者やセキュリティ担当者が異常な操作を検知する手がかりにもなり、セキュリティ対策や法規制への対応という側面でも欠かせない要素となっています。
さらに、監査ログはセキュリティ目的だけでなく、運用者がデータの整合性を検証するためのトラブルシューティングにも役立ちます。例えば、予期しないデータ変更が発生した場合に監査ログを調査することで、どのユーザーがどのような操作を行ったのかを特定し、適切な対応を取ることができます。
監査ログの具体例として、AWS の CloudTrail があります。この機能は AWS 上での API 実行記録を保持しており、いつ、誰が、どの IP アドレスから、どのような操作を行ったのか という情報を記録しています。これにより、管理者はシステム上の操作履歴を正確に把握し、必要に応じて監査やセキュリティ対策を実施できます。
一方で、一般的な(特に小規模な)ウェブアプリケーションを開発する際には、監査ログの実装があまり考慮されません。しかし、監査ログの導入は運用面でも多くのメリットがあるため、案件の性質や要求要件に応じて、監査ログの実装を検討・提案することが望ましいでしょう。
バッチログ
ウェブアプリケーションを運用する中で、特定の時間になった際にプログラムを自動的に実行する手法は広く活用されています。具体的には、昨日のデータを集計する処理や、外部システムから定期的にデータを取得する処理などが該当します。このように、定期的に処理を実行する仕組みをジョブスケジューラと呼び、具体例としては cron や PHP Laravel の schedule などが挙げられます。
一方で、大量のデータを一括処理するプログラムやジョブのことをバッチ処理と呼びます。ジョブスケジューラを使用してバッチ処理を定期実行するケースも多く、例えば日次・週次・月次のデータ集計やバックアップ処理などで用いられます。
バッチ処理の実行結果を記録するログをバッチログと呼び、プログラム中でどのような処理が行われたのかを確認するために非常に重要です。バッチログには、実行開始・終了時間、処理対象のデータ件数、エラー情報 などが記録され、トラブルシューティングや動作確認の際に利用できます。
ジョブスケジューラとして cron を用いてバッチを実行する場合、バッチ自体が適切なログを出力すること、およびその結果を適切にリダイレクトして記録することが求められます。高度なジョブスケジューラであればログの記録機能を自動で提供するものもありますが、ジョブスケジューラの仕様に応じたログ出力の設定(特に 2>&1 によるエラーログのリダイレクトなど)を正しく行い、動作確認を行うことが重要です。
ログの保存期間について
ログを適切に管理することで、システムの運用やトラブルシューティングを効果的に行うことができます。しかし、無制限にログを保存できれば理想的ではあるものの、ログの保存にはディスク容量というコンピュータリソースが必要となるため、現実的には無制限に保持することは困難です。そのため、ログの保存には適切なポリシーを設けることが重要です。
ウェブサーバーやアプリケーションサーバーでは、logrotate という仕組みを活用することで、一定期間が経過したログを自動的に圧縮・削除することができます。これにより、サーバー上のディスク使用量を適切に管理しながら、必要なログを保持することが可能になります。一方で、サーバー上のディスク領域には限りがあるため、Amazon S3 などのクラウドストレージを活用することで、より多くのログを保存することができます。例えば、logrotate により圧縮された古いログを定期的に S3 にコピーすることで、サーバーのディスク負荷を軽減しながら長期間のログ保存を実現できます。また、S3 の Lifecycle ルールを利用すれば、一定期間が経過したログを自動的に削除し、ストレージコストを抑えることも可能です。
さらに、サーバー上にログを保存するのではなく、リアルタイムでログを外部のログ管理サービスに転送する方法もあります。Fluentd を利用すれば、ログを S3、Elasticsearch、BigQuery などの異なる出力先に送信でき、AWS の CloudWatch Agent を活用すれば、CloudWatch Logs に記録して検索や分析が容易になります。 このように、クラウドストレージや外部ログ管理サービスを活用することで、サーバー上でのログ管理だけでなく、より柔軟で信頼性の高いログ保存が可能になります。運用するサービスの特性やログの保持要件に応じて、最適な管理方法を選択することが重要です。
おわりに
本記事では、一言で「ログ」といってもその用途や種類が異なること、そしてウェブアプリケーションの運用でよく利用されるログについてと、それらのログの保存期間についてを説明しました。
ログにはさまざまな種類がありますが、特に重要なのは以下の4種類です。
- アプリケーションログ:アプリケーションの動作状況や処理の流れを記録するログ
- アクセスログ:ウェブサーバーが記録する、ユーザーのリクエストに関するログ
- エラーログ:アプリケーションやサーバーで発生したエラーを記録するログ
- 監査ログ:ユーザーが行った操作を記録し、不正防止やコンプライアンス対応に役立つログ
さらに、定期的に実行される処理(バッチ処理)に関連する バッチログ も、運用において重要な役割を果たします。バッチの実行状況や処理結果を正しく記録することで、トラブルシューティングやパフォーマンス改善に役立てることができます。
適切なログ管理は、障害対応、セキュリティ対策、運用の効率化 につながります。システムの特性や目的に応じて、必要なログを適切に記録し、活用できる環境を整えることが重要です。