TL

OpenTelemetry のデータモデルとパイプライン

計装をベンダーロックインから解放する仕組みを原理から理解。SDKからCollectorへ流れるシグナルの共通リソースモデルと、receiver/processor/exporterの3段パイプラインを構成図のように追えます。

応用OpenTelemetryOTLPオブザーバビリティ分散トレースCollector最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.OpenTelemetryはAPI/SDK(生成)とCollector(収集・加工・転送)に分離され、計装コードとバックエンドの依存を切り離す。
  • 2.traces/metrics/logsは別シグナルだが、共通のResource(生成元の属性)とSemantic Conventions(属性の命名規約)を共有し、後段で相関できる。
  • 3.Collectorは receiver→processor→exporter のパイプラインで、protobuf定義のOTLPを内部表現(pdata)に変換して加工し、複数バックエンドへ扇形に送る。

OpenTelemetry(OTel)は「計装の標準化」と言われますが、上級者が押さえるべきはそのデータモデルとパイプラインの分離設計です。なぜ計装コードを書き換えずにバックエンドを差し替えられるのか、なぜ別物に見える traces/metrics/logs を相関できるのか。本稿はこの2点を内部構造から説明します。三本柱の情報理論的な意味は/devops/observability-pillars-internals/を前提とします。

全体像:生成と収集の二層分離

OTelは責務を2層に切り分けます。

  • API/SDK 層(プロセス内):アプリケーションコードが span・メトリクス・ログレコードを生成する。APIは型と関数の定義だけ、SDKがサンプリングやバッチ化など実装を担う。
  • Collector 層(プロセス外):生成済みデータを受け取り、加工し、1つ以上のバックエンド(Jaeger、Prometheus、Loki など)へ転送する独立プロセス。

この分離が肝心です。アプリはOTLP(OpenTelemetry Protocol)でCollectorに吐くことだけを知り、最終的な保存先を知りません。バックエンドを差し替えてもアプリの計装コードは無傷です。これが/devops/distributed-tracing/で「事実上の標準」とされる理由の中核です。

[アプリ + SDK] --OTLP(gRPC/HTTP)--> [Collector] --各種exporter--> [複数バックエンド]
   生成(in-process)                  収集・加工・転送              保存・可視化

共通データモデル:Resource とシグナル

3シグナルが「別パイプラインなのに相関できる」理由は、共通の土台を共有しているからです。

Resource:誰が出したかを表す不変属性

Resource は、テレメトリの生成元を表す属性集合です。service.nameservice.versionhost.namek8s.pod.name などのキーと値を持ち、そのプロセスから出る全シグナルに共通で付与されます。traces も metrics も logs も同じ Resource を共有するため、後段で「同じ pod の同じ service が出したログとトレース」を突き合わせられます。

Semantic Conventions:属性の命名規約

属性キーをチームごとに自由に決めると相関できません。OTelはSemantic Conventions(セマンティック規約)で属性名を標準化します。HTTPサーバーのspanなら http.request.methodhttp.response.status_codeurl.path のように、意味と型をスペックで固定する。これによりバックエンドやダッシュボードが「どのキーがHTTPメソッドか」を機種非依存で解釈できます。規約は安定版と実験版に分かれ、http.method から http.request.method への改名のように版を追って整理されてきました。

ResourceとSpan属性の役割分担

同じ「属性」でも層が違います。Resource属性は「生成元(service/host/pod)」を表し、プロセス内で不変。Span属性やLogRecord属性は「そのイベント固有」の値(リクエストパス、ステータス)。相関の主キーは前者のResourceと、後述の trace_id の二系統で張られます。

3シグナルの構造

シグナル中核データ構造時間の扱い
tracesSpanの木(trace_id/span_id/parent_span_id、開始・終了時刻、status、events)区間(開始〜終了の2点)
metricsSum/Gauge/Histogram等のデータポイント列(属性付き、累積 or 差分のtemporality)時刻つきの数値点
logsLogRecord(timestamp、severity、body、属性、任意のtrace_id/span_id)単一時刻のイベント

重要なのは、logs の LogRecord が任意で trace_id/span_id を持てる点です。これにより、ログを発生元のspanへ直接ぶら下げられ、三本柱の相関が「時刻の近さ」ではなく共有キーで成立します。

OTLP:シグナルを運ぶ共通ワイヤ形式

SDKとCollectorの間、Collectorとバックエンドの間を流れるのがOTLPです。OTLPはProtocol Buffersでスキーマが定義され、gRPC(既定)またはHTTP/protobufで転送されます。

OTLPの構造は3シグナルで共通の入れ子になっています。トレースなら次の階層です。

ResourceSpans            # ある Resource(service等)に属する
  └ ScopeSpans           # ある計装スコープ(ライブラリ名/版)に属する
      └ Span[]           # 実際の span 群

metrics は ResourceMetrics → ScopeMetrics → Metric[]、logs は ResourceLogs → ScopeLogs → LogRecord[]同じ3段構造を取ります。最上位が必ず Resource でくくられているため、転送単位の時点で「どの生成元のデータか」が保たれます。SDKは内部でこのバッチを組み立て、BatchProcessor 相当の仕組みで一定件数・一定間隔ごとにまとめて送出します(1イベント1送信ではない)。

計装スコープ(Scope)の意味

