ログ出力の考え方 - アーキ教室
ベテランのSI屋さんが考えたことを書き残した雑記です。
SI屋さんにしか通じない単語を説明なしに使うので素人は要注意です。
いろいろな意見を欲しているので、つっこみは大歓迎です。
他の記事はSI屋さんの雑記からどうぞ。
概要
ログ出力の要求、要件、アーキなど、考えなければならないことを整理するための記事です。アーキ以降はまだまだ雑なので、ときどき更新する予定です。
考えるための基本軸
ログ出力で考えるうえで基本となる軸は以下の3点だと思います。
-
何のために出すか
ログが出ていることは大事ですが、垂れ流せばよいというものでもありません。
出すからには目的が必要であり、使うシーンを想定しないと無駄となってしまいます。
この検討を非機能の開発フェーズで言うと「要求定義」に該当すると考えています。 -
何を出すか
ログ出力の目的とシステム構成が定まっていれば、何を出力するべきかは自ずと決まっていきます。
こちらは非機能の開発フェーズで言うと「要件定義」に該当すると考えています。 -
どのように出すか
ログの出力方法や内容に関するものです。デファクトスタンダードが確立されているので要求や要件が整理されている状況であれば、検討することは少ないでしょう。
こちらは非機能の開発フェーズで言うと「アーキ設計」に該当すると考えています。
何のために出すか
ログ出力において最も重要なのはログを出力する目的です。
一般的には以下の目的が考えられます。
-
インシデント検知
対応が必要となる故障や障害を検知するために出力します。
監視ツールでログの中から特定の文字列を検知すると発報するといった使い方がされます。 -
障害調査
技術者が故障や障害を調査するために出力します。
問題を特定するのに役に立つ内容が求められます。 -
監査
システムのガバナンスやマネジメントの検査を目的として、ログの提出が求められる場合があります。
この場合、ログに望まれるのはシステムのふるまいや利用者の操作記録となります。 -
法令や業界ルール
電子帳簿保存法や個人情報保護法など、一部の法律ではログの出力を推奨しています。
また、クレジットカード情報を取り扱う場合のルールであるPCI DSSなどでもログの取り扱いを規定しています。 -
デバッグ
開発者がプログラムの挙動を確認するために一時的に出力する場合があります。
実際にサービス提供を行う本番環境や商用環境とよばれる環境では出力しません。 -
モニタリング
サーバーのリソース状況や、バッチの処理状況などをログに出力する場合があります。
GCログなどもこの範疇だと思います。
何を出すか
ログ出力対象は以下の3点を組み合わせて導出します。
-
目的
前項で整理した内容です。 -
出力ポイント
ログを出力の起点となるシステム上のイベントです。- 利用者の操作
- システム境界
- 処理の開始/終了点
- エラー発生時
-
システム構成コンポーネント
以下のような、ログ出力機能を備えているコンポーネントです。- 開発機能
- フレームワーク
- ミドルウェア
- データベース
- OS
- ネットワーク機器
- 外部サービス
これらを組み合わせて考えることで、抜けや漏れが少ないログ出力対象を決めることができるでしょう。
例として、開発機能におけるログ出力対象を以下に示します。
出力コンポーネント | 出力ポイント | インシデント検知 | 障害調査 | 監査 | 法令 |
---|---|---|---|---|---|
開発機能 | 利用者の操作 | - | 〇 | 〇 | 〇 |
開発機能 | 実行したSQL(システム境界) | - | 〇 | 〇 | - |
開発機能 | API呼び出し(システム境界) | - | 〇 | 〇 | - |
開発機能 | エラー情報 | 〇 | 〇 | - | - |
どのように出すか
目的と対象が整理されていれば、あとは出力内容を考えるだけです。
先にコッチを考えてしまうと、目的や対象が曖昧になってしまうので注意が必要です。
-
ログレベル
ログレベルは、出力する情報の重要度や緊急度に応じて分類します。
また、本番環境や商用環境ではDEBUGログを出さないなど、環境に応じて出力するログレベルを調整することも重要です。- ERROR:システムの処理が継続できない重大な障害や例外が発生した場合に出力します。
例:データベース接続失敗、致命的な例外発生など - WARN:処理は継続できるが、注意が必要な事象が発生した場合に出力します。
例:設定ファイルの一部が読み込めなかった、リトライで復旧した一時的な障害など - INFO:システムの通常動作や重要なイベントを記録します。
例:サービスの起動・停止、ユーザーのログイン、バッチ処理の開始・終了など - DEBUG:主に開発・テスト時に利用し、詳細な内部状態や処理の流れを記録します。
例:関数の入出力値、分岐の判定結果、詳細なトレース情報など
- ERROR:システムの処理が継続できない重大な障害や例外が発生した場合に出力します。
-
ログフォーマット
ログのフォーマットを設計する際に考慮すべき主なポイントは以下の通りです。- タイムスタンプ(日時)を必ず含める
- ログレベル(ERROR, WARN, INFO, DEBUGなど)を明記する
- コンテキスト情報(ユーザーID、リクエストID、セッションIDなど)を含める
- ログ出力元(クラス名、関数名、ファイル名、行番号など)を記録する
- メッセージ内容は簡潔かつ具体的に記述する
- 例外発生時はスタックトレースなど詳細情報も記録する
- 文字コードや改行コードの統一
- 機密情報が含まれないように注意する
- 出力先の選定
-
出力先/永続化方法
ログの出力先は、システムの規模や運用要件に応じて選定します。よく使用される物は以下の通りです。- ローカルファイル:シンプルな構成や小規模システムでよく利用される。ログローテーションやバックアップの仕組みが必要となります。
- 標準出力(stdout):コンテナ環境で推奨される方法です。基本的に外部のログ管理サービスと連携する前提です。
- 外部ログ管理サービス:CloudWatch、Stackdriver、ELK(Elasticsearch, Logstash, Kibana)、Datadogなど。コストはかかるが、スケーラビリティや可用性、分析機能が充実しています。
- データベース:検索性や集計性を重視する場合に利用されますが、パフォーマンスや運用コストに注意が必要となります。
-
保管期間
ログの保管期間は目的に応じて決めるのが良いでしょう。
インシデントの検知や障害対応であれば長い間保管する必要はありません。しかし、年次のバッチ処理で追跡する可能性があるなど、システム特性に応じて設定する必要があります。
また、法令で出力物の保管期間が定められている場合等は、ログも合わせた期間で残しておくのが好ましいでしょう。 -
機密情報への配慮
ログとして出力するメッセージには、機密情報や個人情報が含まれないように注意するのが一般的です。
出力対象外としたり、マスキングを行うことが推奨されます。
参考
ログに関して検討するにあたって非常に参考になる記事たちです。
Discussion