OpenTelemetry は動かせたのに、なぜこんなに複雑なのか?
(iconsolutions.com)- OpenTelemetry (OTel) はオブザーバビリティのフレームワークおよびツール群
- 既存ツールとして Prometheus(メトリクス)、Logstash(ログ)、OpenTracing(分散トレーシング)がある
- OTel はメトリクス、ログ、トレースという 3 つのシグナルを標準化し、OpenTelemetry Protocol (OTLP)、OpenTelemetry Collector、さまざまな言語向け SDK を提供する
- オープンソース、ベンダー非依存、言語非依存、分散、ゼロコードなど、あらゆる流行語を満たしている
OTel の問題点
- ログとメトリクスは既存ツールと似ているため、容易に統合可能。設定を追加するだけで OTel へ移行できる
- トレーシング実装の難しさ
- Context Propagation: 分散システム間でリクエスト情報を伝達するために必要
- リクエスト単位を Trace と Span に分ける
- 例: 「購入する」ボタンのクリック → Frontend → Backend → Payment/Shipping サービス間の関係を Span で表現
- OTel のサポート方法:
- さまざまな Context Propagation 標準を提供(例: b3, W3C Trace Context)
- OTel は複数の標準をサポートする必要がある
- 既存の OpenTracing から OTel へ移行する際、予期しない衝突が発生
- Lightbend Telemetry は OpenTelemetry のログとメトリクスはサポートするが、トレーシングはサポートしていない。
- Context Propagation: 分散システム間でリクエスト情報を伝達するために必要
API 間の衝突問題
Spring と Akka の統合問題
- Spring: アプリケーションのブートストラップと構成管理
- Akka: イベントソーシング、スケジューリング、クラスタリングなどに使用
- 問題:
- OTel 使用時、Spring と Akka のトレーシング API が相互に連携しない
- 同じ Trace ID を共有できない → 誤ったトレース結果になる
解決策: OpenTracing Shim
- OTel Tracer を OpenTracing Tracer に変換するツール
- 問題:
- Akka の Lightbend Telemetry が OpenTracing 実装に適合していない
- Jaeger と OTel が異なる SpanContext を要求し、衝突が発生
解決の過程
OTel と OpenTracing の手動統合
- OTel Context を手動で Jaeger SpanContext に変換:
- OTel コンテキストを Java Map に挿入
- Jaeger SpanContext にそのマップを抽出して手動で設定
- コード例:
var otelContext = new HashMap<>(); GlobalOpenTelemetry.get().getPropagators().getTextMapPropagator() .inject(Context.current(), otelContext, (carrier, key, value) -> carrier.put(key, value)); var openTracingContext = new TextMapCodec(false).extract(new TextMapAdapter(otelContext)); GlobalExtendedTracer.get().local().activateContext(openTracingContext); - 結果:
- Spring と Akka 間のトレーシングデータ統合に成功
- HTTP 境界をまたいでも Trace が正しく接続された
結論
複雑さの原因
- 2 つの異なるトレーシングライブラリを統合しようとしたこと
- OpenTelemetry が提供する標準は有用だが、既存ツールとの衝突の可能性がある
OpenTelemetry の価値
- OpenTelemetry はオブザーバビリティ標準化のために重要な役割を果たす
- 複雑だが強力なオープンソースプロジェクト
今後の課題
- Akka の Trace Context がスレッド間で正しく伝播されるか確認が必要
- プロジェクト改善のため、さらなるテストとフィードバックが不可欠
1件のコメント
Hacker Newsの意見
Otel を学んで移植している間、Java の世界に戻ったような気分だった。コードをたどると EnterpriseFizzBuzz のような感触で、発見可能性がまったくなかった。NodeJS では StatsD より CPU 使用量が約 4 倍で、独自集計によってこれを減らした。OTEL はコアごとに 1 プロセスを使う言語に対して敵対的だ。Prometheus を使うほうがよい。
Otel は、さまざまな可観測性ベンダーが提供する SDK、エージェント、API のせいで複雑に感じられることがある。OpenTelemetry が標準として使われるようになり、Grafana が OpenTelemetry を採用したことは称賛に値する。Datadog の価格は、中規模企業から大企業にかけて手に負えないレベルになった。ドキュメントはもっと改善できるし、オンボーディング文書もプログラミング言語ごとに異なる。NodeJS/Typescript スタックで OpenTelemetry をすぐ始められるパッケージと、サンプルの Grafana スタックを作った。
ローカル開発でログ、トレース、メトリクスのサポートが欲しかったが、複数の Docker イメージは動かしたくなかった。.NET チームが .NET Aspire をリリースし、ローカル開発スタックですべてを簡単に可視化できる。k8s にデプロイするときは OTEL エンドポイントを DataDog エージェントにつなげば、すべて動く。DataDog 独自のトレースライブラリや SDK は避けて、OTEL を使っている。
OpenTelemetry は必要に応じて複雑になりうる。うちのチームではシンプルに使っていて、手動計測で観測対象を慎重に選んでいる。バックエンドは 2 つ使っており、1 つは安価なサードパーティサービス、もう 1 つはローカル開発用の Jaeger 環境だ。
Python で Otel を使うなら、Logfire のクライアントを使うのがよい。Pydantic チームが作ったそのクライアントは、公式の Otel ライブラリよりずっと良くてシンプルだ。
多くの Web フレームワークは、計測の大部分を自動で処理してくれる。opentelemetry-js を使い、Signoz のようなものをセルフホストすれば、1 時間以内に大量のデータを得られる。
OpenTelemetry の導入を簡単にするため、単一コマンドで実行できるオープンソースプロジェクトを始めた。
Python で標準スタックを使えば、いくつか import するだけですべてを自動追跡できる。Otel が複雑なのは、Otel 互換ソフトウェアを販売する企業のために設計されているからだ。
OpenTelemetry はトレースから始まったが、メトリクスとログは専用ソリューションに任せるほうがよい。すべてを 1 つの傘の下に置こうとする試みは、「漏れる抽象化」の問題のように感じる。SQL データベースも何でも同時にできるが、だからといってそうすべきとは限らない。