クラウドネイティブなシステムの可観測性(Observability)を高めるうえで、OpenTelemetry(OTel)は事実上の業界標準になりつつあります。一方、Datadogはメトリクス・トレース・ログを統合的に扱える商用プラットフォームとして高い完成度を持っています。「ベンダーロックインは避けたいが、Datadogの分析機能やアラート機能は活用したい」――この両立を実現するのがOTelとDatadogの統合です。

本記事では、テレメトリの送信アーキテクチャ選定からYAML設定例、言語別の計装コード、Kubernetes本番構成、そして移行ステップまでを体系的にまとめています。

OpenTelemetryとDatadog統合の全体像

OpenTelemetryの位置づけ

OpenTelemetryはCNCF(Cloud Native Computing Foundation)が管理するオープンソースのオブザーバビリティフレームワークです。トレース・メトリクス・ログという3つのテレメトリシグナルを、ベンダー非依存の統一API/SDKで収集・送信できます。2019年にOpenTracingとOpenCensusが統合して誕生し、CNCFのIncubatingプロジェクトとして活発に開発が進んでおり、Kubernetesに次いで2番目にアクティブなCNCFプロジェクトです(出典: CNCF)。

Datadogの役割

Datadogはインフラ監視・APM・ログ管理・セキュリティモニタリングなどを統合的に提供するSaaSプラットフォームです。900以上のインテグレーションを持ち、ダッシュボード、アラート、Watchdog(異常検知AI)など運用に必要な機能が揃っています。料金体系はホスト単位・イベント単位の従量課金が基本で、APMは1ホストあたり月額$31(APM)/$35(APM Pro)/$40(APM Enterprise)です(出典: Datadog Pricing)。

なぜ統合するのか

OTelとDatadogを組み合わせる主な動機は次の3点です。

  • ベンダーロックインの回避: 計装コードがOTel標準APIに準拠するため、バックエンドをDatadog以外に切り替える際のアプリケーション改修が不要になります
  • Datadogの高度な分析機能の活用: Watchdogによる自動異常検知、Continuous Profiler、Error Trackingなど、OSSバックエンドでは得にくい機能をそのまま使えます
  • マルチベンダー戦略: OTel Collectorを中間に挟めば、同じテレメトリデータをDatadogとGrafana Cloudなど複数バックエンドに同時送信できます

テレメトリ送信アーキテクチャの選択肢

OTelで計装したアプリケーションからDatadogへテレメトリを送る構成は、大きく3パターンに分かれます。

パターン1: OTel SDK → OTel Collector → Datadog Exporter

OTel × Datadog 4つの構成パターン(OTel Collector、Datadog Agent、DDOT Collector、ハイブリッド方式)

パターン1(OTel Collector + Datadog Exporter) は、OTel Collectorにdatadogexporterを組み込み、Datadog APIへ直接送信する構成です。Datadog Agentが不要なため、管理対象のコンポーネントが少なくなります。OTel Collectorのprocessorで柔軟にフィルタリングやサンプリングを制御できる点も利点です。

パターン2(Datadog Agent OTLP Ingest) は、Datadog Agent v6.32+/v7.32+(トレース・メトリクス)およびv6.48+/v7.48+(ログ)に搭載されたOTLPレシーバーを使い、OTel SDKからのデータをAgentが受信する構成です。Agentがホストメタデータやライブコンテナ情報を自動付与するため、インフラ監視との統合がシームレスになります。既にDatadog Agentを運用している環境では追加コンポーネントが不要です。

パターン3(DDOT Collector) は、2024年のDASHカンファレンスで発表された、DatadogがOTel Collectorを統合した新しいアプローチです。Datadog Agent v7.65以降で利用でき、既存のOTel Collector設定YAMLをそのまま渡せます。Datadog独自のInfrastructure Attribute Processorが組み込まれ、KubernetesタグのOTLPテレメトリへの自動付与が可能です。Fleet Automationによるリモート管理にも対応しています(出典: Datadog Blog)。

パターン4(Datadog SDK + OTel API ハイブリッド) は、アプリケーションコード上ではOTel APIを使いつつ、内部ではDatadog SDKのTracerProviderがトレースを処理する構成です。OTel APIの標準的なインターフェースでコードを書けるため移植性を保ちつつ、Datadog固有の機能(Continuous Profiler連携、Dynamic Instrumentation等)をフル活用できます。

