AWS Lambda関数の分散トレーシング

手動計装

4 min

ワークショップの第2部では、OpenTelemetryによる手動計装が計測データ収集を強化する方法を実演することに焦点を当てます。より具体的には、今回のケースでは、producer-lambda 関数から consumer-lambda 関数にトレースコンテキストデータを伝播させることができるようになります。これにより、現在は自動コンテキスト伝播をサポートしていないKinesisストリームを介しても、2つの関数間の関係を見ることができるようになります。

手動計装ワークショップディレクトリとコンテンツ

再度、作業ディレクトリとそのファイルの一部を確認することから始めます。今回は o11y-lambda-workshop/manual ディレクトリです。ここにはワークショップの手動計装部分のすべてのコンテンツがあります。

manual ディレクトリ

ワークショップの質問

このディレクトリと最初に始めたautoディレクトリに何か違いがありますか?

automanual のファイルを比較する

見た目が同じように見えるこれらのファイルが実際に同じかどうか確認しましょう。

プロデューサー関数からのトレースコンテキスト伝播

以下のコードはプロデューサー関数内で次のステップを実行します

  1. このトレース用のトレーサーを取得する
  2. コンテキストキャリアオブジェクトを初期化する
  3. アクティブスパンのコンテキストをキャリアオブジェクトに注入する
  4. Kinesisストリームに配置しようとしているレコードを修正し、アクティブスパンのコンテキストをコンシューマーに運ぶキャリアを含める
js
...
import { context, propagation, trace, } from "@opentelemetry/api";
...
const tracer = trace.getTracer('lambda-app');
...
  return tracer.startActiveSpan('put-record', async(span) => {
    let carrier = {};
    propagation.inject(context.active(), carrier);
    const eventBody = Buffer.from(event.body, 'base64').toString();
    const data = "{\"tracecontext\": " + JSON.stringify(carrier) + ", \"record\": " + eventBody + "}";
    console.log(
      `Record with Trace Context added:
      ${data}`
    );

    try {
      await kinesis.send(
        new PutRecordCommand({
          StreamName: streamName,
          PartitionKey: "1234",
          Data: data,
        }),
        message = `Message placed in the Event Stream: ${streamName}`
      )
...
    span.end();

コンシューマー関数でのトレースコンテキスト抽出

以下のコードはコンシューマー関数内で次のステップを実行します

  1. producer-lambda から取得したコンテキストをキャリアオブジェクトに抽出する
  2. 現在のコンテキストからトレーサーを抽出する
  3. 抽出したコンテキスト内でトレーサーを使用して新しいスパンを開始する
  4. ボーナス:メッセージからの値を含むカスタム属性など、追加の属性をスパンに追加する!
  5. 完了したら、スパンを終了する
js
import { propagation, trace, ROOT_CONTEXT } from "@opentelemetry/api";
...
      const carrier = JSON.parse( message ).tracecontext;
      const parentContext = propagation.extract(ROOT_CONTEXT, carrier);
      const tracer = trace.getTracer(process.env.OTEL_SERVICE_NAME);
      const span = tracer.startSpan("Kinesis.getRecord", undefined, parentContext);

      span.setAttribute("span.kind", "server");
      const body = JSON.parse( message ).record;
      if (body.name) {
        span.setAttribute("custom.tag.name", body.name);
      }
      if (body.superpower) {
        span.setAttribute("custom.tag.superpower", body.superpower);
      }
...
      span.end();

これでどのような違いが生まれるか見てみましょう!

Last Modified ·