Amazon SQS を介した AWS Lambda の呼び出しを Datadog で分散トレースする方法
はじめに
Hi 👋 この記事では SQS を介して Lambda を呼び出す非同期処理の一連の流れを Datadog で可視化する方法を紹介します。
Datadog の提供している Tracer や Lambda Extension Layer については前提知識として解説していきます。
やりかた
Python アプリから呼び出す場合は dd-trace-py
を使うことで自動計装で Python アプリ -> SQS -> Lambda
をトレースすることができます。これは dd-trace-py
が SQS を呼び出すクライアントライブラリである botocore
の自動計装をサポートしているためです。
では PHP アプリや Go アプリの場合はどうでしょう。実際 PHP で SQS を呼び出す aws/aws-sdk-php
は dd-trace-php
の自動計装対象ではないです。手動計装しトレースコンテキストを SQS や Lambda 側に渡す必要があります。どう渡せば良いでしょうか?
dd-trace-py
のコードを見てみます。この辺で SQS に送るメッセージの MessageAttributes
に、_datadog
キーとしてトレースコンテキストを埋めていることが分かります。
Datadog Lambda Extension Layer (Python)側の実装も見てみます。ここ でトレースコンテキストを抽出していることがわかります。
これを参考に、PHP でも SQS に送るメッセージにトレースコンテキストを乗せることで PHP アプリ -> SQS -> Lambda
の一連の分散トレースができそうです。やってみましょう。
文章だと分かりにくいですが、絵にするとこんな感じです。
やってみる
PHP スクリプトのメッセージにトレースコンテキストを付与する部分を抜粋します。ソース全体はこちらを参照してください。
# トレースコンテキストを付与した MessageAttributes の作成
$messageAttributes = [
'_datadog' => [
'DataType' => 'String',
'StringValue' => json_encode(\DDTrace\generate_distributed_tracing_headers()),
],
];
# SQS への送信
$sqsClient->sendMessage([
'QueueUrl' => $queueUrl,
'MessageBody' => $messageBody,
'MessageAttributes' => $messageAttributes,
]);
これで dd-trace-py
が内部でやっていることと同様のことを実現できます。PHP アプリから SQS を介して Lambda を実行してみます。
無事に以下のように非同期処理でも分散トレースすることが確認できました。
補足ですが、Lambda の関数処理側で自分で Extract 処理を書くことでトレースコンテキストの伝搬をすることも可能です。Runtime によってはこちらの方法で分散トレースをすることになると思うので補足です。以下のドキュメントが参考になります。
まとめ
自動計装に SQS の呼び出しがサポートされてない場合に、手動でトレースコンテキストを伝搬し アプリ -> SQS -> Lambda
を分散トレースする方法を紹介しました。今回は PHP で行いましたが、もちろん同様のことを Go のアプリで実現することも可能です。
非同期処理でも分散トレースすることで、処理が遅い原因特定の解像度を高めましょう。
Kafka を使った非同期処理も、こっちは OpenTelemetry ですが分散トレースする方法を書いてるので、気になる方は見てみてください!
Discussion