アプリケーションのログ出力指針を作ったときに、どんな事を考えていたのかを思い出しながら、 ログ出力指針について書いていきたいと思います。
ログ指針作成にあたって
そもそもなぜログが欲しいのか?何に利用するのか?
これに対する答えを置いておかないと、内容がぶれてしまうため、最初は目的を定義しました。
目的の作成
目的としてすぐ思いついたのは障害時対策のような守りの要素でしたが、 ビッグデータに取り込んで学習に使うというような攻めの要素にも使いたかったので、 目的には両方を明記しました。
目的を定めたあとは、どのタイミングでログが出力されていればいいのか、必要となる情報はなんなのか、解析しやすいフォーマットは・・・
のように思考が進んだのですが、作成した指針もどんなときにも利用できるというわけでもないだろうし、 無条件に鵜呑みにされると再度考察する機会がなくなると思い、この指針の対象とする範囲を定義しました。
適用範囲の設定
適用範囲を定めたことで、範囲外のログはどういう扱いにするか?という課題が出てきたのですが(例でいうとサーバログ)、 このときは「自分たちはここの範囲のログを整理することとして考えています。他は私たちが持ちますか?そちらで持ちますか?」というように 関連するチームに聞いて調整をしました。
もしサーバログも持つことになっていた場合は、ログ指針別で定義するのではなく、これを拡張していたと思います。
どんなときログを埋め込むのか?または埋め込まないのか?
あとはレビューでも客観的にチェックができるように、ログの埋め込むポイントを定義しました。
出力禁止項目も定義することで、出しては駄目な項目がないかを、このタイミングでチェックしたり話し合ったりしていました。
ログのフォーマットは?
フォーマットに関しては扱いやすさを考慮して設定しました。
解析時にはLTSVが便利だったので、ファイルにはLTSV。
開発中のコンソールは見れればいいということでTSVにしました。
細かい出力順などは利用するフレームワークに基本倣うようにしています。
出力項目については、出せるもの、できれば出したいものなど、とりあえず列挙し、適時選定していこうというスタイルを取りました。
ログの保持方法
ここらへんまできて、アプリケーションとしてどういうものになるのかを置かなければいけないと思っていました。 Fluentdで収集するのか、保持期間はどうするのか、アプリケーション起動にはコンテナを使うのか、起動するインフラ環境はオンプレなのかクラウドなのか、などなど。
このときはインフラ担当者と作業責務が分かれていたため、何をどっちが担当するのかを一つずつ確認しながら行う必要があり、けっこう大変でした。
そしてそろそろ面倒くさいなーと思い、まとめに入ったログ指針が以下のようなものです。
ログ出力の目的
以下の目的のため、ログ出力を行います。
- 攻撃や事故の予兆を検知し、早期対策するため
- 攻撃や事故の事後調査のため
- アプリケーションの運用監査のため
- 行動ログから、アプリケーション改善の指針を定めるため
ログ出力要件
ログ出力の要件を記載します。
本設計の範囲とするログの種類
本ログ出力指針は、アプリケーションが出力するログを対象とします。
サーバへのアクセスログは対象外としますが、アプリケーションからDBへのアクセス(CURD)は対象とします。
ログに記録するべき内容・イベント
ユーザが画面上で行うイベントと、認証・アカウント管理や重要情報へのアクセスに関するイベントを記録してください。 特に個人情報に対してのアクセスは必ず記録するようにお願いします。
またログはユーザIDやユニークIDなど、行動実施者とイベントが紐付けれるように記録してください。
認証・アカウント管理や重要情報へのアクセスに関するイベント
- ログイン・ログアウト(失敗も含む)
- アカウントロック
- ユーザ登録・削除
- パスワード変更
- 重要情報の参照
- 主だった操作(商品購入、送金、メール送信など)
出力禁止項目
以下の内容はログに出力しないようにしてください。
- パスワード
- OAuth関連のキー情報
- 個人情報
ログ出力項目
ログには、4W1H(いつ、誰が、どこで、何を、どのように)に従って、以下の項目を出力します。
- 処理日時
- アクセス元情報(ユーザIDなど)
- アクセス対象(URL、ページ名、スクリプトIDなど)
- 操作内容(閲覧、変更、削除など)
- 捜査対象(リソースID、カテゴリIDなど)
- 操作結果(成功・失敗、処理件数など)
また、アプリケーションのクラッシュ情報、Stacktraceなどを出力します。
ログフォーマット
LTSVで出力します。
ただし、コンソールにはTSVで出力します。
出力項目
項目 | キー | オプション |
---|---|---|
ログの出力日時 | date | yyyy-MM-dd HH:mm:ss.SSS |
スレッド | thread | |
ログレベル | level | |
ロガーの名前 | logger | |
ユーザID | user | |
セッションID | session | |
アクセスURL | uri | |
ログメッセージ | message |
サンプル
date:2018-10-20 19:09:42.216 thread:reactor-http-nio-3 level:DEBUG logger:jp.sample.api.search.repository.ItemSearchRepository message:アプリケーションで設定するログメッセージ
ログ出力先
アプリケーションのログは、/var/log/app配下にアプリケーション単位で出力します。
例えばproduct-name(アプリケーション名)の場合は、/var/log/app/product-nameに用途別でログが出力されます。
ログファイル一覧
ログファイル名 | 用途 |
---|---|
application.log | アプリケーションが出力するログ |
application_error.log | アプリケーションログのERRORレベルのみ |
gc.log | JavaアプリケーションのGCログ |
java_error%p.log | Javaアプリケーションが異常終了した場合のログ(プロセス単位) |
heap/dump.log | ヒープエラーのダンプ |
アプリケーションログのローテーション
アプリケーションログは日単位でローテーションします。
ログの保存期間
アプリケーションサーバ上では最低1週間、最大1ヶ月保持します。 不要になったログ(過去ログ)の削除は、アプリケーション側では実施せず、サーバ側(logrotate)で実施します。
その他、CloudWatchにログを転送し、長期保存を行います。
ログレベルの利用基準
ログレベル | 意味合い | 用途 |
---|---|---|
FATAL | 回復不可能なエラー | 利用しない |
ERROR | エラー | 想定外の処理の発生(システムエラー)に関する情報を出力する。Exception情報がある場合は、Stacktraceも本レベルで出力する。 |
WARN | 警告 | システム上エラーではないが、通常発生し得ない(発生を期待していない)処理の発生を記録する。業務処理のエラーを記録する場合も、本レベルで出力する。 |
INFO | 情報 | 各種イベントの発火・実行の事実を出力する(行動ログ) |
DEBUG | デバック用の情報 | 開発時に参考となる情報を出力する。パラメータ値を出力する場合は、基本的にDEBUGとする。 |
TRACE | デバッグよりも詳細な動作トレース | 利用しない |
Stacktraceの出力タイミング
エラーが発生した場合のStacktraceは、発生箇所で都度出力するのではなく、 エラー処理を実際に行う終端で出力します。
参考
LTSVの活用
LTSVはTSVでもあるので、タブ区切りの場所さえわかれば、以下のようにcutでデータを取得することが出来ます。
$ tail -n 10 application.log | cut -f 5
LTSVはキーがついているので、grepで対象のキーを指定して取得することができ、
$ egrep -o "message:[^タブ文字]*" application.log
※タブ文字はCtrl-vを入力後、Tabキーを押下することで入力できます
以下のようなPerlのワンライナーで意図したキーのみを抽出し、好きにフォーマットすることも出来ます。
$ cat application.log | perl -F'\t' -nale '%h=map{split/:/,$_,2}@F;print"$h{date}\t$h{thread}\t"'
終わりに
いかがでしょうか?未完成なところも目につくと思います。
ですがこういうものは作ってそのまま見られなくなるか、また日の目を浴びたときに古くなっているということでそのまま捨てられたりするものだと思うので、 完璧なものでなくても良いと個人的には思います。
ではなぜログ指針の話をしたかというと、このような指針を元に、 自分たちのチームはどう考えてシステムを作っていくのかの意識合わせを行い、観念を共有することがシステム開発では一番大事だと思っているからです。
何もなければ考えをすり合わせるのも難しいので、適時このように課題への解決案を形にしながら、チームでチームのベースを作っていくのがいいのではないでしょうか。
それに捨てられず、ずっとメンテナンスされて、新しいメンバーがチームを知るために使える資料になっている可能性もないわけではないですからね。
参考文献
- 安全なWebアプリケーションの作り方
- 仕事ではじめる機械学習