構成パターンの選定基準

評価軸OTel Collector + DD ExporterDatadog Agent OTLPDDOT CollectorDD SDK + OTel API
ベンダー非依存性高い中程度中程度低い
Datadog機能の活用度標準的高い高い最大
運用コンポーネント数CollectorのみAgentのみAgentのみAgentのみ
マルチバックエンド送信容易不可可能不可
Kubernetes統合手動設定自動自動自動
設定の柔軟性非常に高い中程度高いSDK依存
導入の容易さ中程度容易容易容易

選択の指針:

  • バックエンド切り替えの可能性を重視するならパターン1
  • 既にDatadog Agentが稼働していて手早く導入したいならパターン2
  • OTel標準とDatadog機能を最大限両立させたいならパターン3(DDOT Collector)
  • Datadogを長期的に使い続ける前提で機能をフル活用したいならパターン4

OTel Collector + Datadog Exporterの設定

基本構成のYAML例

OTel Collectorをスタンドアロンで動かし、Datadog Exporterでデータを送信する設定例です。

# otel-collector-config.yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: "0.0.0.0:4317"
      http:
        endpoint: "0.0.0.0:4318"

processors:
  batch:
    send_batch_size: 100
    send_batch_max_size: 1000
    timeout: 10s
  resourcedetection:
    detectors: [env, system, docker]
    timeout: 5s

exporters:
  datadog:
    api:
      site: "datadoghq.com"   # USサイトの場合
      key: "${env:DD_API_KEY}"
    traces:
      span_name_as_resource_name: true
    metrics:
      resource_attributes_as_tags: true

connectors:
  datadog/connector:

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [resourcedetection, batch]
      exporters: [datadog/connector, datadog]
    metrics:
      receivers: [otlp, datadog/connector]
      processors: [resourcedetection, batch]
      exporters: [datadog]
    logs:
      receivers: [otlp]
      processors: [resourcedetection, batch]
      exporters: [datadog]

設定のポイント

  • datadog/connector: トレースからAPMメトリクス(リクエスト数、レイテンシ、エラー率)を自動生成するコンポーネントです。traceパイプラインのexporterとmetricsパイプラインのreceiverの両方に含めます
  • batch processor: timeout: 10sはDatadog Exporterの推奨値です。バッチ処理でAPI呼び出し回数を削減し、ペイロードサイズの最適化も行います
  • resourcedetection: ホスト名、OS、コンテナIDなどのメタデータを自動検出してリソース属性に付与します
  • span_name_as_resource_name: true: OTelのスパン名をDatadogのリソース名にマッピングします。falseの場合、操作タイプ(http.request等)がリソース名になります

OTel Collectorのビルド

DatadogエクスポーターはContribディストリビューションに含まれています。カスタムビルドする場合はocb(OpenTelemetry Collector Builder)を使います。

# builder-config.yaml
dist:
  name: otelcol-datadog
  output_path: ./build

exporters:
  - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter v0.115.0

connectors:
  - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/connector/datadogconnector v0.115.0

receivers:
  - gomod: go.opentelemetry.io/collector/receiver/otlpreceiver v0.115.0

processors:
  - gomod: go.opentelemetry.io/collector/processor/batchprocessor v0.115.0
ocb --config builder-config.yaml

Datadog AgentでのOTLP受信設定

datadog.yamlの設定

Datadog Agentの設定ファイルにOTLPレシーバーを有効化する記述を追加します。

# /etc/datadog-agent/datadog.yaml
otlp_config:
  receiver:
    protocols:
      grpc:
        endpoint: "0.0.0.0:4317"
      http:
        endpoint: "0.0.0.0:4318"

# ログの OTLP 受信を有効化(デフォルトは無効)
otlp_config:
  logs:
    enabled: true

# ログ収集自体を有効化(前提条件)
logs_enabled: true

環境変数での設定(コンテナ環境向け)

Docker ComposeやKubernetesのマニフェストでは環境変数が便利です。

environment:
  - DD_OTLP_CONFIG_RECEIVER_PROTOCOLS_GRPC_ENDPOINT=0.0.0.0:4317
  - DD_OTLP_CONFIG_RECEIVER_PROTOCOLS_HTTP_ENDPOINT=0.0.0.0:4318
  - DD_OTLP_CONFIG_LOGS_ENABLED=true
  - DD_LOGS_ENABLED=true
  - DD_API_KEY=${DD_API_KEY}

