

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

# 設定 HTTP 端點可見性
<a name="Application-Signals-EndpointVisibility"></a>

此頁面提供 Application Signals 客戶指引，這些客戶希望看到其 HTTP 服務操作以特定端點名稱分隔，但改為看到多個端點分組為相同的指標。根據預設，Application Signals 會將指標維度截斷為 HTTP `Operation` 服務的第一個 URL 路徑區段 （例如， `/api/v1/users`變成 `GET /api`)，以保留低基數指標。因此，使用者可能會發現具有多個端點共享相同字首的服務，對個別端點的運作狀態可見性有限。您可以依照下列步驟，將服務操作端點設定為所需的精細程度。

**重要**  
修改端點可見性是一項重大變更，因為它會影響服務操作的 Application Signals 指標維度。請記得相應地更新您的 SLO 閾值、警示和/或儀表板。

## AWS Distro for OpenTelemetry (ADOT) 解決方案
<a name="Application-Signals-EndpointVisibility-ADOT"></a>

對於使用 AWS Distro for OpenTelemetry (ADOT) 的客戶，請使用以逗號分隔的 HTTP 服務 URL 路徑範本清單來設定`OTEL_AWS_HTTP_OPERATION_PATHS`環境變數：

```
export OTEL_AWS_HTTP_OPERATION_PATHS="/path/to/endpoint, /another/{placeholder}/endpoint"
```

此變數會針對 HTTP 伺服器跨度`url.path`屬性使用最長相符字首，以判斷操作名稱。萬用字元模式符合任何單一 URL 區段，並以 `{placeholder}`、 `:placeholder`或 表示`*`。設定變數之後，請重新啟動應用程式，讓新的端點群組生效。

ADOT for Java、Python、Node.js 和 .NET 支援此變數。

**範例**

請考慮接收下列流量的 API 服務：

```
GET  /api/users
GET  /api/users/42
GET  /api/users/42/orders
POST /api/users/99/orders
POST /api/users/42/orders
GET  /api/users/42/orders/7/items
GET  /api/products
```

根據預設，Application Signals 會將所有這些指標分組為 `GET /api` `POST /api`或服務指標，因此無法區分端點之間的效能。

若要修正此問題，請使用所需的路徑範本設定 環境變數：

```
export OTEL_AWS_HTTP_OPERATION_PATHS="/api/users/{userId}/orders/{orderId}/items, /api/users/{userId}/orders, /api/users/{userId}, /api/users, /api/products"
```

在此組態中，Application Signals 會顯示不同的操作。多個請求可以解析為相同的設定範本：


**端點可見性組態結果範例**  

| 傳入的請求 | 預設操作 | 使用組態 | 
| --- | --- | --- | 
| GET /api/users | GET /api | GET /api/users | 
| GET /api/users/42 | GET /api | GET /api/users/{userId} | 
| GET /api/users/42/orders | GET /api | GET /api/users/{userId}/orders | 
| POST /api/users/99/orders | POST /api | POST /api/users/{userId}/orders | 
| POST /api/users/42/orders | POST /api | POST /api/users/{userId}/orders | 
| GET /api/users/42/orders/7/items | GET /api | GET /api/users/{userId}/orders/{orderId}/items | 
| GET /api/products | GET /api | GET /api/products | 

## 原生 OpenTelemetry 解決方案
<a name="Application-Signals-EndpointVisibility-NativeOTel"></a>

如果您使用的是原生 OpenTelemetry SDK （不含 ADOT)，您可以使用 OpenTelemetry Collector 中的轉換處理器覆寫範圍名稱，或直接在應用程式程式碼中覆寫範圍名稱。

**注意**  
您必須使用 OTLP 匯出工具設定收集器，以保留 OpenTelemetry 跨度名稱，以便 CloudWatch 可以剖析 Application Signals 操作名稱。如需詳細資訊，請參閱[將 OTLP 資料傳送至 CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-OTLPSimplesetup.html)。

**選項 1 （建議）：收集器端轉換**

使用[轉換處理器](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/transformprocessor)根據 URL 模式設定跨度名稱。轉換處理器使用 OTTL (OpenTelemetry 轉換語言），可以直接修改跨度`name`欄位。

從淺到深排序規則 – 陳述式會循序執行，因此清單中稍後更具體的比對會覆寫先前設定的一般比對。在下列範例中，跨度屬性的值`url.path`會相符，而產生的跨度名稱會設定為請求方法，後面接著所需的 URL 模式。

```
processors:
  transform/operation_names:
    trace_statements:
      - context: span
        conditions:
          - IsMatch(attributes["url.path"], "^/api/contests(/|$)")
        statements:
          - set(name, Concat([attributes["http.request.method"], "/api/contests"], " "))

      - context: span
        conditions:
          - IsMatch(attributes["url.path"], "^/api/contests/[^/]+$")
        statements:
          - set(name, Concat([attributes["http.request.method"], "/api/contests/{id}"], " "))

      - context: span
        conditions:
          - IsMatch(attributes["url.path"], "^/api/contests/[^/]+/leaderboard(/|$)")
        statements:
          - set(name, Concat([attributes["http.request.method"], "/api/contests/{id}/leaderboard"], " "))

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [resourcedetection, transform/operation_names, batch]
      exporters: [otlphttp/xray]
```

**選項 2：在應用程式程式碼中設定跨度名稱**

您可以使用 OpenTelemetry API，手動設定應用程式程式碼中伺服器跨度的範圍名稱。將`{HTTP_METHOD} {route_template}`路由範本使用參數化預留位置的名稱設定為 。請注意，這是硬式編碼的備用選項，您必須手動更新每個 HTTP 請求處理常式中的跨度名稱，才能套用此變更。

**Java**

```
import io.opentelemetry.api.trace.Span;

// Inside your request handler
Span.current().updateName("GET /api/contests/{id}/leaderboard");
```

**Python**

```
from opentelemetry import trace

# Inside your request handler
span = trace.get_current_span()
span.update_name("GET /api/contests/{id}/leaderboard")
```

**Go**

```
import "go.opentelemetry.io/otel/trace"

// Inside your request handler
span := trace.SpanFromContext(ctx)
span.SetName("GET /api/contests/{id}/leaderboard")
```

**Node.js**

```
import { trace } from '@opentelemetry/api';

// Inside your request handler
const span = trace.getActiveSpan();
if (span) {
  span.updateName('GET /api/contests/{id}/leaderboard');
}
```