【図解】OpenTelemetry × Datadog 

## はじめに
こんにちは、Datadog Japan で Sales Engineer をしている [**AoTo**](https://qiita.com/AoTo0330) です。

本投稿は **[<font color="#475BC0">Open</font><font color="#EAAB3B">Telemetry</font> Advent Calendar 2024](https://qiita.com/advent-calendar/2023/otel) 8日目**の記事です。

Datadog で OpenTelemetry によって計装されたメトリクス・トレース・ログを扱うためにはさまざまな観点での考慮事項が必要となります。こうした複雑な考慮事項を紐解くために、計装対象のシステムから**メトリクス・ログ・トレース**を収集し Datadog のバックエンドに転送するまでを網羅的に図解し、各手法について解説します。

Datadog と OpenTelemetry の関係は、2023年12月にも『[Datadog って OpenTelemetry に対応しているの？](https://qiita.com/AoTo0330/items/b9a758555b7e049eca9f)』でも解説しているため、併せてご覧ください。

https://qiita.com/AoTo0330/items/b9a758555b7e049eca9f

## 【図解】 OpenTelemetry × Datadog
現在の Datadog の OpenTelemetry(OTel) との関係を図解すると、以下のになります。

![DD-OTEL_ONE_SHOT.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/5820f329-fbd1-8fb4-3a76-3805beb9f671.png)

昨年からの大きな追加点は、**OpenTelemetry API** による**手動計装(custom instrumentation)** と **Datadog Agent** に埋め込まれた **OpenTelemetry Collector** です。

**OTel SDK, OTel API, Propagation(伝搬)** のそれぞれの切り口で解説します。

## OTel SDK
![DD-OTEL_SDK.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/c91b07cb-635d-74eb-8354-6f82cc9c7783.png)

まずは、各言語の **OpenTelemetry SDK** でトレースの計装をする場合を考えます。OTel はトレースを **OTLP(OpenTelemetry Protocol)** で転送します。この転送先としては大きく<INS>①**OpenTelemetry Colloctor** へ転送する</INS>か<INS>②Datadog Agent へ転送する</INS>かを検討します。

### ①OpenTelemetry Colloctor への転送
**OpenTelemetry Colloctor(OTel Col)** へ転送する場合、**OTel Col** はこれらのトレースを [**OTLP Receiver**](https://github.com/open-telemetry/opentelemetry-collector/blob/main/receiver/otlpreceiver/README.md) で受け取ります。さらに、Datadog バックエンドに転送するには [**Datadog Exporter**](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/datadogexporter) が必要です。

**Datadog Exporter** は**トレース・メトリクス・ログ**の全てをの標準の **Datadog API エンドポイント**へデータを変換し送信します。具体的には、Datadog の[**統合サービスタグ付け**](https://docs.datadoghq.com/ja/getting_started/tagging/unified_service_tagging/)に準拠したタグの付与が挙げられます。

### ②Datadog Agent への転送
**Datadog Agent(DDAgent)** へ転送する場合、DDAgent の受け取り方は2通りあります。
1つ目は従来の受け取り方で、DDAgent 内の Agent, Tracer Agent が `4316/tcp`, `4317/tcp` でトレースを受け取り、内部で適切に変換し **Datadog API エンドポイント**に送信します。

2つ目は「DASH 2024」で発表された新しい方法で、DDAgent 内に埋め込まれた **OTel Col** を利用する方式です。この場合、[**Datadog OpenTelemtry Collector**](https://github.com/DataDog/datadog-agent/blob/main/comp/otelcol/collector-contrib/impl/manifest.yaml) という名前の Distribution が Datadog によって用意され、ベンダー中立的な **Receiver, Processor, Exporter, Connector** がこれらに含まれます。面白い点としては、この **Exporter** に **Datadog Exporter** も含まれず、Datadog には **OTLP Exporter** によってデータが送信されます。

### 今後の展開
独自の **OTel Col** をビルドして、**Datadog Exporter** でデータを Datadog に送信する方式は引き続きサポートされることが予想されます。一方で、現状は **Preview** の **DDAgent** に埋め込まれた **OTel Col** は今後最も推奨される方式となることが予想されます。

https://www.datadoghq.com/product-preview/agent-with-embedded-opentelemetry-collector/

これは、OpenTelemetry のエコシステムがサポートするトレース・メトリクス・ログ(・プロファイラー)などのテレメトリ以外の、ネットワーク・セキュリティ・LLM などの Datadog 独自のテレメトリの収集を実現しつつベンダー中立的な基本的な監視データ収集が実現できるためです。

さらに、**DDAgent** を利用することでその機能である [**Fleet Automation**](https://docs.datadoghq.com/agent/fleet_automation/#control-access-to-fleet-automation) によるバージョン・構成・設定の管理や、[**Remote Flare**](https://docs.datadoghq.com/agent/fleet_automation/#send-a-remote-flare) の利用による迅速な Datadog サポートの利用など Datadog エコシステムの恩恵を多大に受けられます。

さらに、**現状は機能として提供されていません**が、[**Remote Confituration**](https://docs.datadoghq.com/agent/remote_config) による Datadog からの **OTel Col** の構成・設定変更が可能になれば、[**OpAMP(Open Agent Management Protocol)**](https://opentelemetry.io/docs/specs/opamp/) での **Supervisor** や **Server** に悩まされることなく柔軟な構成変更が実現できます。

## OTel API
![DD-OTEL_API.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/6fb29b77-27a4-2e96-193d-3efadd5f7aca.png)
続いて、OpenTelemtry によるアプリケーション計装の仕様である **OpenTelemetry API** との関係を見ていきましょう。

**Datadog APM** は各言語でライブラリの実装のみで自動的に特定のライブラリ・フレームワークの動作を計装する**自動計装**から簡単に初めていただけます。しかし、より詳細な要件が生まれると、**手動計装**による独自のスパンの作成やスパンタグの挿入が不可欠となります。

こうした際に、従来の **Datadog APM** は **OpenTracing** ライブラリをもとにした手動計装の方式などを実装していました。しかし、最新では Datadog APM が対応するすべての言語で [**OTel API サポート**](https://docs.datadoghq.com/ja/opentelemetry/interoperability/api_support/)が実装され、**手動計装**の記載を **OTel ライブラリ**を用いた方式で行えます。

:::note warn
[OpenTelemetry Incubating API](https://opentelemetry.io/docs/languages/java/api/) は**含まれません**。
:::


さらに、**手動計装**だけでなく **Datadog APM SDK** が対応していない**自動計装**を、[**OTel 互換** の 計装ライブラリで計装する](https://docs.datadoghq.com/ja/opentelemetry/interoperability/instrumentation_libraries/)ことが可能です。

これらの **OTel API** への対応・互換性の拡張により、Datadog, OpenTelemetry の両方の特性やメリットを活かした計装が実現できます。さらに、この場合もベンダー中立なメリットとして、コードへの手動計装の記載が Datadog に依存しない方式とできます。

## Propagation(伝搬)
![DD-OTEL_PROPAGATION.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2363567/191eeb70-6c0f-21cc-69d1-b52a5698caa9.png)
最後に、各実装の相互運用性を高めるための **Propagation(伝搬)** についても整理します。

**Datadog APM, RUM** はどちらも W3C Trace Context に準拠した方式での HTTP ヘッダーの受け渡しが可能です。これはつまり、**Datadog RUM SDK** から **OTel SDK** への `traceparent`, `tracestate` 伝搬フィールドの受け渡しができ、さらに **OTel SDK** から **Datadog APM SDK** へも同様です。

実際には **Datadog RUM** は W3C Trace Context に準拠した HTTP ヘッダーを発行し、**OTel SDK** はこれを受け取ることで親スパンを Datadog RUM SDK によって生成されたスパン ID として記録します。

https://www.datadoghq.com/blog/correlate-traces-datadog-rum-otel/

同様に、**Datadog APM SDK** は　W3C Trace Context に準拠した HTTP ヘッダーを受け取ると、独自の `x-datadog-trace-id` と共に、`traceparent`, `tracestate` の伝搬フィールドも受け渡します。これにより、後続に **OTel SDK**, **Datadog APM SDK** のどちらで実装されたアプリケーションがあっても、トレースを伝搬し Datadog 上で単一のトレースとして可視化できます。

https://www.datadoghq.com/blog/monitor-otel-with-w3c-trace-context/

こうしたトレースコンテキストの適切な受け渡しがに Datadog の各 SDK が準拠することで、組み合わせに苦慮することなくさまざまなアプリケーション間の分散トレースが実現できます。

## おわりに
OpenTelemetry × Datadog で現在説明できるすべての組み合わせを入れ込んだ図を作成したいというモチベーションから本記事を執筆しました。

本記事の中で唯一触れられていない機能として、[Datadog バックエンドでの OTLP メトリクスの直接取り込み](https://www.datadoghq.com/product-preview/ingest-otlp-metrics-directly-to-the-datadog-backend/)があります。

https://www.datadoghq.com/product-preview/ingest-otlp-metrics-directly-to-the-datadog-backend/

本機能は、**OpenTelemetry Collector** や **Datadog Agent** を利用できず直接メトリクスを送信する必要がある限定されたユースケースの場合にのみ利用が推奨されており、基本的には[ゲートウェイ型](https://opentelemetry.io/ja/docs/collector/deployment/gateway/)の実装であればこれを回避できます。

そのため、積極的には紹介しませんでしたが明確なユースケースがある場合は是非 **Preview** に申請しご利用の上、ユースケースを共有いただけると嬉しいです🐶