トレースサーバーレス関数

Datadog では、サーバーレストレースをメトリクスに接続することで、アプリケーションのパフォーマンスに関する豊富な情報を提供します。これにより、サーバーレスアプリケーションの性質である分散型の環境でもパフォーマンスの問題を的確にトラブルシューティングできます。

Datadog Python、Node.js、Ruby、Go、Java、.NET SDK は、AWS Lambda の分散型トレーシングをサポートしています。

サーバーレスアプリケーションからトレースを送信する

Datadog を使用した AWS Lambda のトレースのアーキテクチャ図

Datadog Python、Node.js、Ruby、Go、Java、.NET SDK は、AWS Lambda の分散型トレーシングをサポートしています。SDK はインストール手順に従ってインストールできます。

ランタイムの推奨事項

Python
Node.js
Ruby
Java
go
.NET

Python と Node.js

Python および Node.js 用の Datadog Lambda ライブラリと SDK は、次の機能をサポートしています。

  • Lambda ログおよびトレースとトレース ID およびタグ挿入との自動相関。
  • Serverless Framework、AWS SAM、AWS CDK インテグレーションを使用したコード変更なしのインストール。
  • ダウンストリームの Lambda 関数またはコンテナを呼び出す HTTP リクエストのトレース。
  • AWS SDK で実行された Lambda の連続呼び出しのトレース。
  • コールドスタートのトレース
  • AWS Managed Services を介した非同期 Lambda 呼び出しのトレース
    • API Gateway
    • SQS
    • SNS
    • SNS と SQS の直接インテグレーション
    • Kinesis
    • EventBridge
    • DynamoDB
    • S3
    • Step Functions
  • すぐに使用できる数十の追加の Python および Node.js ライブラリのトレース。

Datadog では、Python および Node.js のサーバーレスアプリケーション用に Datadog SDK をインストールすることを推奨します。

上記にリストされていないサーバーレスリソースのトレースをご希望の場合は、機能リクエストを開いてください

Ruby

Ruby 用の Datadog Lambda ライブラリと SDK は、次の機能をサポートしています。

  • Lambda ログおよびトレースとトレース ID およびタグ挿入との自動相関。
  • ダウンストリームの Lambda 関数またはコンテナを呼び出す HTTP リクエストのトレース。
  • すぐに使用できる数十の追加の Ruby ライブラリのトレース。

Datadog では Datadog SDK を使用してサーバーレス関数をトレースできます。

上記にリストされていないサーバーレスリソースのトレースをご希望の場合は、機能リクエストを開いてください

Go

Go 用の Datadog Lambda ライブラリと SDK は、次の機能をサポートしています。

  • Lambda ログおよびトレースとトレース ID およびタグ挿入との手動相関。
  • ダウンストリームの Lambda 関数またはコンテナを呼び出す HTTP リクエストのトレース。
  • すぐに使用できる数十の追加の Go ライブラリのトレース。

Datadog では、Go のサーバーレスアプリケーション用に Datadog SDK をインストールすることを推奨します。

上記にリストされていないサーバーレスリソースのトレースをご希望の場合は、機能リクエストを開いてください

Java

Java 用の Datadog Lambda ライブラリと SDK は、次の機能をサポートしています。

  • Lambda ログおよびトレースとトレース ID およびタグ挿入との相関。詳細については、Java ログとトレースの接続を参照してください。
  • ダウンストリームの Lambda 関数またはコンテナを呼び出す HTTP リクエストのトレース。
  • すぐに使用できる数十の追加の Java ライブラリのトレース。

Datadog では、Java のサーバーレスアプリケーション用に Datadog SDK をインストールすることを推奨します。

Java Lambda 関数用の Datadog SDK に関してフィードバックがございましたら、Datadog Slack コミュニティ#serverless チャネルで行われているディスカッションをご確認ください。

.NET

.NET 用の SDK は、次の機能をサポートしています。

  • ダウンストリームの Lambda 関数またはコンテナを呼び出す HTTP リクエストのトレース。
  • すぐに使用できる数十の追加の .NET ライブラリのトレース。

Datadog では、.NET のサーバーレスアプリケーション用に Datadog SDK をインストールすることを推奨します。

.NET Azure サーバーレスアプリケーションを介したトレースの詳細をご覧ください。

スパンの自動リンク

Datadog での DynamoDB のトレース。上部に「This trace is linked to other traces」というメッセージが表示されています。Span Links タブが開いており、別の DynamoDB トレースへのクリック可能なリンクが表示されています。

