ログ出力の方針
Status: Accepted
要約
このアプリに必要な機能を備えたログ出力部品を自作します。 簡易な機能のみを備えていますが、インターフェースに対する実装を切り替えることで拡張可能な作りとします。
コンテキスト
モバイルアプリ開発に必要なログ出力機能を次の観点で議論し、ログ出力方式、およびログ出力部品の仕様を決定します。
- ログ出力の用途
- ログ出力に必要な機能
- ログレベルの設定
- ログフォーマットの設定
- ログ出力先の設定
- ログに含める内容
- サードパーティー・ライブラリを使用
議論
ログ出力の用途
ログ出力の用途としては次のものが考えられます。
- デバッグ用途(プログラム処理の追跡など)
- アプリ状態の把握
- エラー発生時の障害解析
- パフォーマンス分析
- ユーザ操作の把握・分析
- セキュリティおよび不正防止のための監査・証跡、および証拠能力
開発時にログをデバッグ用途で使用する場面は多いです。 また、運用時の障害解析において、アプリで発生したエラー情報が必要となります。
上記理由から、次の用途を対象とします。
- デバッグ用途(プログラム処理の追跡など)
- エラー発生時の障害解析
一方で、次にあげる用途を満たすには、ログ収集のみならず分析視点での考慮や設計が必要となります。
- アプリ状態の把握
- パフォーマンス分析
- ユーザ操作の把握・分析
このアプリとしては過剰要件となるため、上記用途は対象外とします。 ただし、今後の拡張性を考慮して、(主にログ収集を目的とした)出力先の切替機能をログ出力部品に実装します。
セキュリティ用途でログを活用する要件は、このアプリにはありません。 よって、次の用途も対象外とします。
- セキュリティおよび不正防止のための監査・証跡、および証拠能力
ログ出力に必要な機能
ログ出力に必要な機能として、一般的に次の機能があります。
- ログレベルの設定
- ログフォーマットの設定
- ログ出力先の設定
以下、それぞれの機能についての検討結果を示します。
ログレベルの設定
このアプリではデバッグとエラー発生時の障害解析用途でしかログを使用しません。 そのため、一部のログレベル(デバッグとエラー)しか必要ありませんが、将来的な拡張性を考慮し、次のログレベルを用意することにします。
- トレース
- デバッグ
- 情報
- 警告
- エラー
ログフォーマットの設定
出力内容はアプリの背景や環境(開発環境や本番環境)によって変更したい場合があります。 例えば、出力項目はカンマ区切りにしたい、JSONとしてログを出力したいなどです。 こういった要望に柔軟に対応できるよう、フォーマット設定機能を用意します。
ログ出力先の設定
ログ出力先はコンソールのほか、ログ収集先への送信があります。 ログ収集は出力先の切替機能を用いて実現します。
次の理由によりFirebase Crashlyticsをログ収集先として採用します。
- モバイルアプリのmBaaSとして主流
- プッシュ通知でFirebaseの機能(Firebase Cloud Messaging)を使用するのでそれに併せる(関係する外部サービスを広げない)
ビルドタイプRelease
およびReleaseInHouse
では、ログ出力先をFirebase Crashlyticsとします。それ以外の場合はReact NativeのConsoleに出力し、Metro Bundlerを起動しているターミナル上でログを確認できるようにします。
なお、Firebase Crashlyticsに送信するのはログレベルがエラーのログのみとします。デバッグ用途のログが誤って送信されるのを防ぐためです。
クラッシュ時の情報をクラッシュレポートとしてFirebase Crashlyticsに送信します。 クラッシュレポートには大きく次の2つがあります。
- 致命的な例外発生時(アプリクラッシュ時)に自動的に送信するもの
- 非致命的な例外発生時に明示的に送信するもの
Firebase Crashlyticsをログ収集先として使用するにあたり、次の注意事項があります。
- エラーログは非致命的な例外として記録され、次回のアプリ起動時に送信されます。即座にログが送信されないことに注意してください。
- 最新8件の例外だけを保管します。8件を超える例外をスローすると、古い例外は失われます。ユーザ操作の把握などの用途でエラーログを使用しないよう注意してください。
詳細は、Firebase Crashlyticsドキュメントの「非致命的な例外を報告する」を参照してください。
ログに含める内容
ログに含める内容として、次のものを検討しました。
- 出力日時
- アカウントID
- エラーコード
- 起動ID(アプリ起動時に払い出す一意のID)
- モジュール名
出力日時は、Metro BundlerやFirebase Crashlyticsがデフォルトで出力します。そのため、アプリが出力するログには含めません。
アカウントIDは障害解析時においては必要ですが、デバッグ時に欲しい情報ではありません。 起動IDも同様です。 また、これらの内容はFirebase Crashlyticsの機能を用いて運用時に収集することで補えます。 障害解析時はスタックトレース情報からエラー発生箇所を判断できるため、モジュール名は必要ありません。
よって、ログに含める内容はエラーコードのみとします。 ログ出力部品としてエラーコードを含めるログフォーマットを実装し、それをデフォルトで利用します。 アカウントID、起動IDは障害解析時に必要な情報のため、Firebase Crashlyticsのクラッシュレポートに含めて収集できるよう、別途設定します。
アカウントIDと起動IDは、次の設定を通じてFirebase Crashlyticsに送信します。
- アカウントIDはユーザーIDの設定
- 起動IDはカスタムキーの追加
上記内容は致命的、非致命的な例外発生時を問わずFirebase Crashlyticsに送信されますが、エラーコードは非致命的な例外発生時にのみスタックトレースのファイル名として送信されます。
詳細は、Firebase Crashlyticsドキュメントの「Firebase Crashlyticsのクラッシュレポートのカスタマイズ」を参照してください。
サードパーティー・ライブラリの使用
OSSのログライブラリもいくつか存在します。
案件によって利用したいログライブラリも変わると想定されるため、特定のログライブラリに依存せず、ログライブラリを自由に選択できる部品を作成します。 インターフェースに対する実装を切り替えることでアダプター的に利用することを想定しています。
なお、このアプリで使用するログ出力機能は簡易的なものであるため、実装にログライブラリは使用しないで自作します。
決定
デバッグとエラー発生時の障害解析を用途としてログ出力部品を用意します。 インターフェースに対する実装を切り替えることで、ログライブラリを自由に選択できる部品を作成します。 このアプリにおけるログ出力の実装は、ログレベル、ログフォーマット、ログ出力先の設定といった簡易機能を備えたものとします。
デフォルトではエラーコードをログメッセージに含みます。 障害解析時に必要な次の項目は、Firebase Crashlyticsのクラッシュレポートに含めて収集できるよう別途設定します。
- アカウントID
- 起動ID