このガイドの目的は、サービスをより効果的に監視およびトラブルシューティングできるようにするための基本的な洞察と実践を提供することです。 アプリケーション開発では、ログ記録は見落とされがちですが、堅牢で監視可能なシステムを構築する上で重要な要素です。適切なログ記録を実践することで、アプリケーションの可視性を高め、内部の仕組みに対する理解を深め、アプリケーション全体の健全性を向上させることができます。 デフォルトのログ記録 アプリケーションのエントリ ポイントにデフォルトのログ記録メカニズムを組み込むことは、非常に有益です。この自動ログ記録により、重要なやり取りをキャプチャし、エントリ ポイントの引数を含めることができます。ただし、パスワードなどの機密情報をログに記録すると、プライバシーやセキュリティ上のリスクが生じる可能性があるため、注意が必要です。 一般的なエントリポイント : 受信リクエストとレスポンスの詳細をログに記録する APIエンドポイント : ジョブの開始ポイント、実行の詳細、結果をログに記録します バックグラウンドジョブ : 非同期イベントと関連するインタラクションの処理をログに記録します。 非同期イベント 包括的なログ記録 アプリケーションが実行するすべての重要なアクション、特に状態を変更するアクションは、ログ エントリを生成する必要があります。この徹底的なログ記録アプローチは、問題が発生したときに迅速に特定して対処するための鍵であり、アプリケーションの健全性と機能性を透過的に把握できます。ログ記録をこのように入念に行うことで、診断とメンテナンスが容易になります。 適切なログレベルの選択 アプリケーションによって生成される膨大な量のデータを管理および解釈するには、適切なログ レベルを採用することが重要です。ログを重大度と関連性に基づいて分類することで、重要な問題を迅速に特定して対処できると同時に、監視作業に負担をかけずに、それほど緊急でない情報にもアクセスできるようになります。 以下はログ レベルを効果的に活用するためのガイドラインです。 レベル 説明と例 承認された使用 受け入れられません ERROR システム操作を停止させる致命的なイベント。例: データベース接続の喪失 重大なシステムエラー ユーザーのログイン試行の失敗などの重大でないエラー WARN 問題はありますが、システムは実行を続行し、要求された操作を完了できます。 問題につながる潜在的な問題 定期的な状態の変化 INFO ユーザーアカウントの作成やデータの書き込みなど、通常のアプリケーション機能に関する洞察 状態の変化 変更なしの読み取り専用操作 DEBUG プロセスの開始/終了などの詳細な診断情報 プロセスステップのログ記録はシステム状態を変更しない 定期的な状態変更または高頻度の操作 TRACE メソッドのエントリ/終了を含む最も詳細なレベル プロセスの流れと詳細を理解する 機密情報の記録 ログに記録する ID - 階層的アプローチ アプリケーションでアクションをログに記録する場合、直接関係するエンティティの ID を含めることは、ログ情報をデータベース データにリンクするために重要です。階層的なアプローチでは、項目を親グループまたはカテゴリにリンクすることで、アプリケーションの特定の部分に関連付けられているすべてのログをすばやく見つけることができます。 たとえば、メッセージの送信に失敗したときにチャットの ID のみを記録するのではなく、チャット ルームの ID とそれが属する会社の ID も記録する必要があります。こうすることで、より多くのコンテキストが得られ、問題のより広範な影響を把握できます。 ログエントリの例: Failed to send the message - chat=$roomId, chatRoomId=chatRoomId, company=$companyId 生産ログの例 以下は、階層的アプローチを使用した場合の運用ログの例です。 一貫性と標準化 標準プレフィックス すべてのチームでログ形式を標準化すると、ログの読みやすさと理解しやすさが大幅に向上します。検討すべき標準化されたプレフィックスをいくつか示します。 何か を始める 何か に失敗しました 何かを 完了した 何かを した 省略 何かをやり直して みる 変数値を個別にログに記録する 変数名と値をログ メッセージの本文から分離すると、次のようないくつかの利点があります。 特定の情報をフィルタリングして見つけやすくします ログの検索と解析を簡素化: ログメッセージの作成プロセスをシンプルに保ちます ログメッセージの作成を効率化: 大きな値でもログメッセージの読みやすさが損なわれることはありません メッセージの乱雑さを防止: ログ形式の例: Log message - valueName=value 提案されたプラクティスを使用したログの例 理論的な例 以下に、説明したベスト プラクティスに従って適切に構造化されたログ エントリの例を示します。 2023-10-05 14:32:01 [INFO] Successful login attempt - userId=24543, teamId=1321312 2023-10-05 14:33:17 [WARN] Failed login attempt - userId=536435, teamId=1321312 これらの例は以下を示しています。 : 「ログイン試行成功」や「ログイン試行失敗」などの明確で一貫性のあるプレフィックスにより、ログを理解しやすくなります。 標準化されたログ プレフィックス : 変数名と値はログ メッセージから分離され、明確さが維持され、検索が簡素化されます。 分離された変数値 : 構造化された形式により、ログの読み取りと解析が容易になり、効率的なトラブルシューティングと監視に役立ちます。 読みやすさと一貫性 生産ログの例 以下は、提案されたプラクティスを使用した場合の運用ログの例です。 トレースID ログを特定のユーザー アクションに効果的に関連付けるには、ログに ( とも呼ばれます) を含めることが重要です。ID は、そのエントリ ポイントによってトリガーされるロジックによって生成されるすべてのログで一貫している必要があり、イベントのシーケンスを明確に把握できます。 traceId correlationId 実装例 Datadog などの一部の監視サービスでは、ログのグループ化がすぐに使用できますが、手動で実装することもできます。Spring を使用する Kotlin アプリケーションでは、HandlerInterceptor を使用して REST リクエストのトレース ID を実装できます。 @Component class TraceIdInterceptor : HandlerInterceptor { companion object { private const val TRACE_ID = "traceId" } override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean { val traceId = UUID.randomUUID().toString() MDC.put(TRACE_ID, traceId) return true } override fun afterCompletion(request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?) { MDC.remove(TRACE_ID) } } このインターセプターは、リクエストごとに一意の を生成し、リクエストの開始時にそれを MDC に追加し、リクエストの完了後にそれを削除します。 traceId traceId を含むログの例 このようなログ集約を実装すると、以下の例のようにログをフィルタリングできるようになります。 ログでの UUID と長い ID の使用 多くのシステムでは、エンティティは または ID のいずれかを主要な識別子として使用しますが、一部のシステムでは、異なる目的で両方のタイプの ID を使用する場合があります。ログ記録の目的で各タイプが及ぼす影響を理解することは、情報に基づいた選択を行うために重要です。 UUID Long 考慮すべき事項の内訳は次のとおりです。 ID は、特に 範囲の上限にない場合は、読みやすく、かなり短くなります。 読みやすさ: Long Long ID はシステム全体で一意性を提供し、ID の衝突の問題に直面することなく ID を使用してログを検索できるようにします。ここでの衝突とは、関連のない DB テーブルの 2 つのエンティティが同じ ID を持つ可能性があることを意味します。 一意の値: UUID Long : 長い主キーをエンティティ ID として使用するシステムでは、ランダムな ID を追加するのは通常簡単ですが、 エンティティ ID を持つ分散システムでは、ログ記録専用の ID を持つことは困難またはコストがかかる可能性があります。 システムの制限 UUID UUID Long ログで使用される ID の種類の一貫性は、少なくともエンティティごとに重要です。システムがすでに一部のエンティティのログを生成していて、それらすべてを変更することを検討していない場合は、エンティティを識別するためにすでに使用されている種類を維持する方がよいでしょう。移行期間中は両方の ID をログに記録することを検討できますが、複数の ID を永続的に保持すると、ログが不必要に乱雑になります。 既存のログ: 結論 適切なログ記録方法は、効果的なサービス監視に不可欠です。包括的なログ記録、適切なログ レベル、トレース ID、標準化されたログ形式を組み込むことで、アプリケーションの監視とトラブルシューティングの能力を大幅に強化できます。これらの方法により、ログの明瞭性と一貫性が向上し、問題を迅速に診断して解決しやすくなります。 この投稿を読んでいただきありがとうございます。