---
title: "構造化ログとは｜JSONでログを機械可読にする仕組みとslog/structlog実装・オブザーバビリティでの使いどころを実装者目線で解説"
url: "https://www.issoh.co.jp/tech/details/15703/"
published: 2026-07-26
updated: 2026-09-27
categories: ["監視・オブザーバビリティ"]
publisher: "株式会社一創"
---

# 構造化ログとは｜JSONでログを機械可読にする仕組みとslog/structlog実装・オブザーバビリティでの使いどころを実装者目線で解説

構造化ログ（structured logging）とは、ログを人が読むための文章としてではなく、JSONのようなキー・バリュー形式で出力し、タイムスタンプ・ログレベル・メッセージ・トレースIDといった要素を個別のフィールドとして機械が検索・集計できるようにする記録手法です。この記事で扱うのは、非構造化ログとの具体的な違いと共通フィールドの設計、Goの`slog`（log/slogパッケージ・Go 1.21で標準ライブラリ入り）やPythonの`structlog`での実装、OpenTelemetryのログデータモデルによるトレースとの相関、rsyslogやログ基盤での収集・検索、そして導入すべき場面と過剰になる場面の見極めです。単に「JSONで吐く」で終わらせず、障害調査で効くログ設計まで落とし込みます。バージョンや日付は2026年7月時点の公式ドキュメントを基準にします。

## まとめ：構造化ログはログを機械可読なフィールドにして検索・相関を効かせる記録手法

先に結論を示します。構造化ログの本質は、1行のログを「意味のわからない文字列」から「フィールドが定義されたデータ」へ変えることにあります。`2026-07-26 12:00:00 ERROR user 42 login failed`のような文章を、`{"time":"...","level":"ERROR","msg":"login failed","user_id":42}`というJSONオブジェクトにする、というのが実体です。こうするとログ基盤側で`level=ERROR かつ user_id=42`のように条件を指定して絞り込め、grepと正規表現でパースする作業から解放されます。

