

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

# 使用遙測 API 即時存取延伸功能的遙測資料
<a name="telemetry-api"></a>

遙測 API 可讓您的延伸項目直接從 Lambda 接收遙測資料。在函數初始化和調用期間，Lambda 會自動擷取遙測資料，包括日誌、平台指標和平台追蹤。遙測 API 使延伸項目可以近乎即時地從 Lambda 直接存取這些遙測資料。

在 Lambda 執行環境中，您可以讓 Lambda 延伸項目訂閱遙測串流。訂閱後，Lambda 會自動將所有遙測資料傳送至您的延伸項目。隨後，您便能靈活地處理、篩選資料，並將資料傳送至偏好的目的地，例如 Amazon Simple Storage Service (Amazon S3) 儲存貯體或第三方可觀測性工具提供者。

下圖顯示延伸 API 和遙測 API 如何從執行環境中將延伸項目連結至 Lambda。另外，執行期 API 也會將執行期和函數連接至 Lambda。

![連線至執行環境中處理序之延伸、遙測和執行時期 API。](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/telemetry-api-concept-diagram.png)


**重要**  
Lambda 遙測 API 優先於 Lambda 日誌 API。**雖然日誌 API 仍然正常運作，但我們建議您未來只使用遙測 API。**您可以使用遙測 API 或日誌 API 訂閱遙測串流的延伸項目。使用其中一個 API 進行訂閱後，若嘗試使用其他 API 進行任何訂閱，都會傳回錯誤。

**Lambda 受管執行個體結構描述版本需求**  
Lambda 受管執行個體僅支援遙測 API `2025-01-29` 的結構描述版本。訂閱受管執行個體函數的遙測串流時，**您必須在**訂閱請求`"schemaVersion": "2025-01-29"`中使用 。使用先前的結構描述版本會導致 Lambda 拒絕事件。  
`2025-01-29` 結構描述版本回溯相容，可與 Lambda 受管執行個體和 Lambda （預設） 函數搭配使用。我們建議將此版本用於所有新的延伸，以確保兩種部署模型的相容性。

延伸項目可使用遙測 API 來訂閱三個不同的遙測串流：
+ **平台遙測** – 日誌、指標和追蹤，描述與執行環境執行階段生命週期、延伸項目生命週期和函數調用相關的事件和錯誤。
+ **函數日誌** – Lambda 函數程式碼產生的自訂日誌。
+ **延伸項目日誌** - Lambda 延伸項目程式碼產生的自訂日誌。

**注意**  
Lambda 會將日誌和指標傳送到 CloudWatch，並將追蹤傳送至 X-Ray (如果您已啟動追蹤)，即使延伸項目有訂閱遙測串流也一樣。