ResourceとSpanの間にある ScopeSpans の「スコープ」は、そのテレメトリを生成した計装ライブラリの名前と版です。io.opentelemetry.http-client のように識別され、どのインストルメンテーションが出力したかを後から切り分けられます。バグのあるライブラリ版からのデータだけ除外する、といった運用に効きます。

Collector の内部:3段パイプライン

Collectorの本体は receiver → processor → exporter の3段パイプラインです。各段はプラグインで、設定ファイルで組み替えます。

  1. receiver(受信):データを取り込む入口。OTLP receiver のほか、Prometheusのスクレイプ、Jaeger/Zipkin形式、ホストメトリクスなど多様な入力を受ける。受信した時点で内部表現に変換される。
  2. processor(加工):パイプライン上で順番に適用される変換。バッチ化(batch)、メモリ保護(memory_limiter)、属性の追加・削除(attributes)、リソース付与、フィルタ、そして全スパンをバッファしてから採否を決めるテールサンプリング(tail_sampling)などがある。順序が意味を持つ点が重要。
  3. exporter(送出):加工後データを外部へ出す出口。OTLP exporter、Prometheus exporter(リモートライト/スクレイプ)、各種ベンダー向けなど。1つのパイプラインから複数exporterへ扇形に複製でき、同じトレースをJaegerと長期ストレージへ同時送出できる。
# Collector 設定の骨子(パイプラインは signal ごとに定義)
receivers:
  otlp: { protocols: { grpc: {}, http: {} } }
processors:
  memory_limiter: {}
  batch: {}
exporters:
  otlp/tempo: { endpoint: "tempo:4317" }
  prometheusremotewrite: { endpoint: "http://mimir/api/v1/push" }
service:
  pipelines:
    traces:  { receivers: [otlp], processors: [memory_limiter, batch], exporters: [otlp/tempo] }
    metrics: { receivers: [otlp], processors: [memory_limiter, batch], exporters: [prometheusremotewrite] }

パイプラインはシグナルごとに独立して定義します(traces 用、metrics 用、logs 用)。receiver と exporter はシグナルをまたいで共有できますが、processor の適用列はパイプラインごとに別です。

pdata:内部表現と変換コスト

Collectorは受け取ったOTLPを、内部で pdata と呼ばれる正規化表現に変換し、processor はこの pdata を操作します。exporter で再び目的の形式へ直列化します。つまりCollectorの実体は「任意の入力形式 → pdata → 任意の出力形式」という変換ハブです。これが、Prometheusで集めてOTLPで送る、といった異種接続を可能にします。一方で、形式変換と pdata のアロケーションは無視できないCPU・メモリ負荷で、memory_limiter による背圧と batch によるまとめ送りが運用上ほぼ必須になります。

processorの順序は結果を変える

processor はパイプライン上で記述順に適用されます。例えば memory_limiter は batch より前に置き、過負荷時に早く落とすのが定石です。テールサンプリングを attributes 加工の後に置くか前に置くかで、サンプリング判断に使える属性が変わります。「同じ部品でも並び順で挙動が変わる」のは、各 processor が pdata を逐次変換する設計の必然です。

デプロイ形態:Agent と Gateway

Collectorは配置で2形態に大別されます。

形態配置主な役割
Agent(sidecar/daemonset)各ホスト・各Podの近く低遅延の受信、ホスト属性付与、一次バッチ
Gateway(中央集約)クラスタ単位の集約層テールサンプリング、集約、バックエンド振り分け

テールサンプリングは「1トレースの全スパンが同じCollectorインスタンスに集まる」必要があるため、ロードバランシングexporterでtrace_id単位に寄せた上でGateway層に置く、という構成が定番です。Agentだけではスパンが分散して尾部判断ができません。サンプリングの原理は/devops/tracing-context-propagation/を参照してください。

まとめ

  • OTelは**API/SDK(生成)とCollector(収集・加工・転送)**の二層分離で、計装コードとバックエンドの依存を切る。アプリはOTLPで吐くことだけを知る。
  • traces/metrics/logs は別シグナルだが、**共通のResource(生成元属性)とSemantic Conventions(命名規約)**を共有し、logs は trace_id を持てるため、時刻ではなく共有キーで相関できる。
  • OTLPはprotobuf定義で Resource→Scope→シグナル本体 の3段構造を3シグナル共通に取り、転送単位で生成元を保つ。
  • Collectorは receiver→processor→exporter のパイプラインで、内部表現pdataへ変換して加工し、複数バックエンドへ扇形送出する。processorは順序が結果を左右し、テールサンプリングはGateway形態で機能する。
  • 何をどれだけ保持・集約するかの判断は、基数の観点(/devops/metrics-cardinality/)と合わせて設計すると軸が定まります。

DevOps/インフラ Article

OpenTelemetry のデータモデルとパイプラインを実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

OpenTelemetry

比較で見る軸

難易度: advanced / カテゴリ: DevOps/インフラ / タグ数: 5

導入後に効く点

traces/metrics/logsは別シグナルだが、共通のResource(生成元の属性)とSemantic Conventions(属性の命名規約)を共有し、後段で相関できる。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
DevOps/インフラ
タグ数
5

判断チェックリスト

  • 自社の用途が「OpenTelemetry / OTLP」に近いか確認する。
  • 強みである「OpenTelemetryはAPI/SDK(生成)とCollector(収集・加工・転送)に分離され、計装コードとバックエンドの依存を切り離す。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

OpenTelemetryOTLPオブザーバビリティ分散トレースCollectorOpenTelemetryOTLPオブザーバビリティ
参考: 公式情報