エンジニアを目指す初学者に向けて、わかりやすく解説したブログです。

ログフォーマットの設計

目的

そもそも

  • 何のために閲覧するか?
  • どうやって閲覧するか?

を考えることが重要である。

何のために閲覧するか?

  • 正常系のログ
    • アクセス、利用状況の集計をしたい
    • 問い合わせがあったときに追跡したい
  • 異常系のログ
    • いつ起こったかしりたい
    • 発生頻度を知りたい
    • 何の処理の途中で起こったか知りたい
    • エラーの詳細情報(スタックトレース)を知りたい

どうやって閲覧するか?

  • サーバーに吐き出されたログファイルをgrepする
  • ログ分析ツールと連携し、正規表現を使ってログをパースする

つまり、絞り込みがしやすく、正規表現でパースしやすいフォーマットにしておくことが重要である。

ログに出力すべき情報

上記の目的が明確になることで、ログに出力すべき情報も自ずと決まってくる。

アプリケーションログの場合

主に開発者がアプリケーション内部の情報について出力するとき。

  • タイムスタンプ
  • トレースID(これはフレームワークやライブラリに任せる)
  • ログレベル( 📄Arrow icon of a page linkログレベルの設計 を参照)
  • ログのコンテンツ
  • (ERRORやWARNログでは)スタックトレース

特に、トレースIDを入れるためには外部ライブラリを入れたり追加設定が必要なケースが多いので
漏れないように注意しておく。

アクセスログの場合

基本的にフレームワークなどが出力してくれるので、あまり意識する必要はない。

  • タイムスタンプ
  • ステータスコード
  • リクエストのあったパス
  • リクエストのメソッド
  • リクエストサイズ、レスポンスサイズ
  • レスポンスにかかった時間
  • UA

JSON形式か、LTSV形式か

ログフォーマットには大きく分けて2種類のフォーマットが存在する。

どちらにすべきという意見は無いが、主に以下の観点で判断するとよい。

  • ログのパースのしやすさ:JSON形式の方がパースしやすい
  • 人間が生ログを見たときの視認性(ローカル開発環境など):LTSV形式のほうが見やすい

LTSV形式

要素をタブ区切りで出力する形式。

time:2025-06-29T12:00:00+09:00	host:example.com	req:GET /index.html	status:200	size:1024	referer:-	ua:Mozilla/5.0	trace_id:abc123def456
time:2025-06-29T12:00:01+09:00	host:example.com	req:POST /login	status:302	size:512	referer:/login	ua:Mozilla/5.0	trace_id:abc123def456
time:2025-06-29T12:00:02+09:00	host:example.com	req:GET /dashboard	status:200	size:2048	referer:/login	ua:Mozilla/5.0	trace_id:abc123def456

JSON形式

{"time":"2025-06-29T12:00:00+09:00","host":"example.com","req":"GET /index.html","status":200,"size":1024,"referer":"-","ua":"Mozilla/5.0","trace_id":"abc123def456"}
{"time":"2025-06-29T12:00:01+09:00","host":"example.com","req":"POST /login","status":302,"size":512,"referer":"/login","ua":"Mozilla/5.0","trace_id":"abc123def456"}
{"time":"2025-06-29T12:00:02+09:00","host":"example.com","req":"GET /dashboard","status":200,"size":2048,"referer":"/login","ua":"Mozilla/5.0","trace_id":"abc123def456"}

\t=を使ってログ出力するのがおすすめ

個人的には以下で統一することを推奨している。

  • ログ内容の区切り文字: タブ \t を使う
  • 変数名とその値を出力するもの: key=value という形で出力

使いがちな文字として「空白」「カンマ」「コロン」などがあるが、
これは出力したいコンテンツの中身に使われる可能性がある文字なので避けておくとよい。

正規表現で集計したときに「空白区切りを想定して正規表現を作っていたが、ログで出力した中身に空白が含まれていたためパースがうまくできない」ということが発生しうる。

まとめ

  • フィルターしやすく、パースしやすいログフォーマットが理想的
    • デリミタは \t、変数名とその中身を出力する場合は =で区切るのがおすすめ
  • JSONかLTSVかは好みでよい(が、組織で統一した方が良い)
  • トレースIDなどは意図的に入れておかないと同一リクエストの判定ができなくなるので注意

関連記事