Datadog は、非同期リクエストのセグメントがトレースコンテキストを伝播できない場合に、リンクされたスパンを自動的に検出します。たとえば、リクエストによって S3 変更イベントDynamoDB ストリーム がトリガーされる場合などです。自動リンクされたスパンは Span Links タブに表示されます。Backward または Forward のいずれかとして示されます。

Backward: 表示されているトレースによって発生したリンクスパン。

Forward: 表示されているトレースを発生させたリンクスパン。

サンプリングやトレース保持フィルターが自動リンクに干渉することがあります。自動リンクされたスパンが表示される可能性を高めるには、サンプルレートを上げるか、保持フィルターを調整してください。

対応テクノロジー

スパンの自動リンクは、次の対象に利用可能です。

  • Python AWS Lambda 関数で、datadog-lambda-python レイヤー v101 以上を使用してインスツルメントされたもの
  • Python アプリケーションで、dd-trace-py v2.16 以上を使用してインスツルメントされたもの
  • Node.js AWS Lambda 関数で、datadog-lambda-js レイヤー 118 以上を使用してインスツルメントされたもの
  • Node.js アプリケーションで、dd-trace-js v4.53.0 以上または v5.29.0 以上を使用してインスツルメントされたもの

DynamoDB 変更ストリームの自動リンク

DynamoDB Change Stream について、スパンの自動リンクは次の操作をサポートしています。

  • PutItem
  • UpdateItem
  • DeleteItem
  • BatchWriteItem
  • TransactWriteItems

S3 Change Notification の自動リンク

S3 Change Notificationについて、スパンの自動リンクは次の操作をサポートしています。

  • PutObject
  • CompleteMultipartUpload
  • CopyObject

ハイブリッド環境

Lambda 関数、ホスト、コンテナ、およびマネージドサービス全体でエンドツーエンドの可視性を得るには、Datadog SDK (dd-trace) を Lambda 関数とホストの両方にインストールします。これにより、インフラストラクチャーの境界を越えてリクエストの全体像がトレースに表示されます。

Lambda で、Datadog Lambda Extension を使用して dd-trace をインストールします。これにより、Lambda 実行環境内で Datadog Agent が実行され、最小限のオーバーヘッドでトレースが Datadog に直接送信されます。Lambda Extension は、新規と既存のどちらのサーバーレスアプリケーションにも推奨されるインストール方法です。

コンテナおよびホストベースの環境でのトレースのセットアップについては、Datadog APM のドキュメントを参照してください。

Lambda 関数のプロファイリング

Datadog の Continuous Profiler は、Python 向けにプレビュー版として提供されています。バージョン 4.62.0 およびレイヤーバージョン 62 以上で利用可能です。このオプション機能は、DD_PROFILING_ENABLED 環境変数を true に設定することで有効になります。

Continuous Profiler は、定期的にスレッドを起こして、実行中のすべての Python コードの CPU と ヒープのスナップショットを取得することで機能します。これにはプロファイラー自身も含まれる場合があります。プロファイラーが自分自身を無視するようにしたい場合は、DD_PROFILING_IGNORE_PROFILERtrue に設定します。

トレースマージ

ユースケース

Datadog は Datadog APM トレースライブラリ (dd-trace) のみの使用を推奨していますが、高度な状況ではトレースマージを使って Datadog トレースと AWS X-Ray を組み合わせて使用することもできます。トレースマージは、Node.js と Python の AWS Lambda 関数で利用可能です。どの SDK を使用するかわからない場合は、SDK の選択をお読みください。

AWS Step Functions のトレースは、Datadog によってネイティブにサポートされており、X-Ray を必要としません。AWS Step Functions のサーバーレスモニタリングおよび Step Functions と Lambda トレースのマージを参照してください。

dd-trace と AWS X-Ray トレーシングライブラリの両方をインスツルメントするのは、主に 2 つの理由からです。

  • AWS サーバーレス環境では、dd-trace ですでに Lambda 関数をトレースしているため、Datadog APM がまだインスツルメントしていない AWS マネージドサービス (AppSync など) の AWS X-Ray アクティブトレースを要求して、dd-trace および AWS X-Ray スパンを単一トレースで視覚化します。
  • Lambda 関数とホストの両方を使用するハイブリッド環境では、dd-trace がホストをインスツルメントし、AWS X-Ray が Lambda 関数をインスツルメントするため、Lambda 関数およびホスト全体のトランザクションの接続済みトレースを視覚化します。

