AWS Lambda サーバーレスアプリケーションによる分散型トレーシング
Datadog では、サーバーレストレースをメトリクスに接続することで、アプリケーションのパフォーマンスに関する豊富な情報を提供します。これにより、サーバーレスアプリケーションの性質である分散型の環境でもパフォーマンスの問題を的確にトラブルシューティングできます。
Datadog Python、Node.js、Ruby、Go、Java、.NET トレーシングライブラリは、AWS Lambda の分散型トレーシングをサポートしています。
サーバーレス アプリケーションからトレースを送信する
Datadog Python、Node.js、Ruby、Go、Java、.NET のトレーシングライブラリは、AWS Lambda の分散型トレーシングをサポートしています。トレーサーはインストール手順を使ってインストールできます。すでに拡張機能をインストールしている場合は、環境変数 DD_TRACE_ENABLED が true に設定されていることを確認してください。
ランタイムの推奨事項
Python と Node.js
Python および Node.js をサポートする Datadog Lambda ライブラリとトレースライブラリ:
- 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
- すぐに使用できる数十の追加の Python および Node.js ライブラリをトレース。
Python と Node.js のサーバーレス アプリケーションでは、Datadog は Datadog のトレーシング ライブラリをインストール することを推奨します。
上記にリストされていないサーバーレスリソースのトレースをご希望の場合は、機能リクエストを開いてください。
Ruby
Ruby サポート用の Datadog Lambda ライブラリとトレースライブラリ:
- Lambda ログおよびトレースとトレース ID およびタグ挿入との自動相関。
- ダウンストリームの Lambda 関数またはコンテナを呼び出す HTTP リクエストをトレース。
- すぐに使用できる数十の追加の Ruby ライブラリをトレース。
Datadog の トレーシング ライブラリ を使用すると、サーバーレス関数をトレースできます。
上記にリストされていないサーバーレスリソースのトレースをご希望の場合は、機能リクエストを開いてください。
Go
Go サポート用の Datadog Lambda ライブラリとトレースライブラリ:
- Lambda ログおよびトレースとトレース ID およびタグ挿入との手動相関。
- ダウンストリームの Lambda 関数またはコンテナを呼び出す HTTP リクエストをトレース。
- すぐに使用できる数十の追加 Go ライブラリをトレース。
Go のサーバーレス アプリケーションでは、Datadog は Datadog のトレーシング ライブラリのインストール を推奨します。
上記にリストされていないサーバーレスリソースのトレースをご希望の場合は、機能リクエストを開いてください。
Java
Java サポート用の Datadog Lambda ライブラリとトレースライブラリ:
- Lambda ログおよびトレースとトレース ID およびタグ挿入との相関。詳細は、Java ログとトレースの接続を参照してください。
- ダウンストリームの Lambda 関数またはコンテナを呼び出す HTTP リクエストをトレース。
- すぐに使用できる数十の追加 Java ライブラリをトレース。
Java のサーバーレス アプリケーションでは、Datadog は Datadog のトレーシング ライブラリのインストール を推奨します。
Java Lambda 関数用の Datadog のトレースライブラリに関してフィードバックがございましたら、Datadog Slack コミュニティの #serverless チャネルで行われているディスカッションをご確認ください。
.NET
.NET 用のトレースライブラリは以下に対応しています。
- ダウンストリームの Lambda 関数またはコンテナを呼び出す HTTP リクエストをトレース。
- すぐに使用できる数十の追加 .NET ライブラリをトレース。
.NET のサーバーレス アプリケーションでは、Datadog は Datadog のトレーシング ライブラリのインストール を推奨します。
.NET Azure サーバーレスアプリケーションを介したトレースの詳細をご覧ください。
スパンの自動リンク
非同期リクエストの一部がトレース コンテキストを伝播できない場合、Datadog はリンクされたスパンを自動的に検出します。例えば、リクエストが S3 変更イベント や DynamoDB Streams をトリガーしたときに発生することがあります。自動リンクされたスパンは Span Links タブ に表示され、Backward または Forward のいずれかとして示されます。
Backward: 表示中のトレースによって発生したリンク スパンです。
Forward: リンク スパンが表示中のトレースを引き起こしました。
サンプリングや
トレースの保持フィルター が自動リンクに影響することがあります。自動リンクされたスパンを確認できる可能性を高めるには、サンプル レートを上げるか、保持フィルターを調整してください。
対応テクノロジー
スパンの自動リンクが利用可能な対象:
DynamoDB Change Streams の自動リンク
DynamoDB Change Streams に対して、スパンの自動リンクがサポートする操作は次のとおり:
PutItemUpdateItemDeleteItemBatchWriteItemTransactWriteItems
S3 Change Notifications の自動リンク
S3 Change Notifications に対して、スパンの自動リンクがサポートする操作は次のとおり:
PutObjectCompleteMultipartUploadCopyObject
ハイブリッド環境
Datadog のトレーシングライブラリ (dd-trace) を Lambda 関数とホストの両方にインストールした場合は、AWS Lambda、コンテナ、オンプレミスホスト、マネージドサービスなど、インフラストラクチャーの境界を越えてリクエストの全体像がトレースに自動的に表示されます。
Datadog Agent でホストに dd-trace がインストールされていて、サーバーレス関数が AWS X-Ray でトレースされる場合、インフラストラクチャー全体で接続された単一のトレースを表示するには、トレースのマージが必要です。dd-trace と AWS X-Ray からのトレースのマージの詳細については、サーバーレストレースのマージのドキュメントをご覧ください。
Datadog の AWS X-Ray インテグレーションは、Lambda 関数のトレースのみを提供します。コンテナまたはホストベースの環境でのトレースの詳細については、Datadog APM のドキュメントをご覧ください。
Lambda 関数のプロファイリング
Datadog の Continuous Profiler は、Python 向けにプレビューとして提供されています。バージョン 4.62.0 および レイヤー バージョン 62 以上で利用可能です。このオプション機能は、環境変数 DD_PROFILING_ENABLED を true に設定すると有効になります。
Continuous Profiler は、定期的にスレッドを起こして、実行中のすべての Python コードの CPU と ヒープのスナップショットを取得することで機能します。これには、プロファイラ自身が含まれる場合があります。プロファイラ自身を無視させたい場合は、DD_PROFILING_IGNORE_PROFILER を true に設定してください。
トレースマージ
ユースケース
Datadog は Datadog APM トレースライブラリ (dd-trace) のみの使用を推奨していますが、高度な状況ではトレースマージを使って Datadog トレースと AWS X-Ray を組み合わせて使用することもできます。トレースマージは、Node.js と Python の AWS Lambda 関数で利用可能です。どのトレーシングライブラリを使用するかわからない場合は、トレーシングライブラリの選択をお読みください。
dd-trace と AWS X-Ray トレーシングライブラリの両方をインスツルメントするのは、主に 2 つの理由からです。
- AWS サーバーレス環境では、
dd-trace ですでに Lambda 関数をトレースしているため、AppSync や Step Functions など、AWS マネージドサービスの AWS X-Ray アクティブトレースを要求して dd-trace および AWS X-Ray スパンを単一トレースで視覚化します。 - Lambda 関数とホストの両方を使用するハイブリッド環境では、
dd-trace がホストをインスツルメントし、AWS X-Ray が Lambda 関数をインスツルメントするため、Lambda 関数およびホスト全体のトランザクションの接続済みトレースを視覚化します。
注: この場合、使用料が高額になる可能性があります。X-Ray スパンは、トレースのマージ後 2~5 分間は引き続き使用可能です。Datadog では、通常は、単一のトレーシングライブラリの使用をおすすめしています。トレーシングライブラリの選択方法についてご覧ください。
上記のユースケースをセットアップする手順は以下のとおりです。
AWS サーバーレス環境におけるトレースのマージ
AWS X-Ray は、バックエンド AWS サービス (AWS X-Ray アクティブトレース) とクライアントライブラリ一式の両方を提供します。Lambda コンソールでバックエンド AWS サービスのみを有効にすると、AWS Lambda 関数に Initialization と Invocation スパンが与えられます。API Gateway および Step Function コンソールから、AWS X-Ray アクティブトレースを有効にすることも可能です。
AWS X-Ray SDK および Datadog APM クライアントライブラリ (dd-trace) は、いずれも関数に直接アクセスしてダウンストリームのコールのメタデータとスパンを追加します。dd-trace を使用してハンドラーレベルでトレースする場合は、以下のようなセットアップになります。
- AWS Lambda コンソールおよび Datadog 内の AWS X-Ray インテグレーションで、Lambda 関数の AWS X-Ray アクティブトレースを有効にしてあります。
- 使用している Lambda ランタイム用のインストール手順に従い、Datadog APM (
dd-trace) を使用して Lambda 関数をインスツルメントしてあります。 dd-trace により、サードパーティライブラリにパッチが自動的に適用されているため、AWS X-Ray クライアントライブラリをインストールする必要はありません。- Lambda 関数で
DD_MERGE_XRAY_TRACES 環境を true に設定し、X-Ray と dd-trace トレースをマージします (Ruby では DD_MERGE_DATADOG_XRAY_TRACES)。
AWS Lambda とホスト全体のトレース
Datadog のトレーシング ライブラリによるコンテキストの伝播
Datadog のトレーシングライブラリ (dd-trace) を Lambda 関数とホストの両方にインストールした場合は、AWS Lambda、コンテナ、オンプレミスホスト、マネージドサービスなど、インフラストラクチャーの境界を越えてリクエストの全体像がトレースに自動的に表示されます。
X-Ray インテグレーションによるコンテキストの伝播
Datadog Agent でホストに dd-trace がインストールされていて、Node.js または Python サーバーレス関数が AWS X-Ray でトレースされる場合、セットアップは以下のようになります。
- Lambda 関数のトレース用に AWS X-Ray インテグレーションがインストールされていて、AWS X-Ray アクティブトレースと X-Ray クライアントライブラリのインストールが可能です。
- Lambda ランタイム用の Datadog Lambda Library をインストールしており、環境変数
DD_TRACE_ENABLED が true に設定されています。 - ホストおよびコンテナベースのインフラストラクチャーで Datadog APM が構成されています。
そして、X-Ray と Datadog APM トレースを同じフレームグラフに表示するには、すべてのサービスに同じ env タグが必要です。
注: 分散型トレーシングはホストまたはコンテナベースアプリケーションにおけるすべてのランタイムでサポートされています。ホストおよび Lambda 関数が同じランタイムにある必要はありません。
トレース伝搬
必須セットアップ
Lambda 関数を非同期でトリガーする Node や Python のサーバーレスアプリケーションで、1 つのつながったトレースを見るには、追加のインスツルメンテーションが必要になることがあります。Datadog でサーバーレスアプリケーションの監視を始めたばかりであれば、こちらの主なインストール手順に従い、トレースライブラリの選択に関するこのページをお読みください。Datadog Lambda ライブラリを使って 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 トレースヘルパー関数
def handler(event, context):
my_custom_client.sendRequest(
{
'myCustom': 'data',
'_datadog': {
'DataType': 'String',
'StringValue': json.dumps(get_dd_trace_context()) # 発信ペイロードにトレースコンテキストを含めます。
},
},
)
Node では、getTraceHeaders ヘルパー関数を使用して、Lambda 関数内の発信イベントにトレースコンテキストを渡すことができます。
const { getTraceHeaders } = require("datadog-lambda-js"); // Datadog トレースヘルパー関数
module.exports.handler = async event => {
const _datadog = getTraceHeaders(); // 現在の Datadog のトレースコンテキストをキャプチャします。
var payload = JSON.stringify({ data: 'sns', _datadog });
await myCustomClient.sendRequest(payload)
ホストから
Lambda 関数からトレースコンテキストを渡していない場合、getTraceHeaders と get_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
}
// SQS を batchSize=1 のトリガーとして使用すると、1 つの SQS メッセージが
// ハンドラーの実行を駆動するため、これをチェックすることが重要です。
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 でサーバーレス アプリケーションをトレースしており、今後も X-Ray を使用したい場合は、AWS X-Ray インテグレーションをインストール して、X-Ray から Datadog にトレースを送信できます。
その他の参考資料