注意点

  • メトリクスとトレースのOTLP受信はデフォルトで有効ですが、ログの受信はデフォルトで無効です。想定外のログ課金を防ぐためにこの仕様になっています
  • Datadog AgentはOTLPデータを受信した際、自動でホストタグやコンテナタグを付与します。OTel Collectorのresourcedetection processorに相当する機能が組み込まれています

言語別の計装サンプル

Go: OTel SDK → OTLP送信

package main

import (
    "context"
    "log"

    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
    "go.opentelemetry.io/otel/sdk/resource"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
    semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
)

func initTracer() (*sdktrace.TracerProvider, error) {
    ctx := context.Background()

    // OTel Collector または Datadog Agent の OTLP エンドポイントへ送信
    exporter, err := otlptracegrpc.New(ctx,
        otlptracegrpc.WithEndpoint("localhost:4317"),
        otlptracegrpc.WithInsecure(),
    )
    if err != nil {
        return nil, err
    }

    res, err := resource.New(ctx,
        resource.WithAttributes(
            semconv.ServiceNameKey.String("my-go-service"),
            semconv.DeploymentEnvironmentKey.String("production"),
            semconv.ServiceVersionKey.String("1.0.0"),
        ),
    )
    if err != nil {
        return nil, err
    }

    tp := sdktrace.NewTracerProvider(
        sdktrace.WithBatcher(exporter),
        sdktrace.WithResource(res),
    )
    otel.SetTracerProvider(tp)
    return tp, nil
}

func main() {
    tp, err := initTracer()
    if err != nil {
        log.Fatal(err)
    }
    defer tp.Shutdown(context.Background())

    tracer := otel.Tracer("my-go-service")
    ctx, span := tracer.Start(context.Background(), "handleRequest")
    defer span.End()

    // ビジネスロジック
    processOrder(ctx)
}

func processOrder(ctx context.Context) {
    tracer := otel.Tracer("my-go-service")
    _, span := tracer.Start(ctx, "processOrder")
    defer span.End()
    // ...
}

Go: Datadog SDK + OTel API(ハイブリッド方式)

package main

import (
    "context"

    "go.opentelemetry.io/otel"
    ddotel "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/opentelemetry"
    ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
)

func main() {
    // Datadog TracerProvider を OTel API に登録
    tp := ddotel.NewTracerProvider(
        ddtracer.WithService("my-go-service"),
        ddtracer.WithEnv("production"),
    )
    defer tp.Shutdown()
    otel.SetTracerProvider(tp)

    // 以降は標準の OTel API でスパン生成
    tracer := otel.Tracer("my-go-service")
    ctx, span := tracer.Start(context.Background(), "handleRequest")
    defer span.End()

    processOrder(ctx)
}

Java: OTel Java Agent + OTLP送信

Javaの場合、OTel Java Agentを使うとコード変更なしで自動計装が可能です。

# OTel Java Agent をダウンロード
curl -L -o opentelemetry-javaagent.jar \
  https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar

# アプリケーション起動時に Agent をアタッチ
java -javaagent:opentelemetry-javaagent.jar \
  -Dotel.service.name=my-java-service \
  -Dotel.exporter.otlp.endpoint=http://localhost:4317 \
  -Dotel.exporter.otlp.protocol=grpc \
  -Dotel.resource.attributes=deployment.environment=production \
  -jar my-application.jar

Python: OTel SDK + OTLP送信

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource, SERVICE_NAME

resource = Resource.create({
    SERVICE_NAME: "my-python-service",
    "deployment.environment": "production",
})

provider = TracerProvider(resource=resource)
otlp_exporter = OTLPSpanExporter(
    endpoint="localhost:4317",
    insecure=True,
)
provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
trace.set_tracer_provider(provider)

tracer = trace.get_tracer("my-python-service")

with tracer.start_as_current_span("handle_request") as span:
    span.set_attribute("http.method", "GET")
    span.set_attribute("http.url", "/api/orders")
    # ビジネスロジック

トレース・メトリクス・ログの統合

