> Source: https://www.ymotongpoo.com/works/otel-specs-ja/semconv/faas/aws-lambda/


# AWS Lambdaの計装

**ステータス**: [Development][DocumentStatus]

この文書では、AWS Lambdaのリクエストハンドラーを計装する際にセマンティック規約を適用する方法を定義します。AWS Lambdaは、[FaaS][faas]の規約に大きく従いつつ、ハンドラーがHTTPリクエストを処理する場合は[HTTP](/works/otel-specs-ja/semconv/http/http-spans/)の規約も適用されます。

Lambda関数にはさまざまなトリガーがあり、この文書は時間の経過とともにすべての使用例を対象とするよう拡張されます。

## すべてのトリガー

すべてのイベントについて、以下で特に述べない限り、関数呼び出しに対応する`SERVER`種別のスパンが作成されるべきです（SHOULD）。

次の属性が設定されるべきです（SHOULD）。

- [`faas.invocation_id`][faas] - AWS Request IDの値。これは、Lambdaの`Context`上のアクセサから常に取得できます。
- [`cloud.account.id`][cloud] - 言語によっては、これはLambdaの`Context`上のアクセサから取得できます。それ以外の場合は、ARNを`:`で分割して5番目の項目として解析できます。

<!-- semconv span.aws.lambda.server -->
<!-- NOTE: THIS TEXT IS AUTOGENERATED. DO NOT EDIT BY HAND. -->
<!-- see templates/registry/markdown/snippet.md.j2 -->
<!-- prettier-ignore-start -->