注: この場合、使用料が高額になる可能性があります。X-Ray スパンは、トレースのマージ後 2~5 分間は引き続き使用可能です。Datadog では、通常は、単一の SDK の使用をおすすめしています。SDK の選択方法についてご覧ください。

上記のユースケースをセットアップする手順は以下のとおりです。

AWS サーバーレス環境におけるトレースのマージ

AWS X-Ray は、バックエンド AWS サービス (AWS X-Ray アクティブトレース) とクライアントライブラリ一式の両方を提供します。Lambda コンソールでバックエンド AWS サービスのみを有効にすると、AWS Lambda 関数に InitializationInvocation スパンが与えられます。API Gateway および Step Functions コンソールからも AWS X-Ray アクティブトレースを有効にできます。

AWS X-Ray SDK および Datadog APM クライアントライブラリ (dd-trace) は、いずれも関数に直接アクセスしてダウンストリームのコールのメタデータとスパンを追加します。dd-trace を使用してハンドラーレベルでトレースする場合は、次のようなセットアップになります。

  1. AWS Lambda コンソールおよび Datadog 内の AWS X-Ray インテグレーションで、Lambda 関数の AWS X-Ray アクティブトレースを有効にしてあります。
  2. 使用している Lambda ランタイム用のインストール手順に従い、Datadog APM (dd-trace) を使用して Lambda 関数をインスツルメントしてあります。
  3. dd-trace により、サードパーティライブラリにパッチが自動的に適用されているため、AWS X-Ray クライアントライブラリをインストールする必要はありません。
  4. Lambda 関数で DD_MERGE_XRAY_TRACES 環境変数を true に設定し、X-Ray と dd-trace トレースをマージします (Ruby では DD_MERGE_DATADOG_XRAY_TRACES)。

AWS Lambda とホスト全体のトレース

Datadog SDK (dd-trace) を Lambda 関数とホストの両方にインストールします。これにより、AWS Lambda、コンテナ、オンプレミスホスト、マネージドサービスなど、インフラストラクチャーの境界を越えてリクエストの全体像がトレースに自動的に表示されます。

ホストから Lambda 関数へのリクエストのトレース

トレース伝搬

サーバーレス分散型の HTTP 以外のトレース

必須セットアップ

Lambda 関数を非同期でトリガーする Node や Python のサーバーレスアプリケーションで、1 つのつながったトレースを見るには、追加のインスツルメンテーションが必要になることがあります。Datadog でサーバーレスアプリケーションの監視を始めたばかりであれば、こちらの主なインストール手順に従いSDK の選択に関するこのページをお読みくださいDatadog Lambda Libraryを使って Lambda 関数から Datadog にトレースを送るようになったら、以下のようなケースではこれらの手順で 2 つの Lambda 関数間のトレースをつなぐとよいかもしれません。

  • Step Functions で Lambda 関数をトリガーする
  • MQTT など HTTP 以外のプロトコルで Lambda 関数を呼び出す

多くの AWS Managed サービス (こちらを参照) のトレースは、最初からサポートされており、このページで説明されている手順を実行する必要はありません。

トレースを送信するリソース間でトレースコンテキストを正常に接続するために、次のことが必要です。

  • Datadog のトレースコンテキストを発信イベントに含める。発信イベントは、dd-trace をインストールしたホストや Lambda 関数から発生させることができます。
  • コンシューマー Lambda 関数内のトレースコンテキストを抽出する。

トレースコンテキストの受け渡し

以下のサンプルコードでは、HTTP ヘッダーをサポートしないサービスや、Datadog が Node や Python でネイティブに対応していないマネージドサービスに対して、発信ペイロードでトレースコンテキストを渡す方法について説明しています。

Python では、get_dd_trace_context ヘルパー関数を使用して、Lambda 関数内の発信イベントにトレースコンテキストを渡すことができます。

import json
import boto3
import os

from datadog_lambda.tracing import get_dd_trace_context  # Datadog tracing helper function

def handler(event, context):
    my_custom_client.sendRequest(
        {
          'myCustom': 'data',
          '_datadog': {
              'DataType': 'String',
              'StringValue': json.dumps(get_dd_trace_context()) # Includes trace context in outgoing payload.
          },
        },
    )

