開発者必読!🤯 MSA地獄から私を救ってくれたOpenTelemetry完全ガイド

「私のコードは確かにうまく動いているのに、なぜサービス全体は遅いのだろう?」「AサービスからBサービスを呼び出すとき、どんなパラメータが渡されたっけ?」

マイクロサービスアーキテクチャ(MSA)が複雑になるにつれて、障害の原因を特定したり、パフォーマンスのボトルネックを分析したりすることはますます困難になります。まるで巨大な迷路の中で道に迷ったような気分です。😭

このような「可観測性(Observability)」の危機の中で、OpenTelemetry(略してOtel)は私たちに救いの綱となってくれます。今日は、MSA地獄で道に迷った開発者のために、OpenTelemetryのすべてをAからZまで徹底的に掘り下げてみましょう!


🤔 そもそもOpenTelemetryとは何ですか?

OpenTelemetryは、可観測性データを生成および収集する方法を標準化したオープンソースフレームワークです。以前は、各ベンダー(Datadog、New Relicなど)や技術(Jaeger、Prometheus)ごとにデータ収集方法がバラバラでした。Otelはこれらすべてを統一し、どのシステムを使用しても同じ方法でデータを収集および送信できるようにする「標準規格」と考えると簡単です。

全体的な流れは次のとおりです。

アプリケーション(データ生成)➡️ OpenTelemetry Collector(中間処理)➡️ 可観測性バックエンド(Jaeger、Prometheusなど)

この構造のおかげで、アプリケーションコードをほとんど修正することなく、データを送信する宛先を自由に切り替える柔軟性を得ることができます。✨

1️⃣ OpenTelemetryの3大コアデータ:シグナル

Otelはシステムを監視するために、3つのコアデータ、つまり「シグナル」を収集します。

🗺️ トレース(Traces):リクエストの全行程を追跡する

ユーザーリクエストがシステムに入ってから出るまで、すべてのサービスとコンポーネントを経由する過程を一つの旅としてまとめて表示します。まるで宅配便がどこまで来ているか配送状況を追跡するようなものです。

  • Trace:一つのリクエストに対する全行程。(例:商品注文リクエスト全体)
  • Span:行程内の一つの作業単位。(例:ログイン確認、在庫確認、決済API呼び出し)

Spanの構造(例)

>

`

{

“name”: “HTTP GET /api/products”,

“trace_id”: “0af7651916cd43dd8448eb211c80319c”,

“span_id”: “b7ad6b7169203331”,

“parent_span_id”: “f3a4a75a9d201b5a”,

“start_time”: “2025-11-09T11:41:00.123Z”,

“end_time”: “2025-11-09T11:41:00.345Z”,

“attributes”: {

“http.method”: “GET”,

“http.status_code”: 200,

“user.id”: “user123”

},

“events”: [

{

“name”: “Cache miss”,

“timestamp”: “2025-11-09T11:41:00.200Z”

}

]

}

`

このtrace_idさえあれば、複数のマイクロサービスに分散している作業(Span)を一つにまとめ、リクエスト全体の流れを一目で把握できます。

📊 メトリクス(Metrics):システムの健全性を測定する

特定の時点でのシステムの状態を数値で表すデータです。車の計器盤を考えると分かりやすいでしょう。

  • Counter:常に増加するだけの値(例:総リクエスト処理数、ウェブサイト総訪問者数)
  • UpDownCounter:増加または減少する可能性のある値(例:現在アクティブなユーザーセッション数)
  • Histogram:値の分布を測定(例:APIリクエストの95%は100ms以内に処理される)
  • Gauge:特定の時点での値(例:現在のCPU使用率、メモリ使用量)

📝 ログ(Logs):特定のイベントの詳細記録

私たちにとって最も馴染みのあるデータです。特定の時点で発生したイベントに関するテキスト記録です。Otelログの真の力は、トレースとの連携にあります。

Otelログの核心!ログにtrace_idとspan_idが含まれます。これにより、「このエラーログはどのリクエスト(Trace)のどの作業(Span)で発生したのか?」を即座に把握できます。もはやログファイルをひたすら調べて原因を推測する必要はありません!

2️⃣ コードにOtelを組み込む:API & SDK

では、これらのデータをどのように生成するのでしょうか?それは、APIとSDKを通じてアプリケーションに「計測(Instrumentation)」コードを追加することです。

  • API:「どのようなデータを収集するか」についての仕様書(設計図)です。
  • SDK:API仕様書を実際に実装した言語ごとのツール(実装体)です。

これらが分離されているため、API標準に合わせてコードを作成すれば、後でSDKの実装を変更してもコードを修正する必要がありません。