トレースコンテキスト伝搬(W3C Trace Context / traceparent)

分散トレーシングでは、サービス間でトレースコンテキストを伝搬する必要があります。OTelはデフォルトでW3C Trace Context仕様を採用しており、HTTPヘッダーtraceparentでトレースIDとスパンIDを伝搬します。

traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
             |   |                                 |                |
             ver  trace-id (128bit)                span-id (64bit)  flags

Datadog AgentはW3C Trace Contextに対応しており、OTel SDKから送信されたtraceparentヘッダーを正しく解釈します。注意点として、DatadogのネイティブなTrace IDは従来64bitでしたが、現在は128bitにも対応しています。OTel Collectorを経由する場合、128bit Trace IDがそのまま保持されます。

伝搬フォーマットの設定(Datadog Agentの場合):

# datadog.yaml
apm_config:
  # W3C Trace Context を優先的に使用
  propagation_style:
    - tracecontext
    - datadog

ログとトレースの紐付け

ログにトレースIDを埋め込むことで、DatadogのUIからログとトレースを横断的に検索できます。

Goの場合(zap Logger):

import (
    "go.opentelemetry.io/otel/trace"
    "go.uber.org/zap"
    "fmt"
    "strconv"
)

func logWithTrace(ctx context.Context, logger *zap.Logger, msg string) {
    spanCtx := trace.SpanContextFromContext(ctx)
    if spanCtx.IsValid() {
        // Datadog の 128bit Trace ID → 下位 64bit を 10進数に変換
        traceID := spanCtx.TraceID()
        lower64 := traceID[8:]  // 下位8バイト
        ddTraceID := fmt.Sprintf("%d",
            binary.BigEndian.Uint64(lower64))
        ddSpanID := fmt.Sprintf("%d",
            binary.BigEndian.Uint64(spanCtx.SpanID()))

        logger.Info(msg,
            zap.String("dd.trace_id", ddTraceID),
            zap.String("dd.span_id", ddSpanID),
            zap.String("dd.service", "my-go-service"),
            zap.String("dd.env", "production"),
        )
    }
}

OTelメトリクスのDatadogメトリクスへのマッピング

OTelメトリクスは、Datadog Exporterまたは Datadog Agent を通じてDatadogのメトリクス形式に変換されます。変換時のマッピングルールを理解しておくと、ダッシュボードやアラートの設計がスムーズです。

OTel メトリクスタイプDatadog メトリクスタイプ備考
Counter(単調増加)Countデルタ値に変換
UpDownCounterGauge現在値をそのまま送信
HistogramDistributionパーセンタイル計算が可能
GaugeGaugeそのまま送信

重要なのは、OTelはデフォルトでCumulative(累積) Temporalityを使いますが、DatadogはDelta(差分) Temporalityを期待する点です。Datadog ExporterおよびDatadog AgentのOTLP受信は自動でCumulative→Delta変換を行いますが、サードパーティのexporterを使う場合はこの変換が行われないことがあります。

サンプリング戦略の設計

テレメトリデータ量はサービスの規模に比例して増大し、Datadogの課金にも直結します。適切なサンプリング戦略の設計は運用コスト管理の要です。

Head-based Sampling(ヘッドベースサンプリング)

トレースの開始時点でサンプリング判定を行います。実装がシンプルで予測可能なデータ量になる反面、エラーやレイテンシ異常のトレースを取りこぼす可能性があります。

// Go OTel SDK でのサンプリング率設定
tp := sdktrace.NewTracerProvider(
    sdktrace.WithSampler(
        sdktrace.ParentBased(
            sdktrace.TraceIDRatioBased(0.1), // 10% サンプリング
        ),
    ),
    sdktrace.WithBatcher(exporter),
)

Tail-based Sampling(テイルベースサンプリング)

OTel Collectorでトレース完了後にサンプリング判定を行います。エラートレースや高レイテンシトレースを確実に保持できます。

# OTel Collector の tail_sampling processor 設定
processors:
  tail_sampling:
    decision_wait: 10s
    num_traces: 50000
    policies:
      # エラーを含むトレースは全て保持
      - name: errors-policy
        type: status_code
        status_code:
          status_codes:
            - ERROR
      # レイテンシが 1 秒以上のトレースを保持
      - name: latency-policy
        type: latency
        latency:
          threshold_ms: 1000
      # それ以外は 10% をサンプリング
      - name: probabilistic-policy
        type: probabilistic
        probabilistic:
          sampling_percentage: 10