**Status:** ![Development](https://img.shields.io/badge/-development-blue)

このスパンは、AWS Lambdaの呼び出しを表します。

[`faas`リソース][faasres]、[トレース][faas]の規約、および[クラウドリソースの規約][cloud]の他の属性も設定することを検討してください。

**スパン名**は、特に述べない限り、Lambdaの`Context`から取得した関数名に設定しなければなりません（MUST）。

**スパン種別**は、特に述べない限り、`SERVER`でなければなりません（MUST）。

**スパンステータス**は[エラーの記録](/works/otel-specs-ja/semconv/general/recording-errors/)文書に従うべきです（SHOULD）。

**Attributes:**

| Key | Stability | [Requirement Level](/works/otel-specs-ja/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values |
| --- | --- | --- | --- | --- | --- |
| [`aws.lambda.invoked_arn`](https://opentelemetry.io/docs/specs/semconv/registry/attributes/aws/) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` | string | 関数に渡された`Context`上で提供される、呼び出し元の完全なARN（`/runtime/invocation/next`が該当する場合の`Lambda-Runtime-Invoked-Function-Arn`ヘッダー）。[1] | `arn:aws:lambda:us-east-1:123456:function:myfunction:myalias` |
| [`aws.lambda.resource_mapping.id`](https://opentelemetry.io/docs/specs/semconv/registry/attributes/aws/) | ![Development](https://img.shields.io/badge/-development-blue) | `Recommended` | string | [AWS Lambda EventSource Mapping](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html)のUUID。イベントソースはLambda関数にマッピングされます。その内容はLambdaによって読み取られ、関数をトリガーするために使用されます。これはLambdaの実行コンテキストやLambdaランタイム環境では利用できません。これは、そのUUIDが存在する場合に各言語のAWS SDKによって設定されます。これに関連する操作には、Create/Delete/Get/List/Update EventSourceMappingなどがあります。 | `587ad24b-03b9-4413-8202-bbd56b36e5b7` |

**[1] `aws.lambda.invoked_arn`:** エイリアスが関わる場合、これは`cloud.resource_id`と異なる場合があります。

<!-- prettier-ignore-end -->
<!-- END AUTOGENERATED TEXT -->
<!-- endsemconv -->

[faas]: /works/otel-specs-ja/semconv/faas/faas-spans/ "FaaSトレースの規約"
[faasres]: https://opentelemetry.io/docs/specs/semconv/resource/faas/ "FaaSリソースの規約"
[cloud]: https://opentelemetry.io/docs/specs/semconv/resource/cloud/ "クラウドリソースの規約"

### AWS X-Rayのアクティブトレーシングに関する考慮事項

Lambdaで[AWS X-Rayのアクティブトレーシング](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html)が有効になっている場合、ランタイムは設定済みのサンプリングレートに基づいて自動的にスパンを生成し、`_X_AMZN_TRACE_ID`環境変数（およびJava Lambda関数の場合は`com.amazonaws.xray.traceHeader`システムプロパティ）を介してスパンコンテキストを伝搬します。
このスパンコンテキストは、[X-Ray Tracing Header Format](https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader)を使ってエンコードされます。

ユーザーは、このX-Rayの「アクティブトレーシング」スパンコンテキストの伝搬を優先するよう[プロパゲーターを設定](#xray-lambdaプロパゲーターの設定)できなければなりません（MUST）。
（参考: OpenTelemetryがAWS X-Rayへのスパン報告用に設定されている場合、トレースを正しくリンクさせるためにこれを有効にすることをおそらく望むでしょう。）

#### `xray-lambda`プロパゲーターの機能

AWS Lambdaの計装を持つSDKは、X-Rayプロパゲーターに加えて、`OTEL_PROPAGATORS`環境変数の設定で`xray-lambda`として[設定できる](#xray-lambdaプロパゲーターの設定)追加のプロパゲーターを提供すべきです（SHOULD）。
このプロパゲーターは、`OTEL_PROPAGATORS`リスト内の`xray`プロパゲーターを置き換えることが期待されています。このプロパゲーターの挙動は、以下の疑似コードで説明されています。

```
extract(context, carrier) {
    xrayContext = xrayPropagator.extract(context, carrier)

    // To avoid potential issues when extracting with an active span context (such as with a span link),
    // the `xray-lambda` propagator SHOULD check if the provided context already has an active span context.
    // If found, the propagator SHOULD just return the extract result of the `xray` propagator.
    if (Span.fromContext(context).getSpanContext().isValid())
      return xrayContext

    // If xray-lambda environment variable not set, return the xray extract result.
    traceHeader = getEnvironment("_X_AMZN_TRACE_ID")
    if (isEmptyOrNull(traceHeader))
      return xrayContext

    // Apply the xray propagator using the span context contained in the xray-lambda environment variable.
    return xrayPropagator.extract(xrayContext, ["X-Amzn-Trace-Id": traceHeader])
}
```

*注記:* Java実装では、システムプロパティが空でない場合、環境変数の代わりに`com.amazonaws.xray.traceHeader`というキーのシステムプロパティの値を使用すべきです（should）。

#### `xray-lambda`プロパゲーターの設定

AWS LambdaからAWS X-Rayへ**スパンを報告する場合**、`xray-lambda`プロパゲーターは`OTEL_PROPAGATORS`の設定内で`xray`プロパゲーターを置き換えるべきです（SHOULD）。両方を含めると、`xray-lambda`が正しく機能しなくなります。

AWS X-Rayへスパンを報告する場合の有効な設定例。

- `OTEL_PROPAGATORS=tracecontext,baggage,xray-lambda`

無効な設定例。

- `OTEL_PROPAGATORS=tracecontext,baggage,xray,xray-lambda`
- `OTEL_PROPAGATORS=tracecontext,baggage,xray-lambda,xray`

**OpenTelemetryがAWS X-Ray以外の別のシステムにトレースを報告している場合**、ユーザーは`xray-lambda`を使用すべきではありません（SHOULD NOT）。使用すると報告されるトレースが壊れてしまいます。

OpenTelemetryがAWS X-Ray以外の別のシステムにトレースを報告している場合の有効な設定例。

- `OTEL_PROPAGATORS=tracecontext,baggage,xray`

## API Gateway

API Gatewayを使うと、ユーザーはHTTPリクエストへの応答としてLambda関数をトリガーできます。これは、元のHTTPリクエストに関する情報がLambda関数に渡される純粋なプロキシとして設定することも、REST APIの設定として、デシリアライズされたボディのペイロードのみが利用可能になるように設定することもできます。APIゲートウェイがLambda関数へのプロキシとして設定されている場合、計装されたリクエストハンドラーは、API Gateway Proxy Request Eventの形式でHTTPリクエストに関するすべての情報にアクセスできます。

Lambdaのスパン名と[`http.route`スパン属性](/works/otel-specs-ja/semconv/http/http-spans/#httpサーバースパン)は、プロキシリクエストイベントの[resourceプロパティ][resource property]に設定されるべきです（SHOULD）。これは、関数名の代わりに、ユーザーが設定したHTTPルートに対応します。

[`faas.trigger`][faas]は`http`に設定しなければなりません（MUST）。[HTTP属性](/works/otel-specs-ja/semconv/http/http-spans/)は、プロキシリクエストによって開始されたLambdaイベント内で利用可能な情報に基づいて設定されるべきです（SHOULD）。`http.scheme`は、Lambdaイベント内の`x-forwarded-proto`ヘッダーとして利用可能です。詳細は、[入力イベント形式][input event format]を参照してください。

[resource property]: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
[input event format]: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format

## SQS

Amazon Simple Queue Service（SQS）は、メッセージのバッチでLambda関数をトリガーするメッセージキューです。
そのため、バッチ全体の処理と個々のメッセージの処理の両方を考慮します。関数呼び出しのスパンは、メッセージのバッチであるSQSイベントに対応しなければなりません（MUST）。各メッセージについて、そのSQSメッセージの処理に対応する追加のスパンが作成されるべきです（SHOULD）。メッセージの処理はLambdaフレームワークではなくユーザーのビジネスロジックの内部で行われるため、コード変更を伴わない自動計装の仕組みでは、個々のメッセージの処理を計装できないことが多いです。計装は、ユーザーコード内でメッセージ処理スパンを作成するためのユーティリティを提供すべきです（SHOULD）。

両方の種類のSQSスパンについて、スパン種別は`CONSUMER`であるべきです（SHOULD）。

### SQSイベント

SQSイベントスパンについて、イベント内のすべてのメッセージが同じイベントソースを持つ場合、スパンの名前は`<event source> process`でなければなりません（MUST）。バッチ内に複数のソースがある場合、名前は`multiple_sources process`でなければなりません（MUST）。親は、関数呼び出しに対応する`SERVER`スパンであるべきです（SHOULD）。

イベント内のすべてのメッセージについて、（ユーザーが提供するメッセージ属性ではなく）[メッセージシステム属性][message system attributes]で`AWSTraceHeader`キーを確認すべきです（SHOULD）。存在する場合、その属性の値から[AWS X-Ray Propagator](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.59.0/specification/context/api-propagators.md)を使ってOpenTelemetryの`Context`を解析し、スパンへのリンクとして追加すべきです（SHOULD）。つまり、スパンはバッチ内のメッセージ数と同じ数のリンクを持つ場合があります。
詳細は[互換性](https://opentelemetry.io/docs/specs/semconv/non-normative/compatibility/aws/#context-propagation)を参照してください。

- [`faas.trigger`][faas]は`pubsub`に設定しなければなりません（MUST）。
- [`messaging.operation.type`](/works/otel-specs-ja/semconv/messaging/messaging-spans/#messaging-spans)は`process`に設定しなければなりません（MUST）。
- [`messaging.system`](/works/otel-specs-ja/semconv/messaging/messaging-spans/#messaging-spans)は`aws_sqs`に設定しなければなりません（MUST）。

### SQSメッセージ

SQSメッセージスパンについて、名前は`<event source> process`でなければなりません（MUST）。親は、SQSイベントに対応する`CONSUMER`スパンでなければなりません（MUST）。（ユーザーが提供するメッセージ属性ではなく）[メッセージシステム属性][message system attributes]で`AWSTraceHeader`キーを確認すべきです（SHOULD）。存在する場合、その属性の値から[AWS X-Ray Propagator](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.59.0/specification/context/api-propagators.md)を使ってOpenTelemetryの`Context`を解析し、スパンへのリンクとして追加すべきです（SHOULD）。
詳細は[互換性](https://opentelemetry.io/docs/specs/semconv/non-normative/compatibility/aws/#context-propagation)を参照してください。

- [`faas.trigger`][faas]は`pubsub`に設定しなければなりません（MUST）。
- [`messaging.operation.type`](/works/otel-specs-ja/semconv/messaging/messaging-spans/#messaging-spans)は`process`に設定しなければなりません（MUST）。
- [`messaging.system`](/works/otel-specs-ja/semconv/messaging/messaging-spans/#messaging-spans)は`aws_sqs`に設定しなければなりません（MUST）。

[メッセージングスパン](/works/otel-specs-ja/semconv/messaging/messaging-spans/#messaging-spans)向けに定義されているその他の属性は、SQSメッセージイベント内で利用可能な情報に基づいて設定されるべきです（SHOULD）。

`AWSTraceHeader`は、他のソースとの競合を避けるため、SQS計装で`Context`を伝搬するための唯一のサポートされた仕組みであることに注意してください。特に、（システムではなく）ユーザーが提供するメッセージ属性はサポートされていません。リンクされたコンテキストは、常にメッセージの発生元となった`SQS.SendMessage`リクエストのHTTPヘッダーとして送信されていることが期待されます。これはLambda計装の機能ではなく、AWS SDK計装の機能です。

`AWSTraceHeader`を使用することで、たとえばS3 -> SNS -> SQS -> Lambdaというフローのように、SQSを介してLambdaに統合されうるAWSサービス間で伝搬が機能することが保証されます。`AWSTraceHeader`はコンテキストを伝搬する手段の一つに過ぎず、特定のオブザーバビリティバックエンドに紐づいたものではありません。特に、これを使用することはAWS X-Rayの使用を意味しません。どのオブザーバビリティバックエンドでも、この伝搬機構を使って完全に機能します。

[message system attributes]: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-metadata.html#sqs-message-system-attributes

## 例

### API Gatewayリクエストプロキシ（Lambdaトレーシング パッシブ）

プロセスCが、Lambda関数Fのために設定されたパス`/pets/{petId}`のAPI Gatewayエンドポイントに、HTTPリクエストを送信する場合を考えます。

```
Process C: | Span Client        |
--
Function F:    | Span Function |
```

| Field or Attribute | `Span Client` | `Span Function` |
| --- | --- | --- |
| Span name | `HTTP GET` | `/pets/{petId}` |
| Parent | | Span Client |
| SpanKind | `CLIENT` | `SERVER` |
| Status | `Ok` | `Ok` |
| `faas.invocation_id` | | `79104EXAMPLEB723` |
| `faas.trigger` | | `http` |
| `cloud.account.id` | | `12345678912` |
| `server.address` | `foo.execute-api.us-east-1.amazonaws.com` | |
| `server.port` | `413` | |
| `http.request.method` | `GET` | `GET` |
| `user_agent.original` | `okhttp 3.0` | `okhttp 3.0` |
| `url.scheme` | | `https` |
| `url.path` | | `/pets/10` |
| `http.route` | | `/pets/{petId}` |
| `http.response.status_code` | `200` | `200` |

### API Gatewayリクエストプロキシ（Lambdaトレーシング アクティブ）

Lambdaのアクティブトレーシングとは、API Gatewayのスパン`Span APIGW`とLambdaランタイムの呼び出しスパン`Span Lambda`が、（計装ではなく）インフラストラクチャによってAWS X-Rayにエクスポートされることを意味します。上記のすべての属性は同じですが、この場合、`APIGW`の親は`Span Client`であり、`Span Function`の親は`Span Lambda`である点が異なります。つまり、階層は次のようになります。

```
Span Client --> Span APIGW --> Span Lambda --> Span Function
```

### SQS（Lambdaトレーシング パッシブ）

プロセスPが、SQS上のキューQに2つのメッセージを送信し、Lambda関数Fが、その両方を1つのバッチで処理する（Span ProcBatch）とともに、各メッセージに対して個別に処理スパンを生成する（Span Proc1とSpan Proc2）場合を考えます。

```
Process P: | Span Prod1 | Span Prod2 |
--
Function F:                      | Span ProcBatch |
                                        | Span Proc1 |
                                               | Span Proc2 |
```

| Field or Attribute | Span Prod1 | Span Prod2 | Span ProcBatch | Span Proc1 | Span Proc2 |
| --- | --- | --- | --- | --- | --- |
| Span name | `send Q` | `send Q` | `process Q` | `process Q` | `process Q` |
| Parent | | | | Span ProcBatch | Span ProcBatch |
| Links | | | | Span Prod1 | Span Prod2 |
| SpanKind | `PRODUCER` | `PRODUCER` | `CONSUMER` | `CONSUMER` | `CONSUMER` |
| Status | `Ok` | `Ok` | `Ok` | `Ok` | `Ok` |
| `messaging.system` | `aws_sqs` | `aws_sqs` | `aws_sqs` | `aws_sqs` | `aws_sqs` |
| `messaging.destination.name` | `Q` | `Q` | `Q` | `Q` | `Q` |
| `messaging.operation.name` | `send` | `send` | `process` | `process` | `process` |
| `messaging.operation.type` | `publish` | `publish` | `process` | `process` | `process` |
| `messaging.message.id` | | | | `"a1"` | `"a2"` |

Span Prod1とSpan Prod2が異なるキューに送信された場合、Span ProcBatchは複数のキューに対応することになるため、`messaging.destination.name`は設定されないことに注意してください。

上記の`Span Proc1`と`Span Proc2`を作成するには、ユーザーコードの変更が必要です。Javaでは、これらを有効にするために、ユーザーはLambdaの標準の`RequestHandler`ではなく[TracingSqsMessageHandler][]を継承します。そうしなければ、これら2つのスパンは存在しません。

[TracingSqsMessageHandler]: https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/v1.0.1/instrumentation/aws-lambda-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambda/v1_0/TracingSqsMessageHandler.java

### SQS（Lambdaトレーシング アクティブ）

Lambdaのアクティブトレーシングとは、Lambdaランタイムの呼び出しスパン`Span Lambda`が、（計装ではなく）インフラストラクチャによってX-Rayにエクスポートされることを意味します。この場合、`Span ProcBatch`の親が`Span Lambda`になる点を除いて、上記のすべてが同じです。つまり、階層は次のようになります。

```
Span Lambda --> Span ProcBatch --> Span Proc1 (links to Span Prod1 and Span Prod2)
                               \-> Span Proc2 (links to Span Prod1 and Span Prod2)
```

## リソース検出器

AWS Lambdaのリソース情報は、ランタイムが提供する[環境変数][environment variables]として利用可能です。

- [`cloud.provider`][cloud]は`aws`に設定しなければなりません（MUST）。
- [`cloud.region`][cloud]は`AWS_REGION`環境変数の値に設定しなければなりません（MUST）。
- [`faas.name`][faasres]は`AWS_LAMBDA_FUNCTION_NAME`環境変数の値に設定しなければなりません（MUST）。
- [`faas.version`][faasres]は`AWS_LAMBDA_FUNCTION_VERSION`環境変数の値に設定しなければなりません（MUST）。

[`cloud.resource_id`][cloud]は、関数呼び出しまで利用できないため、現時点ではリソースとして設定できないことに注意してください。

[environment variables]: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime
[DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status

