1行が1つの出来事とは限らない
一言でいうと
ログ分析の最初の一歩は、数えることではなく、何が1つのレコードかを決めることです。形式が混ざった束で、行数をレコード数と取り違えると、例外1件がエラー10件になって、そのまま報告書に載ってしまいます。
なぜ必要なのか
顧客企業から受け取る最初の束は、たいてい整っていません。アプリケーションは自分好みの形式で出力し、前段のWebサーバーはCombinedアクセスログを使い、ファイアウォールとプロキシはsyslogで送ります。3つのファイルを1つのディレクトリに置いてgrep -c ERRORを実行すると数字が1つ出ますが、その数字には何の意味もありません。
理由は2つです。1つ目、JavaやPythonの例外は複数行です。ヘッダー1行のあとに、at …のフレームが5、6行、そのあとにCaused by:がさらに付きます。行で数えると、例外1件が10件になります。2つ目、行ごとに時刻の表記が違います。1つは+09:00が付き、1つは05/Mar/2026:14:22:31 +0900で、1つはUTCにZです。時刻を文字列で並べ替えると、この3つはばらばらに並びます。
そのため、分析の前に1つの段階が必要です。3つの形式を1行1レコードの構造化された形に変え、時刻を1つの基準にそろえ、フィールド名を統一する作業です。この作業を正規化と呼びます。
どう動くのか
正規化は、4つの決定でできています。
1つ目は、レコードの開始を何と見なすか。最も堅牢な方法は、「行が時刻で始まれば新しいレコード、そうでなければ前のレコードの続き」です。例外のフレームはタブか空白で始まり、Caused by:には時刻がないので、自動的に前に付きます。このルール1つで、複数行の例外が解決します。
2つ目は、時刻をどの文字列に固定するか。RFC 3339が、インターネットで使う表記を定めています。この文書の5.1節には、なぜこの表記を使うのかも書かれています。オフセット表記が同じで、小数の桁数が同じなら、文字列のソートがそのまま時間順のソートになります。そのため、すべての時刻を2026-03-05T05:22:31.118Zのように、UTC・ミリ秒3桁・Zに固定しておけば、そのあとのすべての作業で、sort1回で済みます。
3つ目は、構造化した結果をどこに入れるか。実務のデフォルトはJSON Lines(NDJSON)です。1行にJSONオブジェクトを1つ入れる形式なので、head・tail・splitのような行単位のツールがそのまま使え、100GBのファイルもストリーミングで読めます。1つの巨大なJSON配列は、ファイルを最後まで読まないと最初のレコードを使えないので、大きなログには合いません。
4つ目は、フィールド名を何に統一するか。ここで、車輪の再発明をする理由はありません。OpenTelemetryのログデータモデルは、ログレコードをTimestamp・ObservedTimestamp・SeverityText・SeverityNumber・Body・Attributesのようなフィールドで規定し、「既存のログ形式を、このモデルに曖昧さなく移せること」を設計要件として書いています。Elastic Common Schemaも、同じ場所を狙うもう1つの辞書です。どちらを使うにしても、チームの中で1つに決めておくことが重要です。
syslogを扱うなら、RFC 5424を一度読んでおく価値があります。先頭の<134>はPRIと呼ばれ、その中の数字1つがfacilityとseverityの2つを含んでいます。facilityは商、severityは余りです(8で割ります)。6.2.3節は、TIMESTAMPがRFC 3339のサブセットであり、TとZは必ず大文字でなければならないと、さらに絞り込んでいます。
現場での姿
捨てられる行が、黙って生まれます。パーサーが読めなかった行をcontinueで飛ばすと、その損失はどこにも残りません。RFC 5424は6.1節で、送信の受信者が、対応サイズを超えるメッセージを切ってもよく、捨ててもよいと書いています(最小480オクテット、2048オクテットまでは対応する必要があります)。つまり、切れた行は正常に発生します。そのため、パースの失敗を例外的な状況ではなく、1種類の結果として扱い、原文・ファイル名・行番号を付けて別に残します。あとで「この時刻になぜ記録が空いているのか」を尋ねるとき、そのファイルが答えになります。
同じ理由で、RFC 5424の8.3節は、重要な情報をメッセージの前のほうに置くよう勧めています。後ろが切れても、前は残るからです。
正規化のルールは、コードではなく契約です。どの行をレコードの開始と見なすか、時刻をどう固定するか、読めなかった行をどこに置くかを、ドキュメントに書いておかないと、次の人が同じファイルで違う数字を出します。顧客との次の会話で「次回からは、JSON 1行で送ってください」と求める根拠も、このドキュメントです。
次のラボですること
顧客企業の束をそのまま再現した3つのファイルを作り、行数とレコード数を分けて数えます。そのあと、複数行の例外を1つのレコードにまとめ、アクセスログとsyslogをそれぞれ構造化し、パースできなかった行を隔離します。最後に、3つを共通スキーマにまとめて時間順に並べ、正規化のルールと捨てた行を、報告書として残します。採点ツールは、原本を自分で再度パースして、あなたの結果と突き合わせます。