推奨パターン: 二段階サンプリング

高トラフィック環境では、Head-basedとTail-basedを組み合わせた二段階サンプリングが効果的です。

二段階サンプリング構成:OTel SDKでHead-based抽出後、OTel CollectorでTail-based条件判定を経てDatadog Exporterへ送信
  1. SDK側でHead-based Samplingにより大幅にデータ量を削減(例: 50%)
  2. OTel Collectorのtail_sampling processorでエラーや異常レイテンシを確実に保持
  3. 正常系トレースはさらに間引いてDatadogへ送信

Kubernetes環境での本番構成

DaemonSet Agent + Sidecar Collector パターン

Kubernetes上では、Datadog AgentをDaemonSetで全ノードに配置し、必要に応じてOTel Collectorをサイドカーとして追加する構成が一般的です。

# Helm values (datadog/datadog チャート)
datadog:
  apiKey: <DATADOG_API_KEY>
  otlp:
    receiver:
      protocols:
        grpc:
          enabled: true
          endpoint: "0.0.0.0:4317"
        http:
          enabled: true
          endpoint: "0.0.0.0:4318"
  logs:
    enabled: true
    containerCollectAll: true
  apm:
    portEnabled: true

agents:
  containers:
    agent:
      env:
        - name: DD_OTLP_CONFIG_LOGS_ENABLED
          value: "true"

アプリケーションPodからは、ノード上のDatadog Agentの4317/4318ポートへOTLPデータを送信します。

# アプリケーション Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-service
spec:
  template:
    spec:
      containers:
        - name: app
          image: my-service:latest
          env:
            # DaemonSet Agent の IP を自動取得
            - name: DD_AGENT_HOST
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: OTEL_EXPORTER_OTLP_ENDPOINT
              value: "http://$(DD_AGENT_HOST):4317"
            - name: OTEL_SERVICE_NAME
              value: "my-service"
            - name: OTEL_RESOURCE_ATTRIBUTES
              value: "deployment.environment=production,service.version=1.0.0"

DDOT Collector を Helm で導入

Agent v7.65以降では、DDOT Collectorを有効にすることでOTel Collector設定YAMLをそのまま利用できます。

# Helm values (datadog/datadog チャート)
datadog:
  apiKey: <DATADOG_API_KEY>
  otelCollector:
    enabled: true
    # 既存の OTel Collector 設定をそのまま指定
    config: |
      receivers:
        otlp:
          protocols:
            grpc:
              endpoint: "0.0.0.0:4317"
      processors:
        infraattributes:
          cardinality: 2
        batch:
          timeout: 10s
      exporters:
        datadog:
          api:
            key: ${env:DD_API_KEY}
      service:
        pipelines:
          traces:
            receivers: [otlp]
            processors: [infraattributes, batch]
            exporters: [datadog]
          metrics:
            receivers: [otlp]
            processors: [infraattributes, batch]
            exporters: [datadog]

infraattributes processorはDDOT独自のコンポーネントで、KubernetesのPod名・Namespace・Deployment名などのタグをOTLPテレメトリに自動付与します。

既存Datadog計装からOTelへの段階的移行

大規模なシステムで一括移行はリスクが高いため、段階的なアプローチを推奨します。

ステップ1: 並行稼働の準備

既存のDatadog SDK計装はそのままに、新規サービスまたはチームからOTel SDKの導入を開始します。Datadog AgentのOTLPレシーバーを有効化するだけで、OTel計装とDatadog計装のデータが同じDatadogバックエンドに集約されます。

# 移行期間中の Datadog Agent 設定
# 既存の dd-trace と OTel OTLP の両方を受信
apm_config:
  enabled: true
otlp_config:
  receiver:
    protocols:
      grpc:
        endpoint: "0.0.0.0:4317"

ステップ2: サービス単位でのSDK切り替え

影響範囲の小さいサービスからOTel SDKへの切り替えを進めます。