計測方法は大きく分けて2つあります。

  1. 自動計測(Automatic Instrumentation)🪄:コードの修正なしに、エージェントやライブラリを追加するだけで、有名なフレームワーク(Spring、Djangoなど)やライブラリ(HTTPクライアント、DBドライバー)のデータを自動的に収集します。最初に試すべき、手軽で強力な方法です!
  2. 手動計測(Manual Instrumentation)✍️:「自社独自の重要なビジネスロジック」のように、自動計測では捉えられない部分を開発者が直接APIを呼び出してデータを生成します。

3️⃣ 万能データハブ:OpenTelemetry Collector

アプリケーションで生成されたデータを直接バックエンドに送信するのは非効率的で危険です。アプリケーションに負荷をかける可能性があり、バックエンドを変更するたびにすべてのアプリケーションコードを修正する必要があるからです。

ここで登場するのが、Otel Collectorです。Collectorは、アプリケーションとバックエンドの間でデータを「受信、処理、エクスポート」する独立したプロキシの役割を果たします。

(Image Source: opentelemetry.io)

Collectorはレゴブロックのように3つの部分で構成されています。

  • レシーバー(Receivers)📥:さまざまな形式(OTLP、Jaeger、Prometheusなど)のデータを受け取ります。
  • プロセッサー(Processors)🛠️:データを加工します。不要なデータをフィルタリングしたり、機密情報をマスキングしたり、データをまとめて効率的に処理(Batch)したりするなどの作業を行います。
  • エクスポーター(Exporters)📤:処理されたデータを最終的な宛先(Jaeger、Prometheus、Datadogなど)にエクスポートします。

💡 なぜCollectorを使うべきなのでしょうか?

>

– 関心事の分離:アプリケーションはデータ「生成」にのみ集中し、Collectorが「処理と送信」を担当することで、アプリの負担を軽減します。

– 柔軟性:データをJaegerとPrometheusに同時に送信したい場合、Collectorの設定ファイルを1行変更するだけで完了です!アプリのコードを触る必要はありません。

– パフォーマンス:Batch Processorを使用すると、データをまとめて一度に送信するため、ネットワーク効率が最大化されます。本番環境では、SimpleSpanProcessor(スパンが生成されるたびに即座に送信)の代わりにBatchSpanProcessorの使用が強く推奨される理由です。

Collector設定ファイルの例(config.yaml)

Collectorがどのように動作するかは、この設定ファイル一つで全て説明されます。

# OpenTelemetry Collectorのconfig.yaml

receivers: # データはOTLPプロトコルで受信する
  otlp:
    protocols:
      grpc:
      http:

processors: # 受信したデータは一括処理し、メモリ使用量を制限する
  batch:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 75

exporters: # 処理されたデータはJaegerに送信し、デバッグのためにコンソールにも出力する
  otlp/jaeger:
    endpoint: "jaeger-all-in-one:4317" # Jaegerアドレス
    tls:
      insecure: true
  logging:
    loglevel: debug

service:
  pipelines: # 上記コンポーネントをパイプラインで接続する
    traces: # トレースデータはこのように処理される
      receivers: [otlp]
      processors: [batch, memory_limiter]
      exporters: [otlp/jaeger, logging]

4️⃣ 分散システムの血管:OTLP & Context Propagation

最後に、これらすべてのコンポーネントがどのように相互に通信するかを見てみましょう。

  • OTLP (OpenTelemetry Protocol) 📡:Otelの公式データ転送プロトコルです。すべてのOtelコンポーネントが理解できる「共通言語」の役割を果たします。
  • Context Propagation 🤝:分散トレーシングの核心技術です。AサービスからBサービスへHTTPリクエストを送信する際、目に見えないところで魔法のようなことが起こります。それは、traceparentというHTTPヘッダーにtrace_idのような追跡情報を乗せて送信することです。

HTTPヘッダーの例

>

`

traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01

`

>

このヘッダーのおかげで、Bサービスは「ああ、このリクエストは0af…トレースの一部だ!」と認識し、自身の作業(Span)を同じトレースに接続できます。この「コンテキスト伝播」がなければ、分散トレーシングは不可能です。


終わりに

OpenTelemetryは単なるもう一つのライブラリやツールではありません。複雑な現代の分散システムの内部を透明に覗き見ることができるようにする標準であり哲学です。

Otelを通じて、私たちは散らばったサービスからのデータを一つにまとめ、全体像を把握し、問題が発生した際には迅速に原因を特定して解決することができます。もう迷路の中でさまよう必要はありません。OpenTelemetryとともに、あなたのシステムに明るい灯台を立ててみてはいかがでしょうか?🚀


Comments

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です