**Topics**
+ [使用遙測 API 建立延伸項目](#telemetry-api-creating-extensions)
+ [註冊延伸項目](#telemetry-api-registration)
+ [建立遙測接聽程式](#telemetry-api-listener)
+ [指定目的地通訊協定](#telemetry-api-destination)
+ [設定記憶體使用量和緩衝](#telemetry-api-buffering)
+ [將訂閱請求傳送至遙測 API](#telemetry-api-subscription)
+ [輸入遙測 API 訊息](#telemetry-api-messages)
+ [Lambda 遙測 API 參考](telemetry-api-reference.md)
+ [Lambda 遙測 API `Event` 結構描述參考](telemetry-schema-reference.md)
+ [將 Lambda 遙測 API`Event` 物件轉換為 OpenTelemetry 跨度](telemetry-otel-spans.md)
+ [使用 Lambda Logs API](runtimes-logs-api.md)

## 使用遙測 API 建立延伸項目
<a name="telemetry-api-creating-extensions"></a>

Lambda 延伸項目會在執行環境中做為獨立的程序執行。延伸項目可以在函數調用完成後繼續執行。由於延伸項目為獨立的處理序，因此您可以使用與函數程式碼不同的語言來撰寫。我們建議您使用 Golang 或 Rust 等編譯語言編寫延伸項目。在這種情況下，延伸項目是獨立的二進位檔案，且與任何支援的執行階段相容。

下圖說明建立延伸項目的四步驟程序，讓延伸項目使用遙測 API 接收和處理遙測資料。

![註冊您的延伸項目、建立接聽程式、訂閱串流，然後取得遙測資料。](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/telemetry-api-creation-steps.png)


以下是各步驟的詳細說明：

1. 使用 [使用 Lambda 延伸 API 來建立延伸項目](runtimes-extensions-api.md) 註冊延伸項目。這會為您提供 `Lambda-Extension-Identifier`，接著需要在下列步驟中使用。如需有關如何註冊延伸項目的詳細資訊，請參閱：[註冊延伸項目](#telemetry-api-registration)。

1. 建立遙測接聽程式。這可以是基本的 HTTP 或 TCP 伺服器。Lambda 使用遙測接聽程式的 URI 來將遙測資料傳送至延伸項目。如需詳細資訊，請參閱[建立遙測接聽程式](#telemetry-api-listener)。

1. 使用遙測 API 中的訂閱 API，為您的延伸項目訂閱需要的遙測串流。在此步驟中，您需要遙測接聽程式的 URI。如需詳細資訊，請參閱[將訂閱請求傳送至遙測 API](#telemetry-api-subscription)。

1. 透過遙測接聽程式從 Lambda 取得遙測資料。您可以對這些資料執行任何自訂處理，例如將資料分派到 Amazon S3 或外部可檢視性服務。

**注意**  
Lambda 函數的執行環境可以在其[生命週期](runtimes-extensions-api.md#runtimes-extensions-api-lifecycle)中多次啟動和停止。一般來說，延伸項目程式碼會在函數調用期間執行，並且在關閉階段執行最多 2 秒。我們建議在遙測傳送到您的接聽程式時進行批次處理。然後，使用 `Invoke` 和 `Shutdown` 生命週期事件將每個批次傳送到所需的目的地。

## 註冊延伸項目
<a name="telemetry-api-registration"></a>

您必須先註冊 Lambda 延伸項目，才能訂閱遙測資料。註冊會在[延伸功能初始化階段](runtimes-extensions-api.md#runtimes-extensions-api-reg)進行。下列範例顯示註冊延伸項目的 HTTP 請求。

```
POST http://${AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension/register
 Lambda-Extension-Name: lambda_extension_name
{
    'events': [ 'INVOKE', 'SHUTDOWN']
}
```

如果請求成功，訂閱者會收到 HTTP 200 成功回應。回應標頭包含 `Lambda-Extension-Identifier`。回應內文包含函數的其他屬性。

```
HTTP/1.1 200 OK
Lambda-Extension-Identifier: a1b2c3d4-5678-90ab-cdef-EXAMPLE11111
{
    "functionName": "lambda_function",
    "functionVersion": "$LATEST",
    "handler": "lambda_handler",
    "accountId": "123456789012"
}
```

如需更多資訊，請參閱[Extensions API 參考](runtimes-extensions-api.md#runtimes-extensions-registration-api)。

## 建立遙測接聽程式
<a name="telemetry-api-listener"></a>

Lambda 延伸項目必須具有可處理遙測 API 所傳入請求的接聽程式。下列程式碼顯示以 Golang 實作的遙測接聽程式實作範例：

```
// Starts the server in a goroutine where the log events will be sent
func (s *TelemetryApiListener) Start() (string, error) {
	address := listenOnAddress()
	l.Info("[listener:Start] Starting on address", address)
	s.httpServer = &http.Server{Addr: address}
	http.HandleFunc("/", s.http_handler)
	go func() {
		err := s.httpServer.ListenAndServe()
		if err != http.ErrServerClosed {
			l.Error("[listener:goroutine] Unexpected stop on Http Server:", err)
			s.Shutdown()
		} else {
			l.Info("[listener:goroutine] Http Server closed:", err)
		}
	}()
	return fmt.Sprintf("http://%s/", address), nil
}

// http_handler handles the requests coming from the Telemetry API.
// Everytime Telemetry API sends log events, this function will read them from the response body
// and put into a synchronous queue to be dispatched later.
// Logging or printing besides the error cases below is not recommended if you have subscribed to
// receive extension logs. Otherwise, logging here will cause Telemetry API to send new logs for
// the printed lines which may create an infinite loop.
func (s *TelemetryApiListener) http_handler(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		l.Error("[listener:http_handler] Error reading body:", err)
		return
	}

	// Parse and put the log messages into the queue
	var slice []interface{}
	_ = json.Unmarshal(body, &slice)

	for _, el := range slice {
		s.LogEventsQueue.Put(el)
	}

	l.Info("[listener:http_handler] logEvents received:", len(slice), " LogEventsQueue length:", s.LogEventsQueue.Len())
	slice = nil
}
```

## 指定目的地通訊協定
<a name="telemetry-api-destination"></a>

使用遙測 API 訂閱以接收遙測資料時，除了目的地 URI 之外，您還可以指定目的地通訊協定：

```
{
    "destination": {
        "protocol": "HTTP",
        "URI": "http://sandbox.localdomain:8080"
    }
}
```

Lambda 接受兩種通訊協定用於接收遙測資料：
+ **HTTP (建議)** - Lambda 會以 JSON 格式的記錄陣列將遙測資料傳遞至本機 HTTP 端點 (`http://sandbox.localdomain:${PORT}/${PATH}`)。`$PATH` 為選用參數。Lambda 僅支援 HTTP，不支援 HTTPS。Lambda 會透過 POST 請求傳遞遙測資料。
+ **TCP** - Lambda 使用[以換行分隔的 JSON (NDJSON) 格式](https://github.com/ndjson/ndjson-spec)將遙測資料傳遞至 TCP 連接埠。

**注意**  
強烈建議使用 HTTP，而不是使用 TCP。若使用 TCP，Lambda 平台無法確認何時將遙測資料傳遞至應用程式層。因此，如果您的延伸項目損毀，遙測資料可能會遺失。HTTP 沒有此限制。

訂閱以接收遙測資料之前，需先建立本機 HTTP 接聽程式或 TCP 連接埠。在設定期間，請注意下列事項：
+ Lambda 只會將遙測資料傳送至執行環境內的目的地。
+ 如果沒有接聽程式，或者如果 POST 請求遇到錯誤，則 Lambda 會重新嘗試傳送遙測資料 (使用回詢)。如果遙測接聽程式損毀，會在 Lambda 重新啟動執行環境之後繼續接收遙測資料。
+ Lambda 保留連接埠 9001。沒有其他連接埠編號限制或建議。

## 設定記憶體使用量和緩衝
<a name="telemetry-api-buffering"></a>

隨著訂閱用戶數量增加，執行環境的記憶體使用量會線性增加。訂閱會耗用記憶體資源，因為每個訂閱都會開啟新的記憶體緩衝區來存放遙測資料。緩衝區記憶體用量會計入執行環境中的整體記憶體耗用量。

透過遙測 API 來訂閱以接收遙測資料時，您可以選擇先緩衝遙測資料再批次傳遞給訂閱用戶。若要最佳化記憶體用量，您可以指定緩衝組態：

```
{
    "buffering": {
        "maxBytes": 256*1024,
        "maxItems": 1000,
        "timeoutMs": 100
    }
}
```


| 參數 | Description | 預設值和限制 | 
| --- | --- | --- | 
| `maxBytes` | 記憶體中要緩衝的遙測資料量上限 (位元組)。 | 預設：262,144<br />下限：262,144<br />上限：1,048,576 | 
| `maxItems` | 記憶體中要緩衝的事件數目上限。 | 預設：10,000<br />下限：1,000<br />上限：10,000 | 
| `timeoutMs` | 緩衝一個批次的時間上限 (毫秒)。 | 預設：1,000<br />下限：25<br />上限：30,000 | 

當設定緩衝時，請記住以下幾點：
+ 如果有任何輸入串流關閉，則 Lambda 會排清日誌。例如，如果執行期損毀，就可能會發生這種情況。
+ 每個訂閱用戶可以在訂閱請求中自訂其緩衝組態。
+ 決定讀取資料的緩衝區大小時，請預期接收的有效負載大小為 `2 * maxBytes + metadataBytes` (其中 `maxBytes` 是緩衝設定的元件)。若要評估要考量的 `metadataBytes` 數量，請檢閱下列中繼資料。Lambda 會將類似的中繼資料新增至每筆記錄：

  ```
  {
     "time": "2022-08-20T12:31:32.123Z",
     "type": "function",
     "record": "Hello World"
  }
  ```
+ 如果訂閱者處理傳入遙測資料的速度不夠快，或是函數程式碼產生了極大量的日誌，Lambda 可能會捨棄記錄，以確保記憶體使用率維持在限制範圍內。發生這種情況時，Lambda 會傳送 `platform.logsDropped` 事件。

## 將訂閱請求傳送至遙測 API
<a name="telemetry-api-subscription"></a>

Lambda 延伸項目可透過將訂閱請求傳送至遙測 API 來訂閱以接收遙測資料。訂閱請求應包含您希望延伸項目訂閱的事件類型相關資訊。此外，請求可以包含[傳遞目的地資訊](#telemetry-api-destination)和[緩衝組態](#telemetry-api-buffering)。

傳送訂閱請求之前，您必須有延伸功能 ID (`Lambda-Extension-Identifier`)。[向延伸 API 註冊您的延伸項目](#telemetry-api-registration)時，您可從 API 回應中取得延伸項目 ID。

訂閱會在[延伸項目初始化階段](runtimes-extensions-api.md#runtimes-extensions-api-reg)進行。下列範例顯示訂閱全部三個遙測串流的 HTTP 請求：平台遙測、函數日誌和延伸項目日誌。

```
PUT http://${AWS_LAMBDA_RUNTIME_API}/2022-07-01/telemetry HTTP/1.1
{
   "schemaVersion": "2025-01-29",
   "types": [
        "platform",
        "function",
        "extension"
   ],
   "buffering": {
        "maxItems": 1000,
        "maxBytes": 256*1024,
        "timeoutMs": 100
   },
   "destination": {
        "protocol": "HTTP",
        "URI": "http://sandbox.localdomain:8080"
   }
}
```

如果請求成功，訂閱者會收到 HTTP 200 成功回應。

```
HTTP/1.1 200 OK
"OK"
```

## 輸入遙測 API 訊息
<a name="telemetry-api-messages"></a>

使用遙測 API 訂閱之後，延伸項目會自動透過 POST 請求開始接收來自 Lambda 的遙測資料。每個 POST 請求主體包含 `Event` 對象的數組。每個 `Event` 項目都有以下結構描述：

```
{
   time: String,
   type: String,
   record: Object
}
```
+ `time` 屬性定義了 Lambda 平台產生事件的時間。這與事件實際發生的時間不同。`time` 的字串值是 ISO 8601 格式的時間戳記。
+ `type` 屬性定義了事件類型。下表說明所有可能的值。
+ `record` 屬性定義了包含遙測資料的 JSON 物件。此 JSON 物件的結構描述取決於 `type`。

**使用並行調用的事件排序**  
對於 [Lambda 受管執行個體](lambda-managed-instances.md)，多個函數調用可以在相同的執行環境中同時執行。在此情況下，不同並行調用之間無法保證 `platform.start`和 `platform.report`事件的順序。延伸模組必須處理平行執行的多個調用的事件，不應採用循序排序。  
為了將事件適當地歸因於特定調用，延伸模組應使用這些平台事件中存在`requestId`的欄位。每個調用都有唯一的請求 ID，該請求 ID 在該調用的所有事件中都保持一致，允許延伸項目即使在不按順序到達時也能正確地關聯事件。

下表摘要說明 `Event` 物件的所有類型，以及每個事件類型之[遙測 API `Event` 結構描述參考](telemetry-schema-reference.md)的連結。


| Category | 事件類型 | Description | 事件記錄結構描述 | 
| --- | --- | --- | --- | 
| 平台事件 | `platform.initStart` | 函數初始化已開始。 | [`platform.initStart`](telemetry-schema-reference.md#platform-initStart) 結構描述 | 
| 平台事件 | `platform.initRuntimeDone` | 函數初始化已完成。 | [`platform.initRuntimeDone`](telemetry-schema-reference.md#platform-initRuntimeDone) 結構描述 | 
| 平台事件 | `platform.initReport` | 函數初始化報告。 | [`platform.initReport`](telemetry-schema-reference.md#platform-initReport) 結構描述 | 
| 平台事件 | `platform.start` | 函數調用已開始。 | [`platform.start`](telemetry-schema-reference.md#platform-start) 結構描述 | 
| 平台事件 | `platform.runtimeDone` | 執行階段已完成處理的事件，結果為成功或失敗。 | [`platform.runtimeDone`](telemetry-schema-reference.md#platform-runtimeDone) 結構描述 | 
| 平台事件 | `platform.report` | 函數調用報告。 | [`platform.report`](telemetry-schema-reference.md#platform-report) 結構描述 | 
| 平台事件 | `platform.restoreStart` | 執行時間還原已開始。 | [`platform.restoreStart`](telemetry-schema-reference.md#platform-restoreStart) 結構描述 | 
| 平台事件 | `platform.restoreRuntimeDone` | 執行時間還原已完成。 | [`platform.restoreRuntimeDone`](telemetry-schema-reference.md#platform-restoreRuntimeDone) 結構描述 | 
| 平台事件 | `platform.restoreReport` | 執行時間還原報告。 | [`platform.restoreReport`](telemetry-schema-reference.md#platform-restoreReport) 結構描述 | 
| 平台事件 | `platform.telemetrySubscription` | 延伸項目已訂閱遙測 API。 | [`platform.telemetrySubscription`](telemetry-schema-reference.md#platform-telemetrySubscription) 結構描述 | 
| 平台事件 | `platform.logsDropped` | Lambda 已捨棄日誌項目。 | [`platform.logsDropped`](telemetry-schema-reference.md#platform-logsDropped) 結構描述 | 
| 函數日誌 | `function` | 函數程式碼的日誌行。 | [`function`](telemetry-schema-reference.md#telemetry-api-function) 結構描述 | 
| 延伸項目日誌 | `extension` | 延伸項目程式碼的日誌行。 | [`extension`](telemetry-schema-reference.md#telemetry-api-extension) 結構描述 | 