Node では、getTraceHeaders ヘルパー関数を使用して、Lambda 関数内の発信イベントにトレースコンテキストを渡すことができます。

const { getTraceHeaders } = require("datadog-lambda-js"); // Datadog tracing helper function

module.exports.handler = async event => {
  const _datadog = getTraceHeaders(); // Captures current Datadog trace context.

  var payload = JSON.stringify({ data: 'sns', _datadog });
  await myCustomClient.sendRequest(payload)

ホストから

Lambda 関数からトレースコンテキストを渡していない場合、getTraceHeadersget_dd_trace_context ヘルパー関数の代わりに次のコードテンプレートを使用すると、現在のスパンコンテキストを取得することができます。すべてのランタイムでこれを行う方法については、ここで説明しています。

const tracer = require("dd-trace");

exports.handler = async event => {
  const span = tracer.scope().active();
  const _datadog = {}
  tracer.inject(span, 'text_map', _datadog)

  // ...

トレースコンテキストの抽出

上記のトレースコンテキストをコンシューマー Lambda 関数から抽出するには、Lambda 関数ハンドラーの実行前にトレースコンテキストをキャプチャするエクストラクター関数を定義する必要があります。これを行うには、エクストラクター関数の場所を指すように DD_TRACE_EXTRACTOR 環境変数を構成してください。フォーマットは <FILE NAME>.<FUNCTION NAME> です。たとえば、json エクストラクターが extractors.js ファイルにある場合は、extractors.json となります。Datadog は、エクストラクターを複数の Lambda 関数で再利用できるように、エクストラクターメソッドを 1 つのファイルにまとめて配置することを推奨しています。これらのエクストラクターは、どんなユースケースにも合うように完全にカスタマイズ可能です。

:

  • TypeScript や webpack のようなバンドラーを使用している場合、エクストラクターが定義されている Node.js モジュールを import または require する必要があります。これにより、モジュールがコンパイルされ、Lambda のデプロイメントパッケージにバンドルされるようになります。
  • Node.js の Lambda 関数が arm64 上で動作する場合、環境変数 DD_TRACE_EXTRACTOR を使用する代わりに、関数コード内でエクストラクターを定義する必要があります。

サンプルエクストラクター

以下のコードサンプルでは、サードパーティシステムや標準的な HTTP ヘッダーをサポートしない API にトレースコンテキストを伝達するために使用するエクストラクターのサンプルについて説明します。

def extractor(payload):
    trace_headers = json.loads(payload["_datadog"]);
    trace_id = trace_headers["x-datadog-trace-id"];
    parent_id = trace_headers["x-datadog-parent-id"];
    sampling_priority = trace_headers["x-datadog-sampling-priority"];
    return trace_id, parent_id, sampling_priority
exports.json = (payload) => {
    const traceData = payload._datadog
    const traceID = traceData["x-datadog-trace-id"];
    const parentID = traceData["x-datadog-parent-id"];
    const sampledHeader = traceData["x-datadog-sampling-priority"];
    const sampleMode = parseInt(sampledHeader, 10);

    return {
      parentID,
      sampleMode,
      source: 'event',
      traceID,
    };
};
var exampleSQSExtractor = func(ctx context.Context, ev json.RawMessage) map[string]string {
	eh := events.SQSEvent{}

	headers := map[string]string{}

	if err := json.Unmarshal(ev, &eh); err != nil {
		return headers
	}

	// Using SQS as a trigger with a batchSize=1 so it's important we check
  // for this as a single SQS message will drive the execution of the handler.
	if len(eh.Records) != 1 {
		return headers
	}

	record := eh.Records[0]

	lowercaseHeaders := map[string]string{}
	for k, v := range record.MessageAttributes {
		if v.StringValue != nil {
			lowercaseHeaders[strings.ToLower(k)] = *v.StringValue
		}
	}

	return lowercaseHeaders
}

cfg := &ddlambda.Config{
    TraceContextExtractor: exampleSQSExtractor,
}
ddlambda.WrapFunction(handler, cfg)

X-Ray インテグレーションで Datadog にトレースを送信する

すでに X-Ray インスツルメンテーションがあり、引き続き利用する場合は、AWS X-Ray インテグレーションをインストールして、X-Ray から Datadog にトレースを送信できます。新しいサーバーレスアプリケーションの場合は、代わりに Datadog Lambda Extension を使用して Lambda 関数をインスツルメントすることをおすすめします。

参考資料