

# AWS Lambda での TypeScript コードのトレース
<a name="typescript-tracing"></a>

Lambda アプリケーションのトレース、デバッグ、最適化を行うために、Lambda は AWS X-Ray と統合されています。X-Ray を使用すると、Lambda 関数や他の AWS のサービスが含まれるアプリケーション内で、リソースを横断するリクエストをトレースできます。

トレーシングデータを X-Ray に送信するには、以下に表示された 3 つの SDK ライブラリのいずれかを使用できます。
+ [AWS Distro for OpenTelemetry (ADOT)](https://aws.amazon.com/otel) – 安全で本番環境に対応し、AWS でサポートされている OpenTelemetry (OTel) SDK のディストリビューション。
+ [AWS X-Ray SDK for Node.js](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs.html) – トレースデータを生成して X-Ray に送信するための SDK。
+ [Powertools for AWS Lambda (TypeScript)](https://docs.aws.amazon.com/powertools/typescript/latest/) – サーバーレスのベストプラクティスを実装し、開発者の作業速度を向上させるための開発者ツールキット。

各 SDK は、テレメトリデータを X-Ray サービスに送信する方法を提供します。続いて、X-Ray を使用してアプリケーションのパフォーマンスメトリクスの表示やフィルタリングを行い、インサイトを取得することで、問題点や最適化の機会を特定できます。

**重要**  
X-Ray および Powertools for AWS Lambda SDK は、AWS が提供する、密接に統合された計測ソリューションの一部です。ADOT Lambda レイヤーは、一般的により多くのデータを収集するトレーシング計測の業界標準の一部ですが、すべてのユースケースに適しているわけではありません。これらのソリューションのいずれかを使用して、X-Ray でエンドツーエンドのトレーシングを実装することができます。選択方法の詳細については、「[Choosing between the AWS Distro for Open Telemetry and X-Ray SDKs](https://docs.aws.amazon.com/xray/latest/devguide/xray-instrumenting-your-app.html#xray-instrumenting-choosing)」( Distro for Open Telemetry または X-Ray SDK の選択) を参照してください。

**Topics**
+ [トレース用の Powertools for AWS Lambda (TypeScript) と AWS SAM の使用](#typescript-tracing-sam)
+ [Powertools for AWS Lambda (TypeScript) およびトレース用の AWS CDK の使用](#typescript-tracing-cdk)
+ [X-Ray トレースの解釈](#typescript-tracing-interpretation)

## トレース用の Powertools for AWS Lambda (TypeScript) と AWS SAM の使用
<a name="typescript-tracing-sam"></a>

AWS SAM を使用した統合 [Powertools for AWS Lambda (TypeScript)](https://docs.powertools.aws.dev/lambda-typescript) モジュールを使用して、Hello World TypeScript サンプルアプリケーションをダウンロード、ビルド、およびデプロイする場合は、以下の手順に従ってください。このアプリケーションは基本的な API バックエンドを実装し、Powertools を使用してログ、メトリクス、トレースを生成します。Amazon API Gateway エンドポイントと Lambda 関数で構成されています。API Gateway エンドポイントに GET リクエストを送信すると、Lambda 関数は呼び出し、Embedded Metric Format を使用してログおよびメトリクスを CloudWatch に送信、トレースを AWS X-Ray に送信します。関数は `hello world` のメッセージを返します。

**前提条件**

このセクションの手順を完了するには、以下が必要です。
+ Node.js
+ [AWS CLI バージョン 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [AWS SAM「CLI バージョン 1.75 以降](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)」 AWS SAM CLI のバージョンが古い場合は、「[AWS SAM CLI のアップグレード](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/manage-sam-cli-versions.html#manage-sam-cli-versions-upgrade)」を参照してください。

**AWS SAM サンプルアプリケーションをデプロイする**

1. Hello World TypeScript テンプレートを使用して、アプリケーションを初期化します。

   ```
   sam init --app-template hello-world-powertools-typescript --name sam-app --package-type Zip --runtime nodejs24.x --no-tracing
   ```

1. アプリケーションを構築します。

   ```
   cd sam-app && sam build
   ```

1. アプリケーションをデプロイします。

   ```
   sam deploy --guided
   ```

1. 画面に表示されるプロンプトに従ってください。インタラクティブな形式で提供されるデフォルトオプションを受け入れるには、`Enter` を押します。
**注記**  
**[HelloWorldFunction には権限が定義されていない場合がありますが、問題ありませんか？]** には、必ず `y` を入力してください。

1. デプロイされたアプリケーションの URL を取得します。

   ```
   aws cloudformation describe-stacks --stack-name sam-app --query 'Stacks[0].Outputs[?OutputKey==`HelloWorldApi`].OutputValue' --output text
   ```

1. API エンドポイントを呼び出します。

   ```
   curl <URL_FROM_PREVIOUS_STEP>
   ```

   成功すると、次のレスポンスが表示されます。

   ```
   {"message":"hello world"}
   ```

1. 関数のトレースを取得するには、[sam traces](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-traces.html) を実行します。

   ```
   sam traces
   ```

   トレース出力は次のようになります。

   ```
   XRay Event [revision 1] at (2023-01-31T11:29:40.527000) with id (1-11a2222-111a222222cb33de3b95daf9) and duration (0.483s)
     - 0.425s - sam-app/Prod [HTTP: 200]
       - 0.422s - Lambda [HTTP: 200]
     - 0.406s - sam-app-HelloWorldFunction-Xyzv11a1bcde [HTTP: 200]
     - 0.172s - sam-app-HelloWorldFunction-Xyzv11a1bcde
       - 0.179s - Initialization
       - 0.112s - Invocation
         - 0.052s - ## app.lambdaHandler
           - 0.001s - ### MySubSegment
       - 0.059s - Overhead
   ```

1. これは、インターネット経由でアクセス可能なパブリック API エンドポイントです。テスト後にエンドポイントを削除することを推奨します。

   ```
   sam delete
   ```

X-Ray は、アプリケーションへのすべてのリクエストをトレースするわけではありません。X-Ray は、サンプリングアルゴリズムを適用することで効率的なトレースを行うと同時に、すべてのリクエストについての代表的なサンプルを示します。サンプルレートは 1 秒あたり 1 回のリクエストで、追加リクエストの 5％ です。関数の X-Ray サンプルレートを設定することはできません。

## Powertools for AWS Lambda (TypeScript) およびトレース用の AWS CDK の使用
<a name="typescript-tracing-cdk"></a>

AWS CDK を使用した統合 [Powertools for AWS Lambda (TypeScript)](https://docs.powertools.aws.dev/lambda-typescript) モジュールを使用して、Hello World TypeScript サンプルアプリケーションをダウンロード、ビルド、およびデプロイする場合は、以下の手順に従ってください。このアプリケーションは基本的な API バックエンドを実装し、Powertools を使用してログ、メトリクス、トレースを生成します。Amazon API Gateway エンドポイントと Lambda 関数で構成されています。API Gateway エンドポイントに GET リクエストを送信すると、Lambda 関数は呼び出し、Embedded Metric Format を使用してログおよびメトリクスを CloudWatch に送信、トレースを AWS X-Ray に送信します。関数は `hello world` のメッセージを返します。

**前提条件**

このセクションの手順を完了するには、以下が必要です。
+ Node.js
+ [AWS CLI バージョン 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [AWS CDK バージョン 2](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_prerequisites)
+ 「[AWS SAM CLI バージョン 1.75 以降](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)」 AWS SAM CLI のバージョンが古い場合は、「[AWS SAM CLI のアップグレード](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/manage-sam-cli-versions.html#manage-sam-cli-versions-upgrade)」を参照してください。

**AWS Cloud Development Kit (AWS CDK) サンプルアプリケーションをデプロイする**

1. 新しいアプリケーション用のプロジェクトディレクトリを作成します。

   ```
   mkdir hello-world
   cd hello-world
   ```

1. アプリケーションを初期化します。

   ```
   cdk init app --language typescript
   ```

1. 開発環境の依存関係として [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) パッケージを追加します。

   ```
   npm install -D @types/aws-lambda
   ```

1. Powertools [Tracer ユーティリティ](https://docs.aws.amazon.com/powertools/typescript/latest/features/tracer/)をインストールします。

   ```
   npm install @aws-lambda-powertools/tracer
   ```

1. **lib** ディレクトリを開きます。**hello-world-stack.ts** という名前のファイルが表示されます。このディレクトリに **hello-world.function.ts** と **hello-world.ts** の 2 つの新しいファイルを作成します。

1. **hello-world.function.ts** を開き、次のコードをファイルに追加します。これは Lambda 関数のコードです。

   ```
   import { APIGatewayEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
   import { Tracer } from '@aws-lambda-powertools/tracer';
   const tracer = new Tracer();
   
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
     // Get facade segment created by Lambda
     const segment = tracer.getSegment();
   
     // Create subsegment for the function and set it as active
     const handlerSegment = segment.addNewSubsegment(`## ${process.env._HANDLER}`);
     tracer.setSegment(handlerSegment);
   
     // Annotate the subsegment with the cold start and serviceName
     tracer.annotateColdStart();
     tracer.addServiceNameAnnotation();
   
     // Add annotation for the awsRequestId
     tracer.putAnnotation('awsRequestId', context.awsRequestId);
     // Create another subsegment and set it as active
     const subsegment = handlerSegment.addNewSubsegment('### MySubSegment');
     tracer.setSegment(subsegment);
     let response: APIGatewayProxyResult = {
       statusCode: 200,
       body: JSON.stringify({
         message: 'hello world',
       }),
     };
     // Close subsegments (the Lambda one is closed automatically)
     subsegment.close(); // (### MySubSegment)
     handlerSegment.close(); // (## index.handler)
   
     // Set the facade segment as active again (the one created by Lambda)
     tracer.setSegment(segment);
     return response;
   };
   ```

1. **hello-world.ts** を開き、次のコードをファイルに追加します。これには、Lambda 関数を作成し、Powertools の環境変数を設定し、ログ保持を 1 週間に設定する [NodejsFunction コンストラクト](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html)が含まれています。また、REST API を作成する [LambdaRestApi コンストラクト](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.LambdaRestApi.html)も含まれています。

   ```
   import { Construct } from 'constructs';
   import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
   import { LambdaRestApi } from 'aws-cdk-lib/aws-apigateway';
   import { CfnOutput } from 'aws-cdk-lib';
   import { Tracing } from 'aws-cdk-lib/aws-lambda';
   
   export class HelloWorld extends Construct {
     constructor(scope: Construct, id: string) {
       super(scope, id);
       const helloFunction = new NodejsFunction(this, 'function', {
         environment: {
           POWERTOOLS_SERVICE_NAME: 'helloWorld',
         },
         tracing: Tracing.ACTIVE,
       });
       const api = new LambdaRestApi(this, 'apigw', {
         handler: helloFunction,
       });
       new CfnOutput(this, 'apiUrl', {
         exportName: 'apiUrl',
         value: api.url,
       });
     }
   }
   ```

1. **hello-world-stack.ts** を開きます。これは、[AWS CDK スタック](https://docs.aws.amazon.com/cdk/v2/guide/stacks.html)を定義するコードです。このコードを、次のコードで置き換えます。

   ```
   import { Stack, StackProps } from 'aws-cdk-lib';
   import { Construct } from 'constructs';
   import { HelloWorld } from './hello-world';
     
   export class HelloWorldStack extends Stack {
     constructor(scope: Construct, id: string, props?: StackProps) {
       super(scope, id, props);
       new HelloWorld(this, 'hello-world');
     }
   }
   ```

1. アプリケーションをデプロイします。

   ```
   cd ..
   cdk deploy
   ```

1. デプロイされたアプリケーションの URL を取得します。

   ```
   aws cloudformation describe-stacks --stack-name HelloWorldStack --query 'Stacks[0].Outputs[?ExportName==`apiUrl`].OutputValue' --output text
   ```

1. API エンドポイントを呼び出します。

   ```
   curl <URL_FROM_PREVIOUS_STEP>
   ```

   成功すると、次のレスポンスが表示されます。

   ```
   {"message":"hello world"}
   ```

1. 関数のトレースを取得するには、[sam traces](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-traces.html) を実行します。

   ```
   sam traces
   ```

   トレース出力は次のようになります。

   ```
   XRay Event [revision 1] at (2023-01-31T11:50:06.997000) with id (1-11a2222-111a222222cb33de3b95daf9) and duration (0.449s)
     - 0.350s - HelloWorldStack-helloworldfunction111A2BCD-Xyzv11a1bcde [HTTP: 200]
     - 0.157s - HelloWorldStack-helloworldfunction111A2BCD-Xyzv11a1bcde
       - 0.169s - Initialization
       - 0.058s - Invocation
         - 0.055s - ## index.handler
           - 0.000s - ### MySubSegment
       - 0.099s - Overhead
   ```

1. これは、インターネット経由でアクセス可能なパブリック API エンドポイントです。テスト後にエンドポイントを削除することを推奨します。

   ```
   cdk destroy
   ```

## X-Ray トレースの解釈
<a name="typescript-tracing-interpretation"></a>

アクティブトレースの設定後は、アプリケーションを通じて特定のリクエストの観測が行えるようになります。[X-Ray トレースマップ](https://docs.aws.amazon.com/xray/latest/devguide/xray-console-servicemap.html)には、アプリケーションとそのすべてのコンポーネントに関する情報が表示されます。次の例はで、サンプルアプリケーションのトレースを示しています。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/sample-typescript-servicemap.png)
