構造化ログとは - JSON ログの設計と検索性
構造化ログとは、ログを JSON など機械可読な形式で出力し、フィールド単位の検索 / 集計を可能にするロギング手法。非構造化ログとの違い、含めるべきフィールド、失敗パターンを解説
構造化ログとは
構造化ログ (Structured Logging) は、ログメッセージを人間が読むためのテキストではなく、JSON などの機械可読な形式で出力するロギング手法である。CloudWatch Logs Insights、Elasticsearch、Datadog などのログ分析ツールでのクエリ、フィルタリング、集計が格段に容易になる。
従来の非構造化ログは console.log('Failed to process order 123 for user abc') のように自由形式のテキストだった。障害調査で「特定のエラーコードが何回発生したか」を集計するには正規表現でパースする必要があり、フォーマットが少しでも変わるとパースが壊れる。構造化ログはこの問題を根本的に解決する。なお「どのレベルで何を出すか」という上流の設計判断はログ設計の項で扱っており、構造化ログはその設計を機械可読な形式で実現する手段にあたる。
非構造化ログとの比較
非構造化ログとの比較を図で示す。
// ❌ 非構造化ログ: パースが困難
"2026-04-01 09:00:00 ERROR Failed to process order 123 for user abc"
// ✅ 構造化ログ: 機械的に解析可能
{"timestamp":"2026-04-01T09:00:00Z","level":"ERROR","message":"Failed to process order","orderId":"123","userId":"abc","errorCode":"PAYMENT_FAILED"}
| 観点 | 非構造化ログ | 構造化ログ |
|---|---|---|
| 検索 | 正規表現でパース | フィールド名で直接クエリ |
| 集計 | 困難 (パース精度に依存) | stats count() by errorCode で即座に集計 |
| フォーマット変更 | パーサーが壊れる | フィールド追加は後方互換 |
| 人間の可読性 | 高い | やや低い (ツールで補完) |
| ストレージ | 小さい | JSON のオーバーヘッドで 1.5〜2 倍 |
ストレージコストは増えるが、障害調査の速度向上で十分に元が取れる。本番環境で「あのエラーは今月何回起きたか」を 10 秒で回答できるか、30 分かけて grep するかの違いだ。
Lambda Powertools での実装
AWS Lambda Powertools の Logger は、構造化ログの実装を大幅に簡素化する。
console.log を直接使うと、コンテキスト情報の付与を毎回手動で行う必要があり、漏れが発生する。Powertools の Logger は一度設定すれば全ログに自動付与されるため、漏れがない。
CloudWatch Logs Insights でのクエリ
構造化ログの真価はクエリ時に発揮される。
# エラーコード別の発生回数 (過去 24 時間)
fields @timestamp, orderId, errorCode
| filter level = "ERROR"
| stats count() as errorCount by errorCode
| sort errorCount desc
# 特定注文の処理フローを時系列で追跡
fields @timestamp, @log, message, orderId
| filter orderId = "ORD-123"
| sort @timestamp asc
# P99 レイテンシの算出
fields @timestamp, duration
| filter message = "注文処理完了"
| stats pct(duration, 99) as p99, avg(duration) as avg_ms
パーセンタイルの集計関数は pct(フィールド, パーセント) である (percentile() という関数は Logs Insights には無い)。また filter の文字列比較は大文字と小文字を区別するため、出力側の level の表記 (この項の例は大文字 ERROR) と揃っているかを先に確認する。非構造化ログでは parse コマンドで正規表現パースが必要だが、構造化ログならフィールド名で直接アクセスできる。
ログに含めるべきフィールド
すべてのログに共通で含めるべきフィールドと、イベントごとに追加するフィールドを分ける。
共通フィールド (自動付与)
timestamp: ISO 8601 形式level: ERROR / WARN / INFO / DEBUGservice: サービス名function_name: Lambda 関数名function_request_id: リクエスト IDcorrelationId: 相関 ID (設定済みの場合)
イベント固有フィールド (手動付与)
- ビジネスコンテキスト:
orderId,userId,productId - エラー情報:
errorCode,errorMessage,stackTrace - パフォーマンス:
duration,itemCount
よくある失敗パターン
個人情報の混入
ログにメールアドレス、氏名、クレジットカード番号を含めてしまうケース。CloudWatch Logs はデフォルトで暗号化されるが、ログへのアクセス権を持つ全員が個人情報を閲覧できてしまう。個人情報はマスキングするか、ID のみをログに記録し、必要時に別途参照する設計にする。
ログレベルの不適切な設定
本番環境で DEBUG レベルを有効にすると、ログ量が爆発して CloudWatch Logs のコストが跳ね上がる。環境ごとにログレベルを制御する。
| 環境 | ログレベル | 理由 |
|---|---|---|
| dev | DEBUG | 開発中の詳細な動作確認 |
| stg | INFO | 統合テストの動作確認 |
| prod | WARN | コスト抑制、重要な情報のみ |
巨大なオブジェクトのログ出力
リクエストボディやレスポンス全体をログに含めると、1 ログエントリが数 KB〜数 MB になる。CloudWatch Logs の 1 イベント上限は 1,024 KB (2026 年 8 月時点。2025 年 6 月に 256 KB から引き上げ) で、これを超えるログイベントは送信できない。大きなペイロードは S3 に保存し、ログには S3 キーだけを記録する。
構造化ログについては関連書籍でも詳しく扱われている。
この記事は役に立ちましたか?
関連用語
ログ設計とは - アプリ開発で最初に決めるログレベルと出力項目
ログ設計とは、何をどの形式 / どのレベルで記録するかを実装前に決める設計活動。ログレベルの使い分け、含めるべき項目と禁止項目、保持期間とコストの目安を解説
オブザーバビリティ
システムの内部状態を外部から観測可能にし、問題の原因を迅速に特定するための仕組み
相関 ID
分散システムで 1 つのリクエストに紐づく全ログを追跡するための一意な識別子
CloudWatch
AWS のモニタリング / ログ管理サービスで、メトリクス収集、ログ分析、アラートを提供する
ロギング
アプリケーションの動作を記録し、デバッグ / 監視 / 監査に活用する仕組み
ログ集約
分散システムの複数サービスから出力されるログを一元的に収集 / 検索 / 分析する仕組み
関連する記事
DevOps 本ガイド - CI/CD とインフラ自動化を学ぶ技術書の選び方
DevOps の文化と原則から CI/CD、IaC、オブザーバビリティまで学べる技術書の選び方と学習順序を紹介します。
技術書の読書ログを GitHub で管理する - エンジニアらしい記録法
技術書の読書記録を GitHub リポジトリで管理する方法を紹介します。Markdown で読書ノートを書き、コミット履歴で読書の軌跡を残す、エンジニアならではの読書ログ術です。
設計 / アーキテクチャ本ガイド - 設計力を上げる技術書の選び方
ソフトウェア設計を学べる技術書をコード / モジュール / システムの 3 レイヤーに分類し、レベルに応じた読む順番の指針を紹介します。