実装は難しくありません。Goなら標準ライブラリの`slog`、PythonならstructlogやloggingのJSONフォーマッタで、数行の初期設定を書くだけで済みます。効きどころは、複数のサービスにまたがる分散システムと、障害調査の頻度が高い運用です。ログに`trace_id`を載せてOpenTelemetryのトレースと突き合わせれば、1リクエストの流れを横断で追えます。そのログをOTelで送出する経路の選び分けは[OpenTelemetryのログ実装｜直接送信とfilelog receiverの選び分け](https://www.issoh.co.jp/tech/details/16555/)にまとめています。逆に、単一プロセスで動く小さなツールや、ログをほとんど見ない用途では、JSON化の手間が見合わないこともあります。導入判断は規模と調査頻度で決めるのが現実的です。

## 構造化ログの基本｜非構造化ログとの違いと機械可読なフィールド設計

構造化ログを理解する近道は、「ログを文章ではなくデータとして扱う」という一点をつかむことです。まずは非構造化ログとの対比から入ります。

### 構造化ログとは何か｜キー・バリューで意味づけされたログレコード

構造化ログは、1つのログを「キーと値の組み合わせ」として表現する記録手法です。従来の`printf`的なログが`ユーザーaliceがAPIに3回アクセスしました`という一続きの文だったのに対し、構造化ログでは`{"user":"alice","count":3}`のように、それぞれの情報が名前のついたフィールドに分かれます。フォーマットはJSONが主流ですが、logfmt（`key=value`を空白区切りで並べる形式）を使う現場もあります。どちらも共通するのは、ログを読むのが人だけでなく機械でもある、という前提に立っている点です。フィールドが定義されていれば、ログ基盤は値の型を保ったまま索引を張り、後から任意の条件で問い合わせられます。

### 非構造化ログとの違い｜grep探索から検索・集計前提への転換

非構造化ログと構造化ログの差は、運用時の「探し方」に最も表れます。非構造化ログでは、障害時にサーバーへSSHで入り、`grep`と正規表現でパターンを組み立てて目的の行を探すのが定番でした。この方式は、ログの書式が少しでも揺れると正規表現が壊れ、複数フィールドをまたぐ集計（例：ユーザーごとのエラー率）はほぼ手作業になります。構造化ログが変えるのはこの点です。フィールドが機械可読なので、ログ基盤側で`status_code >= 500`や`duration_ms > 1000`のような条件検索、フィールド単位の集計・可視化が成り立ちます。

| 観点     | 非構造化ログ（プレーンテキスト） | 構造化ログ（JSON/logfmt） |
| ------ | ---------------- | ------------------ |
| 形式     | 自由な文章の1行         | キー・バリューのレコード       |
| 探し方    | grep＋正規表現        | フィールド条件で検索・集計      |
| 集計     | 手作業・スクリプト頼み      | フィールド単位で自動集計       |
| 可読性（人） | そのまま読みやすい        | 整形しないと読みにくい        |
| 相関     | ID埋め込みでも突合が手間    | trace\_idで横断追跡が容易  |

人の目で1行を読む快適さでは非構造化ログに分があります。開発中にターミナルで眺めるだけなら、色付きのテキストログの方が速いこともあります。差が逆転するのは、ログ量が増え、複数サービスを横断して障害を追う段階です。

### 標準フィールド設計｜timestamp・level・trace\_idの共通化

構造化ログで最初に決めるのは、全サービスで共通させる基本フィールドです。最低限そろえたいのは、発生時刻（`timestamp`）、深刻度（`level`）、人が読む要約（`message`）の3つで、分散システムではこれに`trace_id`／`span_id`を加えます。フィールド名を各サービスでばらばらにすると、ログ基盤で串刺し検索するときに`level`と`severity`と`lvl`が混在して破綻します。命名を統一する土台としては、Elastic Common Schema（ECS）やOpenTelemetryのログデータモデルのように既存のスキーマに寄せる方針が堅実です。加えて、リクエスト単位で意味を持つ属性（`user_id`・`http.method`・`status_code`など）を載せると、後の絞り込みが効きます。ここで決めた共通フィールドが、そのままログ基盤での検索性を左右します。

## 構造化ログの実装｜Goのslog・Pythonのstructlog・出力先の設計

構造化ログは、専用のライブラリを入れなくても始められる言語が増えています。ここでは実装の入り口を、GoとPythonの具体で押さえます。

### Goのlog/slog｜標準ライブラリのJSONHandlerで出力する

Goでは、標準ライブラリの`slog`（log/slogパッケージ）が構造化ログの基点です。`slog`はGo 1.21（2023年8月）で標準ライブラリに追加され、外部依存なしにJSON構造化ログを出力できます。使い方はシンプルで、`slog.New(slog.NewJSONHandler(os.Stdout, nil))`でロガーを作り、`logger.Info("login failed", "user_id", 42)`のように呼ぶと、`{"time":"...","level":"INFO","msg":"login failed","user_id":42}`という1行JSONが出ます。標準キーは`time`・`level`・`msg`です。設計は3層に分かれ、`Logger`が`Record`（Time／Level／Message／Attrs）を作り、それを`Handler`（`JSONHandler`や`TextHandler`）が受け取ってフォーマットします。`slog.String("user","alice")`や`slog.Group("request", ...)`で型を保った属性を付けられ、`WithAttrs`で共通属性をあらかじめロガーに埋め込めます。開発中は`TextHandler`、本番は`JSONHandler`と切り替える構成が定番です。

### Pythonのstructlog・logging｜JSONフォーマッタで構造化する

Pythonでは、標準ライブラリの`logging`にJSON用のフォーマッタを差すか、専用ライブラリの`structlog`を使う2通りが実務的です。`logging`だけで進める場合は、`logging.Formatter`を継承してレコードをJSON文字列にするフォーマッタを書き、ハンドラに設定します。`structlog`を使うと、プロセッサ（処理を連結するパイプライン）でタイムスタンプ付与・ログレベル整形・JSONレンダリングを組み立てられ、`logger.info("login failed", user_id=42)`のようにキーワード引数でそのままフィールドを渡せます。既存の`logging`と連携でき、標準ロガー経由のログもまとめて構造化できる点が実装上の利点です。どちらを採るかは、既存コードが`logging`に深く依存しているなら`logging`＋JSONフォーマッタ、新規で書き味を優先するならstructlog、と分けるのが素直です。

### ログ出力先の設計｜標準出力へ1行JSONを流すstdout方式

実装で見落とされやすいのが、ログをどこへ吐くかです。コンテナ環境では、アプリケーションはファイルではなく標準出力（stdout）へ1行JSONを流し、収集はプラットフォーム側に任せる方式が基本になります。これはThe Twelve-Factor Appが示す「ログはイベントストリームとして扱い、出力先の管理はアプリの責務にしない」という考え方に沿います。アプリはひたすら`stdout`にJSONを書き、Kubernetesならノードのログエージェント、ホスト運用ならrsyslogやFluent Bitが受け取って基盤へ転送する、という分担です。ここでファイルローテーションやバッファリングをアプリに抱え込ませると、責務が肥大化します。コンテナ上でのログとメトリクスの設計をまとめて考える段階では、[Kubernetes監視・モニタリングの設計の解説](https://www.issoh.co.jp/tech/details/15303/)が出力設計の前提を補います。

## 構造化ログとオブザーバビリティ｜トレース相関とログ基盤での検索

構造化ログの価値が最大化するのは、単体で見るときではなく、トレースやメトリクスと突き合わせるときです。オブザーバビリティの文脈で位置づけます。

### OpenTelemetryログデータモデル｜trace\_idでトレースと相関

ログを「探せるデータ」にした次の一手が、トレースとの相関です。OpenTelemetryのログデータモデルは、ログレコードを`Timestamp`／`ObservedTimestamp`、`SeverityText`／`SeverityNumber`（1〜24の数値で表し、大きいほど深刻。17〜20がERROR帯）、`Body`（文章または構造化データ）、`Attributes`、そして`TraceId`／`SpanId`／`TraceFlags`で表現します。`TraceId`と`SpanId`はW3C Trace Contextに準拠し、これをログに載せておくと、分散トレースのどのスパンで出たログかを機械的に結びつけられます。障害調査で「このエラーログは、どのリクエストの、どの処理の途中で出たのか」を一発でたどれる状態です。ログとトレースを同じIDで束ねる計装の全体像は[OpenTelemetryの3つのシグナルとCollectorの解説](https://www.issoh.co.jp/tech/details/3625/)で整理しています。構造化ログは、この相関を成り立たせるための土台にあたります。

### ログ収集・転送｜rsyslog・エージェントからログ基盤への転送

アプリが`stdout`へJSONを吐いた後は、収集・転送のレイヤが受け持ちます。ホスト上ではrsyslogやsyslog-ng、Fluent Bit／Fluentdといったエージェントがログを拾い、フィルタリングや軽い加工をかけてログ基盤へ送る流れです。構造化ログであれば、この段階でJSONをそのままフィールド付きで流せるため、転送先でのパースが軽くなります。送り先がDatadogの場合にどの経路で受けてどう属性へ写すかは、[Datadogのログ収集経路とパイプライン設計](https://www.issoh.co.jp/tech/details/16595/)で扱っています。逆に非構造化ログのままだと、収集エージェント側でGrok（正規表現の名前付きパターン）を書いて無理やり構造に起こす工程が挟まり、書式変更のたびに壊れがちです。Linuxでのログ収集・転送の仕組みと設定は[rsyslogのログ収集・転送とrsyslog.conf設定の解説](https://www.issoh.co.jp/tech/details/13989/)にまとめており、構造化ログの出口設計と合わせて読むと収集経路が具体化します。

### ログ基盤での検索・集計｜フィールド索引を効かせた条件調査と可視化

転送先のログ基盤（Elasticsearch や Loki、クラウドのマネージドサービスなど）では、構造化ログのフィールドに索引が張られ、条件検索と集計が成り立ちます。たとえばAWSのCloudWatch Logsでは、JSON形式で出力したログをCloudWatch Logs Insightsで`fields`／`filter`／`stats`のクエリにかけ、`status_code=500`の件数を時系列で集計する、といった調査が可能です。ここが構造化ログの投資回収点で、非構造化ログでは手作業だった集計が、保存済みクエリとダッシュボードに置き換わります。クラウド上でログ・メトリクス・トレースを1つの基盤に集める構成は[AWSオブザーバビリティの実装（ADOT・CloudWatch）の解説](https://www.issoh.co.jp/tech/details/15297/)で扱っており、構造化ログはその検索性を支える入力データです。ログを含む3種類の監視データを束ねて性能を追う全体像は[APM（アプリケーション性能監視）の仕組みと導入判断の解説](https://www.issoh.co.jp/tech/details/15414/)が判断ハブになります。

## 構造化ログを導入すべき場面と過剰になる場面（規模別の採用判断）

ここは独自の観点で判断を言い切ります。構造化ログは万能ではなく、規模と調査頻度によっては素のテキストログで足りる場面もあります。

### 構造化ログを導入すべき場面｜分散システムと障害調査が多い運用

構造化ログに倒すべきなのは、次の条件が出たときです。第一に、マイクロサービスやコンテナで複数プロセスが動き、1つのリクエストが複数サービスをまたぐ分散システム。`trace_id`で横断追跡できる利得が、そのままフォーマット変更のコストを上回ります。第二に、本番障害の調査が定期的に発生し、ログをフィールドで絞り込みたい運用。第三に、ログを機械で監視し、特定条件でアラートを出したい場合です。これらは要件が明確なので、該当するなら初期設計の段階から構造化ログとフィールド命名規約を決めておくのが得です。後から全ログを構造化し直すのは、命名の統一まで含めると手戻りが大きくなります。

### 構造化ログが過剰になる場面｜単一プロセスでログをほぼ見ないとき

逆に、構造化ログが過剰投資になる場面もあります。単一プロセスで完結する小さなCLIツールやバッチで、開発者が手元のターミナルでログを目視するだけなら、色付きのテキストログの方が速く読め、JSON化はかえって視認性を落とす場面です。ログをほとんど見返さない用途や、運用フェーズに入っていない検証段階のコードでも、フィールド設計に時間をかける価値は薄くなります。現実的な折衷は、開発時はテキスト（Goなら`TextHandler`）、本番はJSON、と出力を環境で切り替える構成です。これなら人の可読性と機械可読性を両取りできます。ログ基盤やオブザーバビリティ環境をどこまで作り込むか、内製と外注のどちらで運用体制を組むかで迷う段階なら、ログ設計から監視基盤の運用・内製化支援まで[保守運用・内製化支援の受託](https://www.issoh.co.jp/service/system/maintenance/)で相談を受け付けています。判断の起点は、あくまで「そのログを機械で検索・集計・相関する必要があるか」に置くのが筋です。

## 構造化ログの実装・JSON化・移行・メリットに関するよくある質問

構造化ログの実装方法やJSONとの関係、導入の得失など、実務でよく挙がる疑問に答えます。

### 構造化ログとJSONログの違いは何ですか？

構造化ログは「ログをキー・バリューのフィールドで表現する」という考え方の総称で、JSONログはその表現形式の1つです。構造化ログのフォーマットにはJSONのほか、`key=value`を並べるlogfmtもあります。実務ではJSONが主流のため、構造化ログとJSONログがほぼ同義で使われる場面も多いですが、厳密にはJSONは実現手段の1つ、という関係です。要点は形式そのものより、フィールドが機械可読で検索・集計できるかどうかにあります。

### 構造化ログのデメリットは何ですか？

主なデメリットは2つです。1つは人の可読性で、JSONの1行は整形しないと目で追いにくく、ターミナルで直接読むにはビューアやログ基盤の整形機能が要ります。もう1つはフィールド設計のコストで、命名規約を決めずに各サービスが好き勝手なキーを使うと、後で串刺し検索が破綻しかねません。加えて、JSONシリアライズのぶんだけログ出力の処理量はわずかに増えます。いずれも、開発時はテキスト出力に切り替える、共通スキーマ（ECSやOpenTelemetry）に寄せる、といった対処で実務上は吸収できます。

### 既存のテキストログから構造化ログへどう移行しますか？

一度に全部を書き換えず、出力の入り口から段階的に進めるのが安全です。まずロギングライブラリを構造化対応のもの（Goなら`slog`、Pythonならstructlogや`logging`＋JSONフォーマッタ）に差し替え、新規のログから`timestamp`・`level`・`message`の共通フィールドで出します。既存のテキストログが残る間は、収集エージェント側でGrokパターンを使ってフィールドに起こし、順次アプリ側の出力を構造化へ寄せる形が現実的です。フィールド命名規約を先に決めておくと、移行後の串刺し検索が成り立ちます。

### 構造化ログにはどんなフィールドを含めるべきですか？

最低限は、発生時刻（`timestamp`）、深刻度（`level`）、人が読む要約（`message`）の3つです。分散システムでは`trace_id`／`span_id`を加え、トレースと相関できるようにします。さらにリクエスト単位で意味を持つ属性として、`user_id`・`http.method`・`path`・`status_code`・`duration_ms`などを載せると、後の絞り込みと集計が効きます。フィールド名はECSやOpenTelemetryのスキーマに寄せ、全サービスで統一しておくのが調査を楽にする鍵です。

### 構造化ログはパフォーマンスに影響しますか？

JSONへのシリアライズが加わるぶん、テキスト出力よりわずかに処理量は増えますが、多くのアプリでは支配的なコストにはなりません。影響が出やすいのは、極端に高頻度なログをホットパスで大量に出す場合です。対策としては、出力するログレベルを本番でINFO以上に絞る、デバッグログをサンプリングする、ログ出力を非同期にする、といった手が定石です。ログ量そのものを絞る設計が効き、フォーマットがJSONかテキストかによる差は、通常その次の論点になります。

## 関連記事

- [APM（アプリケーション性能監視）とは｜仕組み・3種の監視データ・OpenTelemetry計装と導入判断を実装目線で解説](https://www.issoh.co.jp/tech/details/15414/)：構造化ログを含むログ・メトリクス・トレースの3種を束ねて性能を追う、オブザーバビリティの判断ハブ記事です。
- [OpenTelemetry（OTel）とは｜3つのシグナル・OTLP・Collector・Prometheusとの違いを解説](https://www.issoh.co.jp/tech/details/3625/)：構造化ログにtrace\_idを載せてトレースと相関させる計装の全体像を扱っています。
- [AWSオブザーバビリティの実装｜ADOT・CloudWatch・Container Insightsで計装する構成【2026年時点】](https://www.issoh.co.jp/tech/details/15297/)：構造化ログをCloudWatch Logs Insightsで検索・集計する、クラウド側のログ基盤構成です。
- [Kubernetes監視・モニタリングの設計｜メトリクス・ログ・アラート閾値の実装判断](https://www.issoh.co.jp/tech/details/15303/)：コンテナからstdoutへ1行JSONを流すログ出力設計の前提になります。
- [rsyslogとは？Linuxのログ収集・転送の仕組みとrsyslog.conf設定・導入判断を実装目線で解説](https://www.issoh.co.jp/tech/details/13989/)：構造化ログを吐いた後の収集・転送レイヤの仕組みと設定を掘り下げています。
- [外形監視とは？内部監視との違いと監視項目・実装、導入判断を実装目線で解説](https://www.issoh.co.jp/tech/details/15223/)：ログによる内部監視と対をなす、外側からの監視レイヤの補完記事です。

---

出典: [構造化ログとは｜JSONでログを機械可読にする仕組みとslog/structlog実装・オブザーバビリティでの使いどころを実装者目線で解説](<https://www.issoh.co.jp/tech/details/15703/>)（株式会社一創）