移行チェックリスト:

  1. OTel SDKの依存関係を追加
  2. TracerProvider / MeterProvider / LoggerProviderを初期化
  3. Datadog SDK固有のAPIコール(dd-trace直接呼び出し等)をOTel API呼び出しに置換
  4. 環境変数OTEL_EXPORTER_OTLP_ENDPOINTを設定
  5. カナリアリリースで挙動を検証
  6. Datadogダッシュボードでメトリクス・トレースの欠損がないか確認
  7. 問題なければDatadog SDKの依存関係を削除

ステップ3: OTel Collectorの導入

全サービスのOTel化が進んだら、OTel Collectorを中間レイヤーとして導入します。サンプリング・フィルタリング・マルチバックエンド送信など、Collectorならではの機能を活用できるようになります。

OTel × Datadogの運用で押さえるべき注意点

互換性の落とし穴

リソース名のマッピング: OTelのスパン名(span.name)とDatadogのリソース名(resource)は1対1で対応しません。Datadog Exporterのspan_name_as_resource_name設定や、span_name_remappingsによる明示的なマッピングが必要になる場合があります。

128bit Trace ID: OTelは128bit Trace IDを標準としていますが、DatadogのUIやAPIは以前64bitのみ対応していました。現在は128bit対応が進んでいますが、古いDatadog SDK(dd-trace-go v1系の一部バージョンなど)と混在する環境ではIDの不一致に注意が必要です。

セマンティック規則の差異: OTelのSemantic Conventions(http.request.methodurl.path等)とDatadogのスパンタグ(http.methodhttp.url等)は名前が異なります。Datadog ExporterおよびDatadog Agentが自動変換を行いますが、カスタム属性は変換対象外です。

コスト面の考慮

OTelメトリクスをDatadogに送信する際、カスタムメトリクス課金が発生します。OTelのメトリクスはDatadogの標準インテグレーションメトリクスとは異なる扱いになるため、タグの組み合わせによって時系列数が膨大になり得ます。

コスト最適化の施策:

  • 不要なメトリクスはOTel Collectorのfilter processorで送信前に除外する
  • タグのカーディナリティ(一意な値の種類数)を制限する。特にuser_idrequest_idのような高カーディナリティタグは避ける
  • OTel Collectorのtransform processorで不要な属性を削除してからDatadogに送信する
  • DatadogのMetrics without Limits機能で、クエリに使わないタグの組み合わせを除外する
# 高カーディナリティ属性を除外する filter processor の例
processors:
  filter/drop-debug:
    metrics:
      exclude:
        match_type: regexp
        metric_names:
          - ".*debug.*"
  transform/remove-high-cardinality:
    metric_statements:
      - context: datapoint
        statements:
          - delete_key(attributes, "request_id")
          - delete_key(attributes, "user_id")

OTLP送信のトラブルシューティング

よくある問題と対処法をまとめます。

症状原因対処
トレースが表示されないOTLPエンドポイント到達不可grpcurlcurlでポート4317/4318の疎通確認
メトリクスが欠損するTemporalityのミスマッチDatadog Exporter/AgentのOTLP受信を使い自動変換させる
ホスト名が不正リソース属性host.nameの未設定resourcedetection processorを追加
スパン名がgenericHTTP計装ライブラリの未導入言語別のOTel HTTP instrumentation libraryを追加
ログとトレースが紐付かないdd.trace_id属性の欠落ログにdd.trace_id/dd.span_idを埋め込む

まとめ

OpenTelemetryとDatadogの統合は、「オープン標準による移植性」と「Datadogの強力な分析・運用機能」を両立させる現実的な選択肢です。

構成パターンとしては、OTel Collector + Datadog Exporter、Datadog Agent OTLP受信、DDOT Collector、Datadog SDK + OTel APIの4つがあり、ベンダー非依存性・Datadog機能活用度・運用負荷のバランスで選定します。2024年に登場したDDOT CollectorはOTel標準設定とDatadog機能を高いレベルで両立できるため、新規導入であれば有力な選択肢です。

運用上は、128bit Trace IDの互換性、セマンティック規則のマッピング、カスタムメトリクス課金の3点に特に注意が必要です。サンプリング戦略を適切に設計し、不要なメトリクスや高カーディナリティ属性を制御することで、可観測性と運用コストのバランスを保てます。

既存環境からの移行は、Datadog AgentのOTLPレシーバー有効化から始め、サービス単位で段階的にOTel SDKへ切り替えていくアプローチが安全です。