

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 TypeScript 建置 Lambda 函數
<a name="lambda-typescript"></a>

您可以使用 Node.js 執行期在 AWS Lambda中執行 TypeScript。由於 Node.js 不會在本機執行 TypeScript 程式碼，因此必須先將 TypeScript 程式碼轉譯為 JavaScript。然後，使用 JavaScript 檔案，將函數程式碼部署至 Lambda。您的程式碼會在包含適用於 JavaScript 的 AWS 開發套件的環境中執行，其中包含您管理之 AWS Identity and Access Management (IAM) 角色的登入資料。若要進一步了解 Node.js 執行時期隨附的 SDK 版本，請參閱 [包含執行時期的 SDK 版本](lambda-nodejs.md#nodejs-sdk-included)。

Lambda 支援以下 Node.js 執行期。


| 名稱 | 識別符 | 作業系統 | 取代日期 | 封鎖函數建立 | 封鎖函數更新 | 
| --- | --- | --- | --- | --- | --- | 
|  Node.js 24  |  `nodejs24.x`  |  Amazon Linux 2023  |   2028 年 4 月 30 日   |   2028 年 6 月 1 日   |   2028 年 7 月 1 日   | 
|  Node.js 22  |  `nodejs22.x`  |  Amazon Linux 2023  |   2027 年 4 月 30 日   |   2027 年 6 月 1 日   |   2027 年 7 月 1 日   | 
|  Node.js 20  |  `nodejs20.x`  |  Amazon Linux 2023  |   2026 年 4 月 30 日   |   2026 年 8 月 31 日   |   2026 年 9 月 30 日   | 

**Topics**
+ [設定 TypeScript 開發環境](#typescript-dev)
+ [Lambda 的類型定義](#typescript-type-definitions)
+ [定義 TypeScript 格式的 Lambda 函數處理常式](typescript-handler.md)
+ [使用 .zip 檔案封存，在 Lambda 中部署轉換的 TypeScript 程式碼](typescript-package.md)
+ [使用容器映像在 Lambda 中部署轉譯的 TypeScript 程式碼](typescript-image.md)
+ [使用 Lambda 內容物件擷取 TypeScript 函數資訊](typescript-context.md)
+ [記錄和監控 TypeScript Lambda 函數](typescript-logging.md)
+ [在 中追蹤 TypeScript 程式碼 AWS Lambda](typescript-tracing.md)

## 設定 TypeScript 開發環境
<a name="typescript-dev"></a>

使用本機整合式開發環境 (IDE) 或文字編輯器來編寫 TypeScript 函式程式碼。無法在 Lambda 主控台上建立 TypeScript 程式碼。

您可以使用 [esbuild](https://esbuild.github.io/) 或 Microsoft 的 TypeScript 編譯器 (`tsc`)，將 TypeScript 程式碼轉譯為 JavaScript。[AWS Serverless Application Model (AWS SAM)](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html) 與 [AWS Cloud Development Kit (AWS CDK)](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) 均採用 esbuild。

使用 esbuild 時，請考慮下列事項︰
+ 存在若干 [TypeScript caveats](https://esbuild.github.io/content-types/#typescript-caveats)。
+ 您必須設定 TypeScript 轉譯設定，以便與計劃使用的 Node.js 執行時期相符。如需詳細資訊，請參閱 esbuild 文件中的[目標](https://esbuild.github.io/api/#target)。如需 **tsconfig.json** 檔案的範例，該檔案示範了如何以 Lambda 支援的特定 Node.js 版本為目標，請參閱 [TypeScript GitHub 儲存庫](https://github.com/tsconfig/bases/blob/main/bases/node14.json)。
+ esbuild 不執行類型檢查。若要檢查類型，請使用 `tsc` 編譯器。執行 `tsc -noEmit` 或將 `"noEmit"` 參數新增至 **tsconfig.json** 檔案，如下列範例所示。這會將 `tsc` 設定為不發出 JavaScript 檔案。檢查類型後，使用 esbuild 將 TypeScript 檔案轉換為 JavaScript。

**Example tsconfig.json**  

```
 {
  "compilerOptions": {
    "target": "es2020",
    "strict": true,
    "preserveConstEnums": true,
    "noEmit": true,
    "sourceMap": false,
    "module":"commonjs",
    "moduleResolution":"node",
    "esModuleInterop": true, 
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true, 
    "isolatedModules": true, 
  },
  "exclude": ["node_modules", "**/*.test.ts"]
}
```

## Lambda 的類型定義
<a name="typescript-type-definitions"></a>

[@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 套件提供 Lambda 函式的類型定義。若您的函式使用下列任意一項，請安裝此套件：
+ 常見 AWS 事件來源，例如：
  + `APIGatewayProxyEvent`：適用於 [Amazon API Gateway 代理整合](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html) 
  + `SNSEvent`：適用於 [Amazon Simple Notification Service 通知](with-sns.md)
  + `SQSEvent`：適用於 [Amazon Simple Queue Service 訊息](with-sqs.md)
  + `S3Event`：適用於 [S3 觸發事件](with-s3.md)
  + `DynamoDBStreamEvent`：適用於 [Amazon DynamoDB Streams](with-ddb.md)
+ Lambda [內容](typescript-context.md)物件
+ [回呼](typescript-handler.md#typescript-handler-callback)處理常式模式

若要將 Lambda 類型定義新增至函式，請將 `@types/aws-lambda` 安裝為開發相依項：

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

然後，匯入 `aws-lambda` 中的類型：

```
import { Context, S3Event, APIGatewayProxyEvent } from 'aws-lambda';

export const handler = async (event: S3Event, context: Context) => {
    // Function code
};
```

陳述式 `import ... from 'aws-lambda'` 會匯入類型定義。不會匯入 `aws-lambda` npm 套件，該套件是一個不相關的第三方工具。如需詳細資訊，請參閱 DefinitelyTyped GitHub 儲存庫中的 [aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/aws-lambda)。

**注意**  
若您使用自訂類型定義，則無需安裝 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 套件。如需可定義自訂事件物件類型的函式範例，請參閱 [TypeScript Lambda 函式程式碼範例](typescript-handler.md#typescript-example-code)。

# 定義 TypeScript 格式的 Lambda 函數處理常式
<a name="typescript-handler"></a>

Lambda 函數*處理常式*是您的函數程式碼中處理事件的方法。當有人呼叫您的函數時，Lambda 會執行處理常式方法。函數會執行，直到處理常式傳回回應、結束或逾時為止。

本頁介紹了如何在 TypeScript 中使用 Lambda 函式處理常式，包括專案設定選項、命名慣例及最佳實務。本頁還提供了一個 TypeScript Lambda 函式範例，該函式會取得訂單的相關資訊、產生文字檔案收據，並將該檔案放入 Amazon Simple Storage Service (Amazon S3) 儲存貯體。如需編寫函數後如何部署函數的詳細資訊，請參閱[使用 .zip 檔案封存，在 Lambda 中部署轉換的 TypeScript 程式碼](typescript-package.md)或[使用容器映像在 Lambda 中部署轉譯的 TypeScript 程式碼](typescript-image.md)。

**Topics**
+ [設定 TypeScript 專案](#typescript-handler-setup)
+ [TypeScript Lambda 函式程式碼範例](#typescript-example-code)
+ [CommonJS 和 ES 模組](#typescript-commonjs-es-modules)
+ [Node.js 初始化](#typescript-initialization)
+ [處理常式命名慣例](#typescript-handler-naming)
+ [定義和存取輸入事件物件](#typescript-example-input)
+ [TypeScript 函式的有效處理常式模式](#typescript-handler-signatures)
+ [在處理常式中使用適用於 JavaScript v3 的 SDK](#typescript-example-sdk-usage)
+ [存取環境變數](#typescript-example-envvars)
+ [使用全域狀態](#typescript-handler-state)
+ [TypeScript Lambda 函式的程式碼最佳實務](#typescript-best-practices)

## 設定 TypeScript 專案
<a name="typescript-handler-setup"></a>

使用本機整合式開發環境 (IDE) 或文字編輯器來編寫 TypeScript 函式程式碼。無法在 Lambda 主控台上建立 TypeScript 程式碼。

初始化 TypeScript Lambda 專案的方法有多種。例如，您可以使用 `npm` 建立專案，建立 [AWS SAM 應用程式](typescript-package.md#aws-sam-ts)，或建立 [AWS CDK 應用程式](typescript-package.md#aws-cdk-ts)。使用 `npm` 建立專案：

```
npm init
```

函式程式碼位於 `.ts` 檔案中，您在建置時需要將其轉譯為 JavaScript 檔案。您可以使用 [esbuild](https://esbuild.github.io/) 或 Microsoft 的 TypeScript 編譯器 (`tsc`)，將 TypeScript 程式碼轉換為 JavaScript。若要使用 esbuild，請將其新增為開發相依項：

```
npm install -D esbuild
```

一個典型的 TypeScript Lambda 函式專案遵循以下一般結構：

```
/project-root
  ├── index.ts - Contains main handler
  ├── dist/ - Contains compiled JavaScript
  ├── package.json - Project metadata and dependencies
  ├── package-lock.json - Dependency lock file
  ├── tsconfig.json - TypeScript configuration
  └── node_modules/ - Installed dependencies
```

## TypeScript Lambda 函式程式碼範例
<a name="typescript-example-code"></a>

以下 Lambda 函式程式碼範例會取得訂單的相關資訊、產生文字檔案收據，並將該檔案放入 Amazon S3 儲存貯體。此範例定義了自訂事件類型 (`OrderEvent`)。若要了解如何匯入 AWS 事件來源的類型定義，請參閱 [Lambda 的類型定義](lambda-typescript.md#typescript-type-definitions)。

**注意**  
此範例使用了 ES 模組處理常式。Lambda 同時支援 ES 模組與 CommonJS 處理常式。如需詳細資訊，請參閱[CommonJS 和 ES 模組](nodejs-handler.md#nodejs-commonjs-es-modules)。

**Example index.ts Lambda 函式**  

```
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';

// Initialize the S3 client outside the handler for reuse
const s3Client = new S3Client();

// Define the shape of the input event
type OrderEvent = {
    order_id: string;
    amount: number;
    item: string;
}

/**
 * Lambda handler for processing orders and storing receipts in S3.
 */
export const handler = async (event: OrderEvent): Promise<string> => {
    try {
        // Access environment variables
        const bucketName = process.env.RECEIPT_BUCKET;
        if (!bucketName) {
            throw new Error('RECEIPT_BUCKET environment variable is not set');
        }

        // Create the receipt content and key destination
        const receiptContent = `OrderID: ${event.order_id}\nAmount: $${event.amount.toFixed(2)}\nItem: ${event.item}`;
        const key = `receipts/${event.order_id}.txt`;

        // Upload the receipt to S3
        await uploadReceiptToS3(bucketName, key, receiptContent);

        console.log(`Successfully processed order ${event.order_id} and stored receipt in S3 bucket ${bucketName}`);
        return 'Success';
    } catch (error) {
        console.error(`Failed to process order: ${error instanceof Error ? error.message : 'Unknown error'}`);
        throw error;
    }
};

/**
 * Helper function to upload receipt to S3
 */
async function uploadReceiptToS3(bucketName: string, key: string, receiptContent: string): Promise<void> {
    try {
        const command = new PutObjectCommand({
            Bucket: bucketName,
            Key: key,
            Body: receiptContent
        });

        await s3Client.send(command);
    } catch (error) {
        throw new Error(`Failed to upload receipt to S3: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
}
```

此 `index.ts` 檔案包含以下程式碼區段：
+ `import` 區塊：此區塊用於納入 Lambda 函式所需的程式碼，例如 [AWS SDK 用戶端](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/the-request-object.html)。
+ `const s3Client` 宣告：此宣告會在處理常式函式外部初始化 [Amazon S3 用戶端](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/)。Lambda 會於[初始化階段](lambda-runtime-environment.md#runtimes-lifecycle-ib)執行此程式碼，並且該用戶端會被保留下，在[多次調用中重複使用](lambda-runtime-environment.md#execution-environment-reuse)。
+ `type OrderEvent`：定義預期輸入事件的結構。
+ `export const handler`：此為 Lambda 調用的主要處理常式函式。部署函式時，請為[處理常式](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-Handler)屬性指定 `index.handler`。`Handler` 屬性的值由檔案名稱與匯出的處理常式方法名稱組成，兩者以點號分隔。
+ `uploadReceiptToS3` 函式：此為主要處理常式函式所參照的協助程式函式。

若要讓此函式正常運作，其[執行角色](lambda-intro-execution-role.md)必須允許 `s3:PutObject` 動作。此外，請確保定義 `RECEIPT_BUCKET` 環境變數。成功調用後，Amazon S3 儲存貯體應包含收據檔案。

## CommonJS 和 ES 模組
<a name="typescript-commonjs-es-modules"></a>

Node.js 支援兩個模組系統：CommonJS 和 ECMAScript 模組 (ES 模組）。Lambda 建議使用 ES 模組，因為它支援頂層等待，這可在[執行環境初始化](#typescript-initialization)期間完成非同步任務。

Node.js 會將副檔名為 `.cjs` CommonJS 的檔案視為 CommonJS 模組，副`.mjs`檔名則表示 ES 模組。根據預設，Node.js 會將副檔名為 `.js` 的檔案視為 CommonJS 模組。您可以將 Node.js 設定為將`.js`檔案視為 ES 模組，方法是`module`在函數的 `package.json` 檔案中指定`type`為 。您可以在 Lambda 中設定 Node.js，透過將 `—experimental-detect-module`旗標新增至`NODE_OPTIONS`環境變數，自動偵測`.js`檔案是否應視為 CommonJS 或 ES 模組。如需詳細資訊，請參閱[實驗 Node.js 功能](lambda-nodejs.md#nodejs-experimental-features)。

下列範例顯示使用 ES 模組和 CommonJS 模組編寫的函數處理常式。本頁面上的其餘範例都使用 ES 模組。

## Node.js 初始化
<a name="typescript-initialization"></a>

Node.js 使用非封鎖 I/O 模型，支援使用事件迴圈的高效率非同步操作。例如，如果 Node.js 進行網路呼叫，函數會繼續處理其他操作，而不會封鎖網路回應。收到網路回應時，會將其置於回呼佇列中。佇列中的任務會在目前任務完成時處理。

Lambda 建議使用頂層等待，以便在初始化期間完成執行環境初始化期間啟動的非同步任務。初始化期間未完成的非同步任務通常會在第一個函數叫用期間執行。這可能會導致非預期的行為或錯誤。例如，您的函數初始化可能會進行網路呼叫，以從參數存放區擷取 AWS 參數。如果此任務未在初始化期間完成，則值在調用期間可能為 null。初始化和調用之間也可能有延遲，這可能會在時間敏感的操作中觸發錯誤。特別是，如果在初始化階段未完成呼叫， AWS 服務呼叫可能會依賴時間敏感的請求簽章，導致服務呼叫失敗。在初始化期間完成任務通常會改善冷啟動效能，並在使用佈建並行時先調用效能。如需詳細資訊，請參閱我們的部落格文章[使用 Node.js ES 模組和頂層等待。 AWS Lambda](https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda)

## 處理常式命名慣例
<a name="typescript-handler-naming"></a>

設定函式時，[處理常式](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-Handler)的設定值由檔案名稱與匯出的處理常式方法名稱組成，二者以點號分隔。主控台中建立的函數以及本指南中的範例，預設值都是 `index.handler`。這表示 `handler` 方法是透過 `index.js` 或 `index.mjs` 檔案匯出的。

如果要在主控台中使用不同檔案名稱或函數處理常式名稱建立函數，您必須編輯預設處理常式名稱。

**變更函數處理常式名稱的方式 (主控台)**

1. 開啟 Lambda 主控台的[函數](https://console.aws.amazon.com/lambda/home#/functions)頁面，然後選擇您的函數。

1. 選擇 **程式碼** 索引標籤。

1. 向下捲動至**執行時間設定**窗格，並選擇**編輯**。

1. 在**處理常式**中，輸入函數處理常式的新名稱。

1. 選擇**儲存**。

## 定義和存取輸入事件物件
<a name="typescript-example-input"></a>

JSON 是 Lambda 函數最常見的標準輸入格式。在此範例中，函數預期輸入類似以下內容：

```
{
    "order_id": "12345",
    "amount": 199.99,
    "item": "Wireless Headphones"
}
```

使用 TypeScript 開發 Lambda 函式時，可透過類型或介面來定義輸入事件的結構。在此範例中，我們使用類型來定義事件結構：

```
type OrderEvent = {
    order_id: string;
    amount: number;
    item: string;
}
```

定義類型或介面之後，請在處理常式的簽章中加以使用，確保型別安全：

```
export const handler = async (event: OrderEvent): Promise<string> => {
```

在編譯期間，TypeScript 會驗證事件物件是否包含具有正確類型的必要欄位。例如，若嘗試將 `event.order_id` 用作數字或將 `event.amount` 用作字串，TypeScript 編譯器會報告錯誤。

## TypeScript 函式的有效處理常式模式
<a name="typescript-handler-signatures"></a>

建議您使用 [async/await](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/using-async-await.html) 來宣告函式處理常式，而不是使用 [callback](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/using-a-callback-function.html)。async/await 能以簡潔且易讀的方式編寫非同步程式碼，無需使用巢狀回呼或串連承諾。您可以透過非同步/等待模式撰寫讀起來像同步程式碼的程式碼，同時仍維持非同步和非封鎖的特性。

本節中的範例使用了 `S3Event` 類型。不過，您可以在 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 套件中使用任何其他 AWS 事件類型，或定義您自己的事件類型。若要使用來自 @types/aws-lambda 的類型，請執行下列操作：

1. 將 @types/aws-lambda 套件新增為開發依賴項：

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

1. 匯入所需類型，例如 `Context`、`S3Event` 或 `Callback`。

### 非同步函數處理常式 （建議）
<a name="typescript-handler-async"></a>

`async` 關鍵字會將函數標記為非同步，且 `await` 關鍵字會暫停函數的執行，直到 `Promise` 獲得解決為止。處理常式接受下列引數：
+ `event`：包含傳遞至函式的輸入資料。
+ `context`：包含有關調用、函式以及執行環境的資訊。如需詳細資訊，請參閱[使用 Lambda 內容物件擷取 TypeScript 函數資訊](typescript-context.md)。

以下所示為 async/await 模式的有效簽章：

```
export const handler = async (event: S3Event): Promise<void> => { };
```

```
export const handler = async (event: S3Event, context: Context): Promise<void> => { };
```

**注意**  
以非同步方式處理項目陣列時，務必將 await 與 `Promise.all` 搭配使用，確保所有操作完成。`forEach` 等方法不會等待非同步回呼完成。如需更多資訊，請參閱 Mozilla 文件中的 [Array.prototype.forEach()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)。

### 同步函數處理常式
<a name="typescript-handler-synchronous"></a>

如果您的函數不執行任何非同步任務，您可以使用同步函數處理常式，使用以下其中一個函數簽章：

```
export const handler = (event: S3Event): void => { };
```

```
export const handler = (event: S3Event, context: Context): void => { };
```

### 回應串流函數處理常式
<a name="typescript-handler-response-streaming"></a>

Lambda 支援使用 Node.js 進行回應串流。回應串流函數處理常式使用 awslambda.streamifyResponse() 裝飾項目，並採用 3 個參數：事件、responseStream 和內容。函數簽章為：

```
export const handler = awslambda.streamifyResponse(async (event: APIGatewayProxyEvent, responseStream: NodeJS.WritableStream, context: Context) => { });
```

如需詳細資訊，請參閱 Lambda 函數的回應串流。

### 以回呼為基礎的函數處理常式
<a name="typescript-handler-callback"></a>

**注意**  
以回呼為基礎的函數處理常式最多僅支援 Node.js 22。從 Node.js 24 開始，應使用非同步函數處理常式實作非同步任務。

以回呼為基礎的函數處理常式可以使用事件、內容和回呼引數。回呼引數預期會接收一個 `Error` 與一個回應物件，其中回應物件必須可進行 JSON 序列化。

以下是回呼處理常式模式的有效簽章：

```
export const handler = (event: S3Event, context: Context, callback: Callback<void>): void => { };
```

該函式會一直執行，直至[事件迴圈](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/)清空或函式逾時為止。直到完成所有的事件迴圈任務，回應才會傳送到叫用端。如果函式逾時，便會傳回錯誤。您可以透過設定 [context.callbackWaitsForEmptyEventLoop](typescript-context.md) 為「false (失敗)」來設定執行時間立即傳回回應。

**Example 帶回呼功能的 TypeScript 函數**  
下列範例使用了 `APIGatewayProxyCallback`，這是專用於 API Gateway 整合的指定回呼類型。大多數 AWS 事件來源使用上述簽章中顯示的一般`Callback`類型。  

```
import { Context, APIGatewayProxyCallback, APIGatewayEvent } from 'aws-lambda';

export const lambdaHandler = (event: APIGatewayEvent, context: Context, callback: APIGatewayProxyCallback): void => {
    console.log(`Event: ${JSON.stringify(event, null, 2)}`);
    console.log(`Context: ${JSON.stringify(context, null, 2)}`);
    callback(null, {
        statusCode: 200,
        body: JSON.stringify({
            message: 'hello world',
        }),
    });
};
```

## 在處理常式中使用適用於 JavaScript v3 的 SDK
<a name="typescript-example-sdk-usage"></a>

通常，您將使用 Lambda 函數與其他 AWS 資源互動或進行更新。與這些資源互動的最簡單方法便是使用 適用於 JavaScript 的 AWS SDK。所有支援的 Lambda Node.js 執行時期都包含[適用於 JavaScript 第 3 版的 SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/introduction/)。不過，我們強烈建議您在部署套件中包含所需的 AWS SDK 用戶端。此舉能在日後 Lambda 執行時期更新時，最大限度實現[回溯相容性](runtimes-update.md#runtime-update-compatibility)。

若要將 SDK 相依項新增至函數，請針對您需要的特定 SDK 用戶端使用 `npm install` 命令。在範例程式碼中，我們使用的是 [Amazon S3 用戶端](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/)。透過在包含 `package.json` 檔案的目錄中執行下列命令，即可新增這些相依項：

```
npm install @aws-sdk/client-s3
```

在函式程式碼中匯入所需的用戶端與命令，如範例函式所示：

```
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
```

然後，初始化 [Amazon S3 用戶端](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/)：

```
const s3Client = new S3Client();
```

在此範例中，我們在主要處理常式函式外部初始化 Amazon S3 用戶端，以免每次調用函式時都必須初始化該用戶端。初始化 SDK 用戶端之後，您可以使用它來對該 AWS 服務進行 API 呼叫。此範例程式碼會呼叫 Amazon S3 [PutObject](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/command/PutObjectCommand/) API，如下所示：

```
const command = new PutObjectCommand({
    Bucket: bucketName,
    Key: key,
    Body: receiptContent
});
```

## 存取環境變數
<a name="typescript-example-envvars"></a>

在處理常式程式碼中，您可以使用 `process.env` 來引用任意[環境變數](configuration-envvars.md)。在此範例中，我們使用下列程式碼行來引用定義的 `RECEIPT_BUCKET` 環境變數：

```
// Access environment variables
const bucketName = process.env.RECEIPT_BUCKET;
if (!bucketName) {
    throw new Error('RECEIPT_BUCKET environment variable is not set');
}
```

## 使用全域狀態
<a name="typescript-handler-state"></a>

在首次調用函式之前，Lambda 會在[初始化階段](lambda-runtime-environment.md#runtimes-lifecycle-ib)執行靜態程式碼。在初始化期間建立的資源會在調用間隔期間保留在記憶體中，無需您在每次調用函式時都建立這些資源。

在範例程式碼中，S3 用戶端初始化程式碼位於主要處理常式外部。執行時期會在函式處理第一個事件之前初始化用戶端，且用戶端在所有調用中均可供重複使用。

## TypeScript Lambda 函式的程式碼最佳實務
<a name="typescript-best-practices"></a>

建置 Lambda 函式時，請遵循下列準則：
+ **區隔 Lambda 處理常式與您的核心邏輯。**能允許您製作更多可測單位的函式。
+ **控制函數部署套件內的相依性。** AWS Lambda 執行環境包含許多程式庫。對於 Node.js 和 Python 執行期，這些包括 AWS SDKs。若要啟用最新的一組功能與安全更新，Lambda 會定期更新這些程式庫。這些更新可能會為您的 Lambda 函數行為帶來細微的變更。若要完全掌控您函式所使用的相依性，請利用部署套件封裝您的所有相依性。
+ **最小化依存項目的複雜性。**偏好更簡易的框架，其可快速在[執行環境](lambda-runtime-environment.md)啟動時載入。
+ **將部署套件最小化至執行時間所必要的套件大小。**這能減少您的部署套件被下載與呼叫前解壓縮的時間。

**請利用執行環境重新使用來改看函式的效能。**在函式處理常式之外初始化 SDK 用戶端和資料庫連線，並在本機快取 `/tmp` 目錄中的靜態資產。由您函式的相同執行個體處理的後續叫用可以重複使用這些資源。這可藉由減少函數執行時間來節省成本。

若要避免叫用間洩漏潛在資料，請不要使用執行環境來儲存使用者資料、事件，或其他牽涉安全性的資訊。如果您的函式依賴無法存放在處理常式內記憶體中的可變狀態，請考慮為每個使用者建立個別函式或個別函式版本。

**使用 Keep-Alive 指令維持持續連線的狀態。**Lambda 會隨著時間的推移清除閒置連線。叫用函數時嘗試重複使用閒置連線將導致連線錯誤。若要維護持續連線，請使用與執行階段相關聯的 keep-alive (保持啟用) 指令。如需範例，請參閱[在 Node.js 中重複使用 Keep-Alive 的連線](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-reusing-connections.html)。

**使用[環境變數](configuration-envvars.md)將操作參數傳遞給您的函數。**例如，如果您正在寫入到 Amazon S3 儲存貯體，而非對您正在寫入的儲存貯體名稱進行硬式編碼，請將儲存貯體名稱設定為環境變數。

**避免在 Lambda 函數中使用遞迴調用**，其中函數會調用自己或啟動可能再次調用函數的程序。這會導致意外的函式呼叫量與升高的成本。若您看到意外的調用數量，當更新程式碼時，請立刻將函數的預留並行設為 `0`，以調節對函數的所有調用。

**請勿在您的 Lambda 函數程式碼中使用未記錄的非公有 API**。對於 AWS Lambda 受管執行期，Lambda 會定期將安全性和功能更新套用至 Lambda 的內部 APIs。這些內部 API 更新可能是向後不相容的，這會導致意外結果，例如若您的函數依賴於這些非公有 API，則叫用失敗。請參閱 [API 參考](https://docs.aws.amazon.com/lambda/latest/api/welcome.html)查看公開可用 API 的清單。

**撰寫等冪程式碼。**為函數撰寫等冪程式碼可確保採用相同方式來處理重複事件。程式碼應正確驗證事件並正常處理重複的事件。如需詳細資訊，請參閱 [How do I make my Lambda function idempotent?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/) (如何讓 Lambda 函數等冪？)。

# 使用 .zip 檔案封存，在 Lambda 中部署轉換的 TypeScript 程式碼
<a name="typescript-package"></a>

您必須先將 TypeScript 程式碼轉換為 JavaScript，才能將 TypeScript 程式碼部署到其中。 AWS Lambda JavaScript 本頁介紹了建置 TypeScript 程式碼，並透過 .zip 封存檔將其部署至 Lambda 的三種方法︰
+ [使用 AWS Serverless Application Model (AWS SAM)](#aws-sam-ts)
+ [使用 AWS Cloud Development Kit (AWS CDK)](#aws-cdk-ts)
+ [使用 AWS Command Line Interface (AWS CLI) 和 esbuild](#aws-cli-ts)

AWS SAM 並 AWS CDK 簡化 TypeScript 函數的建置和部署。[AWS SAM 範本規範](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification.html)提供了一個簡單而清晰的語法，來描述構成無伺服器應用程式的 Lambda 函數、API、許可、組態和事件。藉助 [AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/home.html)，您可以在雲端建置可靠、可擴展且經濟高效的應用程式，並具有程式設計語言的強大表達能力。 AWS CDK 適用於中等至經驗豐富的 AWS 使用者。 AWS CDK 和 都 AWS SAM 使用 esbuild 將 TypeScript 程式碼轉換為 JavaScript。

## 使用 AWS SAM 將 TypeScript 程式碼部署至 Lambda
<a name="aws-sam-ts"></a>

請遵循以下步驟，使用 AWS SAM下載、建置和部署範例 Hello World TypeScript 應用程式。此應用程式實作一個基本的 API 後端。其包含 Amazon API Gateway 端點和 Lambda 函數。當您將 GET 請求傳送至 API Gateway 端點時，會叫用 Lambda 函數。該函數會傳回 `hello world` 訊息。

**注意**  
AWS SAM 使用 esbuild 從 TypeScript 程式碼建立 Node.js Lambda 函數。esbuild 支援目前為公開預覽。在公開預覽期間，esbuild 支援可能面臨向後相容變更。

**先決條件**

若要完成本節中的步驟，您必須執行下列各項：
+ [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)
+ Node.js

**部署範例 AWS SAM 應用程式**

1. 使用 Hello World TypeScript 範本來初始化應用程式。

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

1. (選用) 範例應用程式包含常用工具的組態，如用於程式碼檢查的 [ESLlint](https://eslint.org/) 和用於單元測試的 [Jest](https://jestjs.io/)。執行檢查和測試命令︰

   ```
   cd sam-app/hello-world
   npm install
   npm run lint
   npm run test
   ```

1. 建置應用程式。

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

1. 部署應用程式。

   ```
   sam deploy --guided
   ```

1. 依照螢幕上的提示操作。若要接受互動體驗中提供的預設選項，請以 `Enter` 回應。

1. 輸出會顯示 REST API 的端點。在瀏覽器中開啟端點以測試函數。您應看到此回應︰

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

1. 這是可透過網際網路存取的公有 API 端點。建議您在測試後刪除端點。

   ```
   sam delete
   ```

## 使用 AWS CDK 將 TypeScript 程式碼部署至 Lambda
<a name="aws-cdk-ts"></a>

請遵循以下步驟，使用 AWS CDK建置和部署範例 TypeScript 應用程式。此應用程式實作一個基本的 API 後端。其包含 API Gateway 端點和 Lambda 函數。當您將 GET 請求傳送至 API Gateway 端點時，會叫用 Lambda 函數。該函數會傳回 `hello world` 訊息。

**先決條件**

若要完成本節中的步驟，您必須執行下列各項：
+ [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)
+ Node.js
+ [Docker](https://www.docker.com/get-started/) 或 [esbuild](https://esbuild.github.io/)

**部署範例 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) 套件作為開發相依項。此套件包含 Lambda 的類型定義。

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

1. 開啟 **lib** 目錄。您應看到名稱為 **hello-world-stack.ts** 的檔案。在此目錄中建立兩個新檔案：**hello-world.function.ts** 和 **hello-world.ts**。

1. 開啟 **hello-world.function.ts**，並將下列程式碼新增至檔案。這是 Lambda 函數的程式碼。
**注意**  
`import` 陳述式會從 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 中匯入類型定義。不會匯入 `aws-lambda` NPM 套件，這是不相關的第三方工具。如需詳細資訊，請參閱 DefinitelyTyped GitHub 儲存庫中的 [aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/aws-lambda)。

   ```
   import { Context, APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda';
   
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
       console.log(`Event: ${JSON.stringify(event, null, 2)}`);
       console.log(`Context: ${JSON.stringify(context, null, 2)}`);
       return {
           statusCode: 200,
           body: JSON.stringify({
               message: 'hello world',
           }),
       };
   };
   ```

1. 開啟 **hello-world.ts**，然後將下列程式碼新增至檔案。這包含可建立 Lambda 函數的 [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';
     
   export class HelloWorld extends Construct {
     constructor(scope: Construct, id: string) {
       super(scope, id);
       const helloFunction = new NodejsFunction(this, 'function');
       new LambdaRestApi(this, 'apigw', {
         handler: helloFunction,
       });
     }
   }
   ```

   `NodejsFunction` 建構預設會假設以下內容︰
   + 您的函數處理常式被稱為 `handler`。
   + 包含函數程式碼 (**hello-world.function.ts**) 的 .ts 檔案，與包含建構 (**hello-world.ts**) 的 .ts 檔案位於同一目錄中。該建構使用建構 ID ("hello-world") 和 Lambda 處理常式檔案的名稱 ("function") 來尋找函數程式碼。例如，如果您的函數程式碼位於名稱為 **hello-world.my-function.ts** 檔案，則 **hello-world.ts** 檔案必須引用如下所示函數程式碼︰

     ```
     const helloFunction = new NodejsFunction(this, 'my-function');
     ```

   您可以變更此行為並設定其他 esbuild 參數。如需詳細資訊，請參閱 AWS CDK API [參考中的設定 esbuild](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html#configuring-esbuild)。

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. 在包含 `cdk.json` 檔案的 `hello-world` 目錄中部署您的應用程式。

   ```
   cdk deploy
   ```

1. 會使用 esbuild AWS CDK 建置和封裝 Lambda 函數，然後將函數部署至 Lambda 執行時間。輸出會顯示 REST API 的端點。在瀏覽器中開啟端點以測試函數。您應看到此回應︰

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

   這是可透過網際網路存取的公有 API 端點。建議您在測試後刪除端點。

## 使用 AWS CLI 和 esbuild 將 TypeScript 程式碼部署至 Lambda
<a name="aws-cli-ts"></a>

下列範例示範如何使用 esbuild 和 將 TypeScript 程式碼傳輸和部署至 Lambda AWS CLI。esbuild 會產生一個 JavaScript 檔案，其中包含所有相依性。這是您需要新增至 .zip 封存的唯一檔案。

**先決條件**

若要完成本節中的步驟，您必須執行下列各項：
+ [AWS CLI 第 2 版](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ Node.js
+ Lambda 函數的[執行角色](lambda-intro-execution-role.md)
+ 若您是 Windows 使用者，則為壓縮檔公用程式，如 [7zip](https://www.7-zip.org/download.html)。

**部署範例函數**

1. 在您的本機電腦上，為新函數建立專案目錄。

1. 建立具有 npm 的新 Node.js 專案，或您選擇的套件管理器。

   ```
   npm init
   ```

1. 新增 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 和 [esbuild](https://esbuild.github.io/) 套件作為開發相依項。`@types/aws-lambda` 套件包含 Lambda 的類型定義。

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

1. 建立名稱為 **index.ts** 的新檔案。將下列程式碼新增至新檔案︰ 這是 Lambda 函數的程式碼。該函數會傳回 `hello world` 訊息。函數不會建立任何 API Gateway 資源。
**注意**  
`import` 陳述式會從 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 中匯入類型定義。不會匯入 `aws-lambda` NPM 套件，這是不相關的第三方工具。如需詳細資訊，請參閱 DefinitelyTyped GitHub 儲存庫中的 [aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/aws-lambda)。

   ```
   import { Context, APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda';
   
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
     console.log(`Event: ${JSON.stringify(event, null, 2)}`);
     console.log(`Context: ${JSON.stringify(context, null, 2)}`);
     return {
         statusCode: 200,
         body: JSON.stringify({
             message: 'hello world',
         }),
      };
   };
   ```

1. 將建置指令碼新增至 **package.json** 檔案。這會將 esbuild 設定為自動建立 .zip 部署套件。如需詳細資訊，請參閱 esbuild 文件中的[建置指令碼](https://esbuild.github.io/getting-started/#build-scripts)。

------
#### [ Linux and MacOS ]

   ```
   "scripts": {
     "prebuild": "rm -rf dist",
     "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js",
     "postbuild": "cd dist && zip -r index.zip index.js*"
   },
   ```

------
#### [ Windows ]

   在此範例中，`"postbuild"` 命令會使用 [7zip](https://www.7-zip.org/download.html) 公用程式來建立 .zip 檔案。使用您偏好的 Windows zip 公用程式，並視需要修改命令。

   ```
   "scripts": {
     "prebuild": "del /q dist",
     "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js",
     "postbuild": "cd dist && 7z a -tzip index.zip index.js*"
   },
   ```

------

1. 建置套件。

   ```
   npm run build
   ```

1. 使用 .zip 部署套件來建立 Lambda 函數。用[執行角色](lambda-intro-execution-role.md)的 Amazon Resource Name (ARN) 取代反白顯示的文字。

   ```
   aws lambda create-function --function-name hello-world --runtime "nodejs24.x" --role arn:aws:iam::123456789012:role/lambda-ex --zip-file "fileb://dist/index.zip" --handler index.handler
   ```

1. [執行測試事件](testing-functions.md)，以確認函數傳回下列回應。如果您想使用 API Gateway 叫用此函數，[請建立並設定 REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html)。

   ```
   {
     "statusCode": 200,
     "body": "{\"message\":\"hello world\"}"
   }
   ```

# 使用容器映像在 Lambda 中部署轉譯的 TypeScript 程式碼
<a name="typescript-image"></a>

您可以將 TypeScript 程式碼部署到 AWS Lambda 函數做為 Node.js [容器映像](images-create.md)。 AWS 提供 Node.js [的基礎映像](nodejs-image.md#nodejs-image-base)，以協助您建置容器映像。這些基礎映像會預先載入語言執行時間，以及在 Lambda 上執行映像所需的其他元件。 為每個基礎映像 AWS 提供 Dockerfile，以協助建置容器映像。

如果您使用社群或私有企業基礎映像，必須[將 Node.js 執行時間介面用戶端 (RIC)](nodejs-image.md#nodejs-image-clients) 新增至基礎映像，以使其與 Lambda 相容。

Lambda 提供執行期介面模擬器，供您在本機測試函數。Node.js AWS 的基礎映像包含執行時間界面模擬器。如果您使用替代基礎映像 (例如 Alpine Linux 或 Debian 映像)，便可 [將模擬器建置到映像中](https://github.com/aws/aws-lambda-runtime-interface-emulator/?tab=readme-ov-file#build-rie-into-your-base-image) 或 [將其安裝在本機電腦上](https://github.com/aws/aws-lambda-runtime-interface-emulator/?tab=readme-ov-file#test-an-image-without-adding-rie-to-the-image)。

## 使用 Node.js 基礎映像來建置和封裝 TypeScript 函數程式碼
<a name="base-image-typescript"></a>

### 先決條件
<a name="typescript-image-prerequisites"></a>

若要完成本節中的步驟，您必須執行下列各項：
+ [AWS CLI 第 2 版](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
+ [Docker](https://docs.docker.com/get-docker) (最低版本 25.0.0)
+ Docker [buildx 外掛程式](https://github.com/docker/buildx/blob/master/README.md)。
+ Node.js 22.x

### 從基礎映像建立映像
<a name="typescript-image-create"></a>

**從 Lambda AWS 的基礎映像建立映像**

1. 在您的本機電腦上，為新函數建立專案目錄。

1. 建立具有 `npm` 的新 Node.js 專案，或您選擇的套件管理員。

   ```
   npm init
   ```

1. 新增 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 和 [esbuild](https://esbuild.github.io/) 套件作為開發相依項。`@types/aws-lambda` 套件包含 Lambda 的類型定義。

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

1. 將[建置指令碼](https://esbuild.github.io/getting-started/#build-scripts)新增至 `package.json` 檔案。

   ```
     "scripts": {
     "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js"
   }
   ```

1. 建立稱為 `index.ts` 的新檔案。將下列範本程式碼新增至新檔案。這是 Lambda 函數的程式碼。該函數會傳回 `hello world` 訊息。
**注意**  
`import` 陳述式會從 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 中匯入類型定義。不會匯入 `aws-lambda` NPM 套件，這是不相關的第三方工具。如需詳細資訊，請參閱 DefinitelyTyped GitHub 儲存庫中的 [aws-lambda](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/aws-lambda)。

   ```
   import { Context, APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda';
   
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
       console.log(`Event: ${JSON.stringify(event, null, 2)}`);
       console.log(`Context: ${JSON.stringify(context, null, 2)}`);
       return {
           statusCode: 200,
           body: JSON.stringify({
               message: 'hello world',
           }),
       };
   };
   ```

1. 建立包含下列組態的新 Dockerfile。
   + 將 `FROM` 屬性設定為基礎映像的 URI。
   + 設定 `CMD` 引數以指定 Lambda 函數處理常式。

   下列範例 Dockerfile 使用多階段建置。第一步將 TypeScript 程式碼轉譯為 JavaScript。第二步產生僅包含 JavaScript 檔案和生產相依項的容器映像。

   請注意，範例 Dockerfile 不包含 [USER 指令](https://docs.docker.com/reference/dockerfile/#user)。當您將容器映像部署到 Lambda 時，Lambda 會自動定義一個具有最低權限許可的預設 Linux 使用者。這與標準 Docker 行為不同，後者會在未提供 `USER` 指令時預設為 `root` 使用者。  
**Example Dockerfile**  

   ```
   FROM public.ecr.aws/lambda/nodejs:22 as builder
   WORKDIR /usr/app
   COPY package.json index.ts  ./
   RUN npm install
   RUN npm run build
       
   FROM public.ecr.aws/lambda/nodejs:22
   WORKDIR ${LAMBDA_TASK_ROOT}
   COPY --from=builder /usr/app/dist/* ./
   CMD ["index.handler"]
   ```

1. 使用 [docker build](https://docs.docker.com/engine/reference/commandline/build/) 命令建立 Docker 映像檔。以下範例將映像命名為 `docker-image` 並為其提供 `test` [標籤](https://docs.docker.com/engine/reference/commandline/build/#tag)。若要使映像與 Lambda 相容，必須使用 `--provenance=false` 選項。

   ```
   docker buildx build --platform linux/amd64 --provenance=false -t docker-image:test .
   ```
**注意**  
此命令會指定 `--platform linux/amd64` 選項，確保無論建置機器的架構為何，您的容器都與 Lambda 執行環境相容。如果您打算使用 ARM64 指令集架構建立 Lambda 函數，務必將命令變更為改用 `--platform linux/arm64` 選項。

### (選用) 在本機測試映像
<a name="typescript-image-test"></a>

1. 使用 **docker run** 命令啟動 Docker 影像。在此範例中，`docker-image` 為映像名稱，`test` 為標籤。

   ```
   docker run --platform linux/amd64 -p 9000:8080 docker-image:test
   ```

   此命令將映像作為容器執行，並在 `localhost:9000/2015-03-31/functions/function/invocations` 建立本機端點。
**注意**  
如果您為 ARM64 指令集架構建立 Docker 映像檔，請務必將`--platform linux/arm64`選項改用選項。`--platform linux/amd64`

1. 從新的終端機視窗，將事件張貼至本機端點。

------
#### [ Linux/macOS ]

   在 Linux 或 macOS 中，執行下列 `curl` 命令：

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
   ```

   此命令會透過空白事件調用函數，並傳回一個回應。如果您使用自己的函數程式碼而不是範例函數程式碼，則可能需要使用 JSON 承載調用該函數。範例：

   ```
   curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
   ```

------
#### [ PowerShell ]

   在 PowerShell 中，執行下列 `Invoke-WebRequest` 命令：

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{}' -ContentType "application/json"
   ```

   此命令會透過空白事件調用函數，並傳回一個回應。如果您使用自己的函數程式碼而不是範例函數程式碼，則可能需要使用 JSON 承載調用該函數。範例：

   ```
   Invoke-WebRequest -Uri "http://localhost:9000/2015-03-31/functions/function/invocations" -Method Post -Body '{"payload":"hello world!"}' -ContentType "application/json"
   ```

------

1. 取得容器 ID。

   ```
   docker ps
   ```

1. 使用 [docker kill](https://docs.docker.com/engine/reference/commandline/kill/) 命令停止容器。在此命令中，將 `3766c4ab331c` 替換為上一步驟中的容器 ID。

   ```
   docker kill 3766c4ab331c
   ```

### 部署映像
<a name="typescript-image-deploy"></a>

**若要將映像上傳至 Amazon ECR 並建立 Lambda 函數**

1. 使用 [get-login-password](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/get-login-password.html) 命令，向 Amazon ECR 登錄檔驗證 Docker CLI。
   + 將 `--region`值設定為您要 AWS 區域 在其中建立 Amazon ECR 儲存庫的 。
   + `111122223333` 以您的 AWS 帳戶 ID 取代 。

   ```
   aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-east-1.amazonaws.com
   ```

1. 使用 [create-repository](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecr/create-repository.html) 命令在 Amazon ECR 中建立儲存庫。

   ```
   aws ecr create-repository --repository-name hello-world --region us-east-1 --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE
   ```
**注意**  
Amazon ECR 儲存庫必須與 Lambda 函數位於相同的 AWS 區域 中。

   如果成功，您將會看到以下回應：

   ```
   {
       "repository": {
           "repositoryArn": "arn:aws:ecr:us-east-1:111122223333:repository/hello-world",
           "registryId": "111122223333",
           "repositoryName": "hello-world",
           "repositoryUri": "111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world",
           "createdAt": "2023-03-09T10:39:01+00:00",
           "imageTagMutability": "MUTABLE",
           "imageScanningConfiguration": {
               "scanOnPush": true
           },
           "encryptionConfiguration": {
               "encryptionType": "AES256"
           }
       }
   }
   ```

1. 從上一步驟的輸出中複製 `repositoryUri`。

1. 執行 [docker tag](https://docs.docker.com/engine/reference/commandline/tag/) 命令，將 Amazon ECR 儲存庫中的本機映像標記為最新版本。在此命令中：
   + `docker-image:test` 為 Docker 映像檔的名稱和[標籤](https://docs.docker.com/engine/reference/commandline/build/#tag)。這是您在 `docker build` 命令中指定的映像名稱和標籤。
   + 將 `<ECRrepositoryUri>` 替換為複製的 `repositoryUri`。確保在 URI 的末尾包含 `:latest`。

   ```
   docker tag docker-image:test <ECRrepositoryUri>:latest
   ```

   範例：

   ```
   docker tag docker-image:test 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. 執行 [docker push](https://docs.docker.com/engine/reference/commandline/push/) 命令，將本機映像部署至 Amazon ECR 儲存庫。確保在儲存庫 URI 的末尾包含 `:latest`。

   ```
   docker push 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest
   ```

1. [建立函數的執行角色](lambda-intro-execution-role.md#permissions-executionrole-api) (若您還沒有的話)。在下一個步驟中您需要角色的 Amazon Resource Name (ARN)。

1. 建立 Lambda 函數。對於 `ImageUri`，從之前的設定中指定儲存庫 URI。確保在 URI 的末尾包含 `:latest`。

   ```
   aws lambda create-function \
     --function-name hello-world \
     --package-type Image \
     --code ImageUri=111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
     --role arn:aws:iam::111122223333:role/lambda-ex
   ```
**注意**  
只要映像與 Lambda 函數位於相同的區域，您就可以使用不同 AWS 帳戶中的映像來建立函數。如需詳細資訊，請參閱[Amazon ECR 跨帳戶許可](images-create.md#configuration-images-xaccount-permissions)。

1. 調用函數。

   ```
   aws lambda invoke --function-name hello-world response.json
   ```

   您應該看到如下回應：

   ```
   {
     "ExecutedVersion": "$LATEST", 
     "StatusCode": 200
   }
   ```

1. 若要查看函數的輸出，請檢查 `response.json` 檔案。

若要更新函數程式碼，您必須再次建置映像、將新映像上傳到 Amazon ECR 存放庫，然後使用 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令將映像部署到 Lambda 函數。

Lambda 會將映像標籤解析為特定映像摘要。這表示如果您將用來部署函數的映像標籤指向 Amazon ECR 中的新映像，Lambda 不會自動更新函數以使用新映像。

若要將新映像部署至相同的 Lambda 函數，必須使用 [update-function-code](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-code.html) 命令，即使 Amazon ECR 中的映像標籤保持不變亦如此。在以下範例中，`--publish` 選項會使用更新的容器映像來建立新的函數版本。

```
aws lambda update-function-code \
  --function-name hello-world \
  --image-uri 111122223333.dkr.ecr.us-east-1.amazonaws.com/hello-world:latest \
  --publish
```

# 使用 Lambda 內容物件擷取 TypeScript 函數資訊
<a name="typescript-context"></a>

當 Lambda 執行您的函數時，它會將內容物件傳遞至[處理常式](typescript-handler.md)。此物件提供的方法和各項屬性提供了有關調用、函式以及執行環境的資訊。

若要啟用內容物件的類型檢查，必須將 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 套件新增為開發相依項，並匯入 `Context` 類型。如需詳細資訊，請參閱[Lambda 的類型定義](lambda-typescript.md#typescript-type-definitions)。

**內容方法**
+ `getRemainingTimeInMillis()` - 傳回執行逾時前剩餘的毫秒數。

**內容屬性**
+ `functionName` – Lambda 函數的名稱。
+ `functionVersion` – 函數的[版本](configuration-versions.md)。
+ `invokedFunctionArn` - 用於調用此函數的 Amazon Resource Name (ARN)。指出調用者是否指定版本號或別名。
+ `memoryLimitInMB` - 分配給函數的記憶體數量。
+ `awsRequestId` - 調用請求的識別符。
+ `logGroupName` - 函數的日誌群組。
+ `logStreamName` - 函數執行個體的記錄串流。
+ `identity` - (行動應用程式) 已授權請求的 Amazon Cognito 身分的相關資訊。
  + `cognitoIdentityId` - 已驗證的 Amazon Cognito 身分。
  + `cognitoIdentityPoolId` - 授權調用的 Amazon Cognito 身分集區。
+ `clientContext` - (行動應用程式) 用戶端應用程式提供給 Lambda 的用戶端內容。
  + `client.installation_id`
  + `client.app_title`
  + `client.app_version_name`
  + `client.app_version_code`
  + `client.app_package_name`
  + `env.platform_version`
  + `env.platform`
  + `env.make`
  + `env.model`
  + `env.locale`
  + `Custom` - 用戶端應用程式所設定的自訂值。
+ `callbackWaitsForEmptyEventLoop` – 根據預設 (`true`)，在使用回呼型函數處理常式時，Lambda 會在回呼執行後等待事件迴圈為空，再結束函數叫用。將 設定為 `false`以傳送回應，並在回呼執行後立即結束調用，而不是等待事件迴圈為空。未處理的事件會在下次調用期間繼續執行。請注意，Lambda 僅支援 Node.js 22 和更早執行時間的回呼式函數處理常式。

**Example index.ts 檔案**  
以下範例函式紀錄內文資訊和傳回日誌的位置。  
在 Lambda 函數中使用這段程式碼之前，您必須先新增 [@types/aws-lambda](https://www.npmjs.com/package/@types/aws-lambda) 套件當作開發相依項。此套件包含 Lambda 的類型定義。如需詳細資訊，請參閱[Lambda 的類型定義](lambda-typescript.md#typescript-type-definitions)。

```
import { Context } from 'aws-lambda';
export const lambdaHandler = async (event: string, context: Context): Promise<string> => {
  console.log('Remaining time: ', context.getRemainingTimeInMillis());
  console.log('Function name: ', context.functionName);
  return context.logStreamName;
};
```

# 記錄和監控 TypeScript Lambda 函數
<a name="typescript-logging"></a>

AWS Lambda 會自動監控 Lambda 函數，並將日誌項目傳送至 Amazon CloudWatch。您的 Lambda 函數隨附有 CloudWatch Logs 日誌群組，且函數的每一執行個體各有一個日誌串流。Lambda 執行期環境會將每次調用的詳細資訊和函數程式碼的其他輸出，傳送至日誌串流。如需 CloudWatch Logs 的詳細資訊，請參閱[將 Lambda 函式日誌傳送至 CloudWatch Logs](monitoring-cloudwatchlogs.md)。

若要由您的函數程式碼輸出日誌，您可以在[主控台物件](https://nodejs.org/docs/latest-v18.x/api/console.html)上使用方法。若要更詳細記錄，您可以使用任何寫入 `stdout` 或 `stderr` 的記錄程式庫。

**Topics**
+ [使用日誌記錄工具和程式庫](#typescript-tools-libraries)
+ [使用 Powertools for AWS Lambda (TypeScript) 和 AWS SAM 進行結構化記錄](#typescript-logging-sam)
+ [使用 Powertools for AWS Lambda (TypeScript) 和 AWS CDK 進行結構化記錄](#typescript-logging-cdk)
+ [在 Lambda 主控台檢視日誌](#typescript-logging-console)
+ [在 CloudWatch 主控台中檢視 記錄](#typescript-logging-cwconsole)

## 使用日誌記錄工具和程式庫
<a name="typescript-tools-libraries"></a>

[Powertools for AWS Lambda (TypeScript)](https://docs.aws.amazon.com/powertools/typescript/) 是一種開發人員工具組，可實作無伺服器最佳實務並提高開發人員速度。[Logger 公用程式](https://docs.powertools.aws.dev/lambda/typescript/latest/features/logger/)提供 Lambda 優化記錄器，其中包含有關所有函數之函數內容的其他資訊，輸出結構為 JSON。使用此公用程式執行下列操作：
+ 從 Lambda 內容、冷啟動和 JSON 形式的結構記錄輸出中擷取關鍵欄位
+ 在收到指示時記錄 Lambda 調用事件 (預設為停用)
+ 透過日誌採樣僅列印調用百分比的所有日誌 (預設為停用)
+ 在任何時間點將其他金鑰附加至結構化日誌
+ 使用自訂日誌格式化程式 (自帶格式化程式)，以與組織的日誌記錄 RFC 相容的結構輸出日誌。

## 使用 Powertools for AWS Lambda (TypeScript) 和 AWS SAM 進行結構化記錄
<a name="typescript-logging-sam"></a>

請依照下列步驟，使用 搭配整合式 Powertools for (TypeScript) 模組下載、建置和部署範例 Hello World TypeScript 應用程式 AWS SAM。 [AWS Lambda TypeScript](https://docs.powertools.aws.dev/lambda-typescript) 此應用程式實作了基本 API 後端，並使用 Powertools 發送日誌、指標和追蹤。其包含 Amazon API Gateway 端點和 Lambda 函數。當您將 GET 請求傳送至 API Gateway 端點時，Lambda 函數會調用、使用內嵌指標格式將日誌和指標傳送至 CloudWatch，並將追蹤傳送至 AWS X-Ray。該函數會傳回 `hello world` 訊息。

**先決條件**

若要完成本節中的步驟，您必須執行下列各項：
+ Node.js 20 或更新版本
+ [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
   ```

1. 建置應用程式。

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

1. 部署應用程式。

   ```
   sam deploy --guided
   ```

1. 依照螢幕上的提示操作。若要接受互動體驗中提供的預設選項，請按下 `Enter`。
**注意**  
對於 **HelloWorldFunction may not have authorization defined, Is this okay?**，確保輸入 `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 日誌](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-logs.html)。如需詳細資訊，請參閱《AWS Serverless Application Model 開發人員指南》** 中的 [使用日誌](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-logging.html)。

   ```
   sam logs --stack-name sam-app
   ```

   日誌輸出如下：

   ```
   2025/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.552000 START RequestId: 70693159-7e94-4102-a2af-98a6343fb8fb Version: $LATEST
   2025/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.594000 2025-08-31T09:33:10.557Z 70693159-7e94-4102-a2af-98a6343fb8fb INFO {"_aws":{"Timestamp":1661938390556,"CloudWatchMetrics":[{"Namespace":"sam-app","Dimensions":[["service"]],"Metrics":[{"Name":"ColdStart","Unit":"Count"}]}]},"service":"helloWorld","ColdStart":1}
   2025/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.595000 2025-08-31T09:33:10.595Z 70693159-7e94-4102-a2af-98a6343fb8fb INFO {"level":"INFO","message":"This is an INFO log - sending HTTP 200 - hello world response","service":"helloWorld","timestamp":"2025-08-31T09:33:10.594Z"}
   2025/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.655000 2025-08-31T09:33:10.655Z 70693159-7e94-4102-a2af-98a6343fb8fb INFO {"_aws":{"Timestamp":1661938390655,"CloudWatchMetrics":[{"Namespace":"sam-app","Dimensions":[["service"]],"Metrics":[]}]},"service":"helloWorld"}
   2025/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.754000 END RequestId: 70693159-7e94-4102-a2af-98a6343fb8fb
   2025/01/31/[$LATEST]4d53e8d279824834a1ccd35511a4949c 2025-08-31T09:33:10.754000 REPORT RequestId: 70693159-7e94-4102-a2af-98a6343fb8fb Duration: 201.55 ms Billed Duration: 202 ms Memory Size: 128 MB Max Memory Used: 66 MB Init Duration: 252.42 ms
   XRAY TraceId: 1-630f2ad5-1de22b6d29a658a466e7ecf5 SegmentId: 567c116658fbf11a Sampled: true
   ```

1. 這是可透過網際網路存取的公有 API 端點。建議您在測試後刪除端點。

   ```
   sam delete
   ```

### 管理日誌保留
<a name="typescript-log-retention"></a>

當您刪除函數時，不會自動刪除日誌群組。若要避免無限期地儲存日誌，請刪除日誌群組，或設定保留期間，CloudWatch 會在該時間之後自動刪除日誌。若要設定日誌保留，請將下列項目新增至您的 AWS SAM 範本：

```
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
    # Omitting other properties
  
  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/aws/lambda/${HelloWorldFunction}"
      RetentionInDays: 7
```

## 使用 Powertools for AWS Lambda (TypeScript) 和 AWS CDK 進行結構化記錄
<a name="typescript-logging-cdk"></a>

請依照下列步驟，使用 下載、建置和部署範例 Hello World TypeScript 應用程式，搭配整合式 [Powertools for AWS Lambda (TypeScript)](https://docs.powertools.aws.dev/lambda-typescript) 模組 AWS CDK。此應用程式實作了基本 API 後端，並使用 Powertools 發送日誌、指標和追蹤。其包含 Amazon API Gateway 端點和 Lambda 函數。當您將 GET 請求傳送至 API Gateway 端點時，Lambda 函數會調用、使用內嵌指標格式將日誌和指標傳送至 CloudWatch，並將追蹤傳送至 AWS X-Ray。該函數會傳回 `hello world` 訊息。

**先決條件**

若要完成本節中的步驟，您必須執行下列各項：
+ Node.js 20 或更新版本
+ [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 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 [Logger 公用程式](https://docs.aws.amazon.com/powertools/typescript/latest/features/logger/)。

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

1. 開啟 **lib** 目錄。您應看到名稱為 **hello-world-stack.ts** 的檔案。在此目錄中建立兩個新檔案：**hello-world.function.ts** 和 **hello-world.ts**。

1. 開啟 **hello-world.function.ts**，並將下列程式碼新增至檔案。這是 Lambda 函數的程式碼。

   ```
   import { APIGatewayEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
   import { Logger } from '@aws-lambda-powertools/logger';
   const logger = new Logger();
     
   export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => {
     logger.info('This is an INFO log - sending HTTP 200 - hello world response');
     return {
       statusCode: 200,
       body: JSON.stringify({
         message: 'hello world',
       }),
     };
   };
   ```

1. 開啟 **hello-world.ts**，然後將下列程式碼新增至檔案。其中包含 [NodejsFunction 建構模組](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html)，它會建立 Lambda 函數、設定 Powertools 的環境變數，並將日誌保留設定為一週。另外也包括負責建立 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 { RetentionDays } from 'aws-cdk-lib/aws-logs';
   import { CfnOutput } from 'aws-cdk-lib';
     
   export class HelloWorld extends Construct {
     constructor(scope: Construct, id: string) {
       super(scope, id);
       const helloFunction = new NodejsFunction(this, 'function', {
         environment: {
           Powertools_SERVICE_NAME: 'helloWorld',
           LOG_LEVEL: 'INFO',
         },
         logRetention: RetentionDays.ONE_WEEK,
       });
       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 hello-world
   ```

1. 部署您的應用程式。

   ```
   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 日誌](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-logs.html)。如需詳細資訊，請參閱《AWS Serverless Application Model 開發人員指南》** 中的 [使用日誌](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-logging.html)。

   ```
   sam logs --stack-name HelloWorldStack
   ```

   日誌輸出如下：

   ```
   2025/01/31/[$LATEST]2ca67f180dcd4d3e88b5d68576740c8e 2025-08-31T14:48:37.047000 START RequestId: 19ad1007-ff67-40ce-9afe-0af0a9eb512c Version: $LATEST
   2025/01/31/[$LATEST]2ca67f180dcd4d3e88b5d68576740c8e 2025-08-31T14:48:37.050000 {
   "level": "INFO",
   "message": "This is an INFO log - sending HTTP 200 - hello world response",
   "service": "helloWorld",
   "timestamp": "2025-08-31T14:48:37.048Z",
   "xray_trace_id": "1-630f74c4-2b080cf77680a04f2362bcf2"
   }
   2025/01/31/[$LATEST]2ca67f180dcd4d3e88b5d68576740c8e 2025-08-31T14:48:37.082000 END RequestId: 19ad1007-ff67-40ce-9afe-0af0a9eb512c
   2025/01/31/[$LATEST]2ca67f180dcd4d3e88b5d68576740c8e 2025-08-31T14:48:37.082000 REPORT RequestId: 19ad1007-ff67-40ce-9afe-0af0a9eb512c Duration: 34.60 ms Billed Duration: 35 ms Memory Size: 128 MB Max Memory Used: 57 MB Init Duration: 173.48 ms
   ```

1. 這是可透過網際網路存取的公有 API 端點。建議您在測試後刪除端點。

   ```
   cdk destroy
   ```

## 在 Lambda 主控台檢視日誌
<a name="typescript-logging-console"></a>

您可以在調用 Lambda 函數之後，使用 Lambda 主控台來檢視日誌輸出。

如果可以從內嵌**程式碼**編輯器測試您的程式碼，您會在**執行結果**中找到日誌。使用主控台測試功能以調用函數時，您會在**詳細資訊**區段找到**日誌輸出**。

## 在 CloudWatch 主控台中檢視 記錄
<a name="typescript-logging-cwconsole"></a>

您可以使用 Amazon CloudWatch 主控台來檢視所有 Lambda 函數調用的日誌。

**若要在 CloudWatch 主控台上檢視日誌**

1. 在 CloudWatch 主控台上開啟[日誌群組頁面](https://console.aws.amazon.com/cloudwatch/home?#logs:)。

1. 選擇您的函數的日誌群組 (**/aws/lambda/*your-function-name***)。

1. 選擇日誌串流

每個日誌串流都會對應至[函式的執行個體](lambda-runtime-environment.md)。當您更新 Lambda 函數，以及建立其他執行個體以處理並行調用時，就會顯示日誌串流。若要尋找特定調用的日誌，建議您使用 檢測函數 AWS X-Ray。X-Ray 會在追蹤內記錄有關請求和日誌串流的詳細資訊。

# 在 中追蹤 TypeScript 程式碼 AWS Lambda
<a name="typescript-tracing"></a>

Lambda 與 整合 AWS X-Ray ，以協助您追蹤、偵錯和最佳化 Lambda 應用程式。您可以使用 X-Ray 來追蹤請求，因為它會周遊您應用程式中的資源，其中可能包含 Lambda 函數和其他 AWS 服務。

若要將追蹤資料傳送至 X-Ray，您可以使用以下三個 SDK 庫之一：
+ [AWS Distro for OpenTelemetry (ADOT)](https://aws.amazon.com/otel) – OpenTelemetry (OTel) SDK 的安全、生產就緒、 AWS支援的分發。
+ [AWS X-Ray 適用於 Node.js 的開發套件](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs.html) – 用於產生追蹤資料並將其傳送至 X-Ray 的開發套件。
+ [Powertools for AWS Lambda (TypeScript)](https://docs.aws.amazon.com/powertools/typescript/latest/) – 開發人員工具組，用於實作無伺服器最佳實務並提高開發人員速度。

每個 SDK 均提供將遙測資料傳送至 X-Ray 服務的方法。然後，您可以使用 X-Ray 來檢視、篩選應用程式的效能指標並獲得洞察，從而識別問題和進行最佳化的機會。

**重要**  
X-Ray 和 Powertools AWS Lambda SDKs是 提供的緊密整合檢測解決方案的一部分 AWS。ADOT Lambda Layers 是用於追蹤檢測之業界通用標準的一部分，這類檢測一般會收集更多資料，但可能不適用於所有使用案例。您可以使用任一解決方案在 X-Ray 中實作端對端追蹤。若要深入了解如何在兩者之間做選擇，請參閱[在 AWS Distro for OpenTelemetry 和 X-Ray SDK 之間進行選擇](https://docs.aws.amazon.com/xray/latest/devguide/xray-instrumenting-your-app.html#xray-instrumenting-choosing)。

**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>

請依照下列步驟，使用 搭配整合式 Powertools for (TypeScript) 模組下載、建置和部署範例 Hello World TypeScript 應用程式 AWS SAM。 [AWS Lambda TypeScript](https://docs.powertools.aws.dev/lambda-typescript) 此應用程式實作了基本 API 後端，並使用 Powertools 發送日誌、指標和追蹤。其包含 Amazon API Gateway 端點和 Lambda 函數。當您將 GET 請求傳送至 API Gateway 端點時，Lambda 函數會調用、使用內嵌指標格式將日誌和指標傳送至 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 may not have authorization defined, Is this okay?**，確保輸入 `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 追蹤](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 次請求和 5% 的額外請求。不能針對函數設定 X-Ray 取樣率。

## 使用 Powertools for AWS Lambda (TypeScript) 和 AWS CDK 進行追蹤
<a name="typescript-tracing-cdk"></a>

請依照下列步驟，使用 搭配整合式 Powertools for (TypeScript) 模組下載、建置和部署範例 Hello World TypeScript 應用程式 AWS CDK。 [AWS Lambda TypeScript](https://docs.powertools.aws.dev/lambda-typescript) 此應用程式實作了基本 API 後端，並使用 Powertools 發送日誌、指標和追蹤。其包含 Amazon API Gateway 端點和 Lambda 函數。當您將 GET 請求傳送至 API Gateway 端點時，Lambda 函數會調用、使用內嵌指標格式將日誌和指標傳送至 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**。

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**，然後將下列程式碼新增至檔案。其中包含 [NodejsFunction 建構模組](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html)，它會建立 Lambda 函數、設定 Powertools 的環境變數，並將日誌保留設定為一週。另外也包括負責建立 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 追蹤](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/zh_tw/lambda/latest/dg/images/sample-typescript-servicemap.png)
