

# C\$1 による Lambda 関数の構築
<a name="lambda-csharp"></a>

マネージド型 .NET 8 ランタイム、カスタムランタイム、コンテナイメージを使用して Lambda で .NET アプリケーションを実行できます。アプリケーションコードをコンパイルしたら、.zip ファイルまたはコンテナイメージとして Lambda にデプロイできます。Lambda は、次の .NET 言語のランタイムをサポートしています。


| 名前 | 識別子 | オペレーティングシステム | 廃止日 | 関数の作成をブロックする | 関数の更新をブロックする | 
| --- | --- | --- | --- | --- | --- | 
|  .NET 10  |  `dotnet10`  |  Amazon Linux 2023  |   2028 年 11 月 14 日   |   2028 年 12 月 14 日   |   2029 年 1 月 15 日   | 
|  .NET 9 (コンテナのみ)  |  `dotnet9`  |  Amazon Linux 2023  |   2026 年 11 月 10 日   |   スケジュールされていません   |   スケジュールされていません   | 
|  .NET 8  |  `dotnet8`  |  Amazon Linux 2023  |   2026 年 11 月 10 日   |   2026 年 12 月 10 日   |   2027 年 1 月 11 日   | 

## .NET 開発環境のセットアップ
<a name="csharp-dev-env"></a>

Lambda 関数の開発と構築には、Microsoft Visual Studio、Visual Studio Code、JetBrains Rider など、一般的に利用できる .NET 統合開発環境 (IDE) をどれでも使用できます。開発作業を簡素化するために、AWS には、.NET プロジェクトテンプレートのセットと `Amazon.Lambda.Tools` コマンドラインインターフェイス (CLI) が用意されています。

次の .NET CLI コマンドを実行して、これらのプロジェクトテンプレートとコマンドラインツールをインストールします。

### .NETプロジェクトテンプレートのインストール
<a name="csharp-dev-env-templates"></a>

プロジェクトテンプレートをインストールするには、次のコマンドを実行します。

```
dotnet new install Amazon.Lambda.Templates
```

### CLI ツールのインストールと更新
<a name="csharp-dev-env-cli-tools"></a>

`Amazon.Lambda.Tools` CLI をインストール、更新、アンインストールするには、次のコマンドを実行します。

コマンドラインツールをインストールするには:

```
dotnet tool install -g Amazon.Lambda.Tools
```

コマンドラインツールを更新するには:

```
dotnet tool update -g Amazon.Lambda.Tools
```

コマンドラインツールをインストールするには:

```
dotnet tool uninstall -g Amazon.Lambda.Tools
```

# C\$1 の Lambda 関数ハンドラーの定義
<a name="csharp-handler"></a>

Lambda 関数*ハンドラー*は、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。関数は、ハンドラーが応答を返すか、終了するか、タイムアウトするまで実行されます。

このページでは、プロジェクトのセットアップオプション、命名規則、ベストプラクティスなど、C\$1 で Lambda 関数ハンドラーを使用して .NET マネージドランタイムを扱う方法について説明します。このページには、注文に関する情報を取得し、テキストファイル受信を生成して、このファイルを Amazon Simple Storage Service (S3) バケットに配置する C\$1 Lambda 関数の例も含まれています。関数を書き込んだ後にデプロイする方法については、「[.zip ファイルアーカイブを使用して C\$1 Lambda 関数を構築し、デプロイする](csharp-package.md)」または「[コンテナイメージを使用して.NET の Lambda 関数をデプロイする](csharp-image.md)」を参照してください。

**Topics**
+ [

## C\$1 ハンドラープロジェクトのセットアップ
](#csharp-handler-setup)
+ [

## C\$1 Lambda 関数のコードの例
](#csharp-example-code)
+ [

## クラスライブラリハンドラー
](#csharp-class-library-handlers)
+ [

## 実行可能アセンブリハンドラー
](#csharp-executable-assembly-handlers)
+ [

## C\$1 関数の有効なハンドラー署名
](#csharp-handler-signatures)
+ [

## ハンドラーの命名規則
](#csharp-handler-naming)
+ [

## C\$1 Lambda 関数のシリアル化
](#csharp-handler-serializer)
+ [

## ファイルベースの関数
](#csharp-file-based-functions)
+ [

## Lambda コンテキストオブジェクトへのアクセスと使用
](#csharp-example-context)
+ [

## ハンドラーでの SDK for .NET v3 の使用
](#csharp-example-sdk-usage)
+ [

## 環境変数にアクセスする
](#csharp-example-envvars)
+ [

## グローバルな状態を使用する
](#csharp-handler-state)
+ [

## Lambda Annotations Framework による関数コードの簡略化
](#csharp-handler-annotations)
+ [

## C\$1 Lambda 関数のコードのベストプラクティス
](#csharp-best-practices)

## C\$1 ハンドラープロジェクトのセットアップ
<a name="csharp-handler-setup"></a>

C\$1 で Lambda 関数を使用する場合、プロセスにはコードを記述し、コードを Lambda にデプロイする動作が含まれます。.NET で Lambda 関数をデプロイするための実行モデルには、クラスライブラリアプローチと実行可能アセンブリアプローチの 2 種類があります。

クラスライブラリアプローチでは、関数コードを .NET アセンブリ (`.dll`) としてパッケージ化し、.NET マネージドランタイム (`dotnet8`) を使用して Lambda にデプロイします。ハンドラー名として、Lambda は `AssemblyName::Namespace.Classname::Methodname` 形式の文字列を想定します。関数の初期化フェーズでは、関数のクラスが初期化され、コンストラクタ内のすべてのコードが実行されます。

実行可能ファイルのアセンブリアプローチでは、C\$1 9 で初めて導入された[最上位ステートメント機能](https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/top-level-statements)を使用します。この方法では、関数の呼び出しコマンドを受信するたびに Lambda が実行する実行可能アセンブリが生成されます。この方法では、.NET マネージドランタイム (`dotnet8`) も使用します。ハンドラー名として、Lambda に実行する実行可能アセンブリの名前を提示します。

このページのメインの例では、クラスライブラリ手法を示しています。C\$1 Lambda プロジェクトはさまざまな方法で初期化できますが、最も簡単な方法は .NET CLI と `Amazon.Lambda.Tools` CLI を使用することです。[.NET 開発環境のセットアップ](lambda-csharp.md#csharp-dev-env) の手順に従って `Amazon.Lambda.Tools` CLI を設定します。次に、以下のコマンドでプロジェクトを初期化します。

```
dotnet new lambda.EmptyFunction --name ExampleCS
```

このコマンドを実行すると、以下のファイル構造が生成されます。

```
/project-root 
    └ src
        └ ExampleCS
            └ Function.cs (contains main handler)
            └ Readme.md
            └ aws-lambda-tools-defaults.json
            └ ExampleCS.csproj          
    └ test
         └ ExampleCS.Tests
            └ FunctionTest.cs (contains main handler)
            └ ExampleCS.Tests.csproj
```

このファイル構造では、関数のメインハンドラーロジックは `Function.cs` ファイルにあります。

## C\$1 Lambda 関数のコードの例
<a name="csharp-example-code"></a>

以下の C\$1 Lambda 関数コードの例では、注文に関する情報を取得し、テキストファイル受信を生成し、このファイルを Amazon S3 バケットに配置します。

**Example `Function.cs` Lambda 関数**  

```
using System;
using System.Text;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.S3;
using Amazon.S3.Model;

// Assembly attribute to enable Lambda function logging
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace ExampleLambda;

public class Order
{
    public string OrderId { get; set; } = string.Empty;
    public double Amount { get; set; }
    public string Item { get; set; } = string.Empty;
}

public class OrderHandler
{
    private static readonly AmazonS3Client s3Client = new();

    public async Task<string> HandleRequest(Order order, ILambdaContext context)
    {
        try
        {
            string? bucketName = Environment.GetEnvironmentVariable("RECEIPT_BUCKET");
            if (string.IsNullOrWhiteSpace(bucketName))
            {
                throw new ArgumentException("RECEIPT_BUCKET environment variable is not set");
            }

            string receiptContent = $"OrderID: {order.OrderId}\nAmount: ${order.Amount:F2}\nItem: {order.Item}";
            string key = $"receipts/{order.OrderId}.txt";

            await UploadReceiptToS3(bucketName, key, receiptContent);

            context.Logger.LogInformation($"Successfully processed order {order.OrderId} and stored receipt in S3 bucket {bucketName}");
            return "Success";
        }
        catch (Exception ex)
        {
            context.Logger.LogError($"Failed to process order: {ex.Message}");
            throw;
        }
    }

    private async Task UploadReceiptToS3(string bucketName, string key, string receiptContent)
    {
        try
        {
            var putRequest = new PutObjectRequest
            {
                BucketName = bucketName,
                Key = key,
                ContentBody = receiptContent,
                ContentType = "text/plain"
            };

            await s3Client.PutObjectAsync(putRequest);
        }
        catch (AmazonS3Exception ex)
        {
            throw new Exception($"Failed to upload receipt to S3: {ex.Message}", ex);
        }
    }
}
```

この `Function.cs` ファイルには以下のコードのセクションが含まれます:
+ `using` ステートメント: これらを使用して、Lambda 関数に必要な C\$1 クラスをインポートします。
+ `[assembly: LambdaSerializer(...)]`: `LambdaSerializer` は、JSON イベントペイロードを関数に渡す前に C\$1 オブジェクトに自動的に変換するよう Lambda に指示するアセンブリ属性です。
+ `namespace ExampleLambda`: 名前空間を定義します。C\$1 では、名前空間名がファイル名と一致する必要はありません。
+ `public class Order {...}`: 予測される入力イベントの形状を定義します。
+ `public class OrderHandler {...}`: これは C\$1 クラスを定義します。その中で、メインハンドラーメソッドとその他のヘルパーメソッドを定義します。
+ `private static readonly AmazonS3Client s3Client = new();`: これにより、メインハンドラーメソッドの外部で、デフォルトの認証情報プロバイダーチェーンを使用して Amazon S3 クライアントが初期化されます。これにより、Lambda は[初期化フェーズ](lambda-runtime-environment.md#runtimes-lifecycle-ib)中にこのコードを実行します。
+ `public async ... HandleRequest (Order order, ILambdaContext context)`: これは**メインハンドラーメソッド**で、メインアプリケーションロジックが含まれています。
+ `private async Task UploadReceiptToS3(...) {}`: これは、メイン `handleRequest` ハンドラーメソッドによって参照されるヘルパーメソッドです。

この関数には Amazon S3 SDK クライアントが必要なため、プロジェクトの依存関係に追加する必要があります。このためには、`src/ExampleCS` に移動して次のコマンドを実行することもできます。

```
dotnet add package AWSSDK.S3
```

### aws-lambda-tools-defaults.json にメタデータ情報を追加する
<a name="csharp-metadata-example"></a>

デフォルトでは、生成された `aws-lambda-tools-defaults.json` ファイルには関数の `profile` または `region` 情報は含まれません。さらに、`function-handler` 文字列を正しい値 (`ExampleCS::ExampleLambda.OrderHandler::HandleRequest`) に更新します。この更新を手動で行い、関数に特定の認証情報プロファイルとリージョンを使用するために必要なメタデータを追加できます。例えば、`aws-lambda-tools-defaults.json` ファイルは次のようになります。

```
{
  "Information": [
    "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
    "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
    "dotnet lambda help",
    "All the command line options for the Lambda command can be specified in this file."
  ],
  "profile": "default",
  "region": "us-east-1",
  "configuration": "Release",
  "function-architecture": "x86_64",
  "function-runtime": "dotnet8",
  "function-memory-size": 512,
  "function-timeout": 30,
  "function-handler": "ExampleCS::ExampleLambda.OrderHandler::HandleRequest"
}
```

この関数が正しく機能するには、[実行ロール](lambda-intro-execution-role.md)で `s3:PutObject` アクションを許可する必要があります。また、必ず `RECEIPT_BUCKET` 環境変数を定義してください。呼び出しに成功したら、Amazon S3 バケットに受信ファイルが含まれているはずです。

## クラスライブラリハンドラー
<a name="csharp-class-library-handlers"></a>

このページのメインの[コード例](#csharp-example-code)は、クラスライブラリハンドラーを示しています。クラスライブラリハンドラーの構造は次のとおりです。

```
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace NAMESPACE;

...

public class CLASSNAME {
    public async Task<string> METHODNAME (...) {
    ...
    }
}
```

Lambda 関数を作成するときは、関数のハンドラーに関する情報を[ハンドラーフィールド](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-Handler)の文字列の形式で Lambda に提供する必要があります。これにより、関数の呼び出し時に実行するコードのメソッドを Lambda に指示します。C\$1 では、クラスライブラリハンドラーの場合、ハンドラー文字列の形式は `ASSEMBLY::TYPE::METHOD` です。ここでは、次のようになります。
+ `ASSEMBLY` は、アプリケーションの .NET アセンブリファイルの名前です。`Amazon.Lambda.Tools` CLI を使用してアプリケーションを構築し、`.csproj` ファイルの `AssemblyName` プロパティを使用してアセンブリ名を設定しない場合、`ASSEMBLY` は単に `.csproj` ファイルの名前になります。
+ `TYPE` は、ハンドラー型の正式名称で、`NAMESPACE.CLASSNAME` です。
+ `METHOD` は、コード内の関数ハンドラーメソッドの名前で、`METHODNAME` です。

このページのメインのコード例では、アセンブリに `ExampleCS` という名前が付けられている場合、完全なハンドラー文字列は `ExampleCS::ExampleLambda.OrderHandler::HandleRequest` です。

## 実行可能アセンブリハンドラー
<a name="csharp-executable-assembly-handlers"></a>

C\$1 の Lambda 関数を実行ファイルアセンブリとして定義することもできます。実行可能アセンブリハンドラーは、C\$1 の最上位ステートメント機能を使用します。この機能では、コンパイラが `Main()` メソッドを生成し、関数コードをその中に配置します。実行可能アセンブリを使用する場合は、Lambda ランタイムをブートストラップする必要があります。これを行うには、コードで `LambdaBootstrapBuilder.Create` メソッドを使用します。このメソッドへの入力は、メインハンドラー関数と使用する Lambda シリアライザーです。以下は、C\$1 の実行可能アセンブリハンドラーの例です。

```
namespace GetProductHandler;

IDatabaseRepository repo = new DatabaseRepository();

await LambdaBootstrapBuilder.Create<APIGatewayProxyRequest>(Handler, new DefaultLambdaJsonSerializer())
    .Build()
    .RunAsync();

async Task<APIGatewayProxyResponse> Handler(APIGatewayProxyRequest apigProxyEvent, ILambdaContext context)
{
    var id = apigProxyEvent.PathParameters["id"];
    var databaseRecord = await this.repo.GetById(id);
    
    return new APIGatewayProxyResponse 
    {
        StatusCode = (int)HttpStatusCode.OK,
        Body = JsonSerializer.Serialize(databaseRecord)
    };
};
```

実行可能アセンブリの[ハンドラーフィールド](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html#lambda-CreateFunction-request-Handler)では、コードの実行方法を Lambda に指示するハンドラー文字列はアセンブリの名前です。この例では、`GetProductHandler` です。

## C\$1 関数の有効なハンドラー署名
<a name="csharp-handler-signatures"></a>

C\$1 では、有効な Lambda ハンドラー署名は 0～2 個の引数を取ります。通常、ハンドラー署名には、メインの例に示すように、2 つの引数があります。

```
public async Task<string> HandleRequest(Order order, ILambdaContext context)
```

引数を2つ指定する場合、最初の引数はイベント入力で、2 番目の引数は Lambda コンテキストオブジェクトである必要があります。どちらの引数もオプションです。例えば、以下も有効な C\$1 の Lambda ハンドラー署名です。
+ `public async Task<string> HandleRequest()`
+ `public async Task<string> HandleRequest(Order order)`
+ `public async Task<string> HandleRequest(ILambdaContext context)`

ハンドラー署名の基本構文以外にも、いくつかの制限があります。
+ ハンドラー署名で `unsafe` キーワードを使用することはできません。ただし、ハンドラーメソッドとその依存関係内で `unsafe` コンテキストを使用できます。詳細については、Microsoft ドキュメントウェブサイトの「[unsafe (C\$1 reference)](https://msdn.microsoft.com/en-us/library/chfa2zb8.aspx)」を参照してください。
+ ハンドラーは、`params` キーワードを使用したり、入力または戻りパラメータとして `ArgIterator` を使用したりすることはできません。これらのキーワードは、可変数のパラメータをサポートします。ハンドラーが受け入れることができる引数の最大数は 2 です。
+ ハンドラーは汎用メソッドではない場合があります。つまり、`<T>` などの汎用型パラメータを使用することはできません。
+ Lambda は、署名に `async void` を持つ非同期ハンドラーをサポートしていません。

## ハンドラーの命名規則
<a name="csharp-handler-naming"></a>

C\$1 の Lambda ハンドラーには、厳密な命名制限はありません。ただし、関数をデプロイするときに、Lambda に正しいハンドラー文字列を指定する必要があります。適切なハンドラー文字列は、[クラスライブラリハンドラー](#csharp-class-library-handlers)と[実行可能アセンブリハンドラー](#csharp-executable-assembly-handlers)のどちらをデプロイするかによって異なります。

ハンドラーには任意の名前を使用できますが、C\$1 の関数名は通常 PascalCase です。また、ファイル名はクラス名やハンドラー名と一致する必要はありませんが、クラス名が `OrderHandler` の場合と同様に `OrderHandler.cs` などのファイル名を使用するのがベストプラクティスです。例えば、この例のファイル名を `Function.cs` から `OrderHandler.cs` に変更できます。

## C\$1 Lambda 関数のシリアル化
<a name="csharp-handler-serializer"></a>

JSON は Lambda 関数の最も一般的な標準入力形式です。この例では、関数は以下のような入力を想定しています:

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

C\$1 では、クラスで予想される入力イベントの形状を定義できます。この例では、この入力をモデル化する `Order` クラスを定義します。

```
public class Order
{
    public string OrderId { get; set; } = string.Empty;
    public double Amount { get; set; }
    public string Item { get; set; } = string.Empty;
}
```

Lambda 関数が、`Stream` オブジェクト以外の入出力タイプを使用する場合は、アプリケーションにシリアル化ライブラリを追加する必要があります。これにより、JSON 入力を定義したクラスのインスタンスに変換できます。Lambda の C\$1 関数のシリアル化には、リフレクションベースのシリアル化とソース生成のシリアル化の 2 つの方法があります。

### リフレクションベースのシリアル化
<a name="csharp-reflection-based-serialization"></a>

AWS は、アプリケーションに迅速に追加できる事前構築済みライブラリを提供しています。これらのライブラリは、[リフレクション](https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/reflection-and-attributes/)を使用してシリアル化を実装します。リフレクションベースのシリアル化を実装するには、次のいずれか 1 つのパッケージを使用します。
+ `Amazon.Lambda.Serialization.SystemTextJson` – バックエンドでは、このパッケージは `System.Text.Json` を使用してシリアル化タスクを実行します。
+ `Amazon.Lambda.Serialization.Json` – バックエンドでは、このパッケージは `Newtonsoft.Json` を使用してシリアル化タスクを実行します。

`ILambdaSerializer` インターフェイスの実装によって独自のシリアル化ライブラリを作成することもできます。これは、`Amazon.Lambda.Core` ライブラリの一部として使用できます。このインターフェイスは 2 つのメソッドを定義します。
+ `T Deserialize<T>(Stream requestStream);`

  このメソッドを実装して、`Invoke` API から Lambda 関数ハンドラーに渡されるオブジェクトにリクエストのペイロードを逆シリアル化することができます。
+ `T Serialize<T>(T response, Stream responseStream);`

  このメソッドを実装して、Lambda 関数のハンドラーから返される結果を `Invoke` API オペレーションが返すレスポンスペイロードにシリアル化することができます。

このページのメインの例では、リフレクションベースのシリアル化を使用しています。リフレクションベースのシリアル化は、AWS Lambda ですぐに機能し、追加のセットアップを必要としないため、作業をシンプルにするにはよい選択です。ただし、関数のメモリ使用量を増やす必要があります。ランタイムリフレクションにより、関数のレイテンシーが高くなる場合もあります。

### ソース生成のシリアル化
<a name="csharp-source-generated-serialization"></a>

ソース生成のシリアル化では、コンパイル時にシリアル化コードが生成されます。これにより、リフレクションが不要になり、関数のパフォーマンスが向上します。ソース生成のシリアル化を関数で使用するには、以下を実行する必要があります。
+ `JsonSerializerContext` を継承する新しい部分クラスを作成し、シリアル化または逆シリアル化を必要とするすべての型の `JsonSerializable` 属性を追加します。
+ `LambdaSerializer` を設定して `SourceGeneratorLambdaJsonSerializer<T>` を使用します。
+ アプリケーションコード内の手動シリアル化および逆シリアル化をすべて更新して、新しく作成したクラスを使用するようにします。

次の例は、リフレクションベースのシリアル化を使用するこのページのメインの例を変更して、代わりにソース生成のシリアル化を使用する方法を示しています。

```
using System.Text.Json;
using System.Text.Json.Serialization;

...

public class Order
{
    public string OrderId { get; set; } = string.Empty;
    public double Amount { get; set; }
    public string Item { get; set; } = string.Empty;
}

[JsonSerializable(typeof(Order))]
public partial class OrderJsonContext : JsonSerializerContext {}

public class OrderHandler
{

    ...

    public async Task<string> HandleRequest(string input, ILambdaContext context)
    {
    
    var order = JsonSerializer.Deserialize(input, OrderJsonContext.Default.Order);
    
    ...
    
    }

}
```

ソース生成のシリアル化には、リフレクションベースのシリアル化よりも多くのセットアップが必要です。ただし、ソース生成を使用する関数は、コンパイル時のコード生成により、メモリ使用量が減少し、パフォーマンスが向上します。関数の[コールドスタート](lambda-runtime-environment.md#cold-start-latency)を排除するには、ソース生成のシリアル化に切り替えることを検討してください。

**注記**  
Lambda でネイティブの[事前コンパイル (AOT)](dotnet-native-aot.md) を使用する場合は、ソース生成のシリアル化を使用する必要があります。

## ファイルベースの関数
<a name="csharp-file-based-functions"></a>

.NET 10 で導入されたファイルベースのアプリケーションを使用すると、`.csproj` ファイルやディレクトリ構造なしで、単一の `.cs` ファイルから .NET アプリケーションを構築できます。Lambda は、.NET 10 以降のファイルベースの関数をサポートしています。これらは、C\$1 での Lambda 関数構築を合理化、軽量化します。

C\$1 ファイルベースの Lambda 関数の作成を開始する最も簡単な方法は、`Amazon.Lambda.Templates` パッケージを使用することです。次のコマンドを実行して、このパッケージをインストールします。

```
dotnet new install Amazon.Lambda.Templates
```

次に、C\$1 ファイルベースの Lambda サンプル関数を次のように作成します。

```
dotnet new lambda.FileBased -n MyLambdaFunction
```

ファイルベースの関数は、[実行可能アセンブリハンドラー](#csharp-executable-assembly-handlers)を使用します。したがって、`Amazon.Lambda.RuntimeSupport` NuGet パッケージを含めるとともに `LambdaBootstrapBuilder.Create` メソッドを使用してイベントタイプの .NET ハンドラー関数を登録し、.NET Lambda ランタイムクライアントを起動する必要があります。

ファイルベースの関数はデフォルトで .NET ネイティブ AOT を使用します。これにはソース生成のシリアル化が必要です。ソースファイルで `#:property PublishAot=false` を指定することで、ネイティブ AOT を無効にできます。Lambda でのネイティブ AOT の使用の詳細については、「[.NET Lambda 関数コードをネイティブランタイム形式にコンパイルする](dotnet-native-aot.md)」を参照してください。

## Lambda コンテキストオブジェクトへのアクセスと使用
<a name="csharp-example-context"></a>

Lambda [コンテキストオブジェクト](csharp-context.md)には、呼び出し、関数、および実行環境に関する情報が含まれます。この例では、コンテキストオブジェクトは `Amazon.Lambda.Core.ILambdaContext` 型で、メインハンドラー関数の 2 番目の引数です。

```
public async Task<string> HandleRequest(Order order, ILambdaContext context) {
    ...
}
```

コンテキストオブジェクトはオプションの入力です。有効な受理されたハンドラー署名の詳細については、「[C\$1 関数の有効なハンドラー署名](#csharp-handler-signatures)」を参照してください。

コンテキストオブジェクトは、Amazon CloudWatch に関数ログを生成するのに役立ちます。`context.getLogger()` メソッドを使用して、ログ記録用の `LambdaLogger` オブジェクトを取得できます。この例では、何らかの理由で処理が失敗した場合、ロガーを使用してエラーメッセージをログに記録できます。

```
context.Logger.LogError($"Failed to process order: {ex.Message}");
```

ログ記録以外では、関数のモニタリングにコンテキストオブジェクトを使用することもできます。コンテキストオブジェクトの詳細については、「[Lambda コンテキストオブジェクトを使用して C\$1 関数の情報を取得する](csharp-context.md)」を参照してください。

## ハンドラーでの SDK for .NET v3 の使用
<a name="csharp-example-sdk-usage"></a>

多くの場合、Lambda 関数を使用して、他の AWS リソースとやり取りしたり、更新したりします。これらのリソースとインターフェイスする最も簡単な方法は、SDK for .NET v3 を使用することです。

**注記**  
SDK for .NET (v2) は非推奨になりました。今後は SDK for .NET v3 のみを使用することをお勧めします。

次の `Amazon.Lambda.Tools` コマンドを使用して、プロジェクトに SDK 依存関係を追加できます。

```
dotnet add package <package_name>
```

例えば、このページのメインの例では、Amazon S3 API を使用して S3 に受信をアップロードする必要があります。次のコマンドを使用して、Amazon S3 SDK クライアントをインポートできます。

```
dotnet add package AWSSDK.S3
```

このコマンドは、依存関係をプロジェクトに追加します。また、プロジェクトの `.csproj` ファイルには次のような行が表示されます。

```
<PackageReference Include="AWSSDK.S3" Version="3.7.2.18" />
```

次に、依存関係を C\$1 コードに直接インポートします。

```
using Amazon.S3;
using Amazon.S3.Model;
```

その後、コード例では、Amazon S3 クライアントを ([デフォルトの認証情報プロバイダーチェーン](https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html)を使用して) 次のように初期化します。

```
private static readonly AmazonS3Client s3Client = new();
```

この例では、関数を呼び出すたびに Amazon S3 クライアントを初期化する必要がないように、メインハンドラー関数の外で Amazon S3 クライアントを初期化しました。SDK クライアントを初期化したら、SDK クライアントを使用して他の AWS サービスとやり取りできます。サンプルコードは、以下のように Amazon S3 `PutObject` API を呼び出します。

```
var putRequest = new PutObjectRequest
{
    BucketName = bucketName,
    Key = key,
    ContentBody = receiptContent,
    ContentType = "text/plain"
};

await s3Client.PutObjectAsync(putRequest);
```

## 環境変数にアクセスする
<a name="csharp-example-envvars"></a>

ハンドラーコードでは、`System.Environment.GetEnvironmentVariable` メソッドを使用して任意の[環境変数](configuration-envvars.md)を参照できます。この例では、以下のコード行を使用して、定義された `RECEIPT_BUCKET` 環境変数を参照します:

```
string? bucketName = Environment.GetEnvironmentVariable("RECEIPT_BUCKET");
if (string.IsNullOrWhiteSpace(bucketName))
{
    throw new ArgumentException("RECEIPT_BUCKET environment variable is not set");
}
```

## グローバルな状態を使用する
<a name="csharp-handler-state"></a>

Lambda は、関数を初めて呼び出す前の[初期化フェーズ](lambda-runtime-environment.md#runtimes-lifecycle-ib)で静的コードとクラスコンストラクターを実行します。初期化中に作成されたリソースは呼び出し間でメモリに保持されるため、関数を呼び出すたびにリソースを作成する必要がなくなります。

コード例では、S3 クライアント初期化コードはメインハンドラーメソッドの外にあります。ランタイムは、関数が最初のイベントを処理する前にクライアントを初期化するため、処理時間が長くなる可能性があります。Lambda がクライアントを再度初期化する必要がないため、後続のイベントはより高速になります。

## Lambda Annotations Framework による関数コードの簡略化
<a name="csharp-handler-annotations"></a>

[Lambda Annotations](https://www.nuget.org/packages/Amazon.Lambda.Annotations) は .NET 8 用のフレームワークであり、C\$1 を使用して Lambda 関数の記述を簡素化します。Annotations Framework は[ソースジェネレーター](https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview)を使用して、Lambda プログラミングモデルから簡素化されたコードに変換するコードを生成します。Annotations Framework では、通常のプログラミングモデルを使用して記述された Lambda 関数のコードの多くを置き換えることができます。このフレームワークを使用して記述されたコードでは、ビジネスロジックに集中できるより単純な式が使用されます。例については、nuget ドキュメントの「[Amazon.Lambda.Annotations](https://www.nuget.org/packages/Amazon.Lambda.Annotations)」を参照してください。

Lambda Annotations を利用する完全なアプリケーションの例については、`awsdocs/aws-doc-sdk-examples`GitHub リポジトリの [PhotoAssetManager](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/dotnetv3/cross-service/PhotoAssetManager) の例を参照してください。`Function.cs` ディレクトリのメイン `PamApiAnnotations` ファイルで Lambda Annotations が使用されています。比較のために、`PamApi` ディレクトリには、通常の Lambda プログラミングモデルを使用して記述された同等のファイルがあります。

### Lambda Annotations Framework による依存関係インジェクション
<a name="csharp-handler-annotations-injection"></a>

Lambda Annotations Framework を使用して、使い慣れた構文を用いて Lambda 関数に依存関係インジェクションを追加することもできます。`[LambdaStartup]` 属性を `Startup.cs` ファイルに追加すると、Lambda Annotations Framework がコンパイル時に必要なコードを生成します。

```
[LambdaStartup]
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IDatabaseRepository, DatabaseRepository>();
    }
}
```

Lambda 関数は、コンストラクタインジェクションを使用するか、`[FromServices]` 属性を使用して個々のメソッドに挿入することで、サービスを挿入できます。

```
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetProductHandler;

public class Function
{
    private readonly IDatabaseRepository _repo;
    
    public Function(IDatabaseRepository repo)
    {
        this._repo = repo;
    }
    
    [LambdaFunction]
    [HttpApi(LambdaHttpMethod.Get, "/product/{id}")]
    public async Task<Product> FunctionHandler([FromServices] IDatabaseRepository repository, string id)
    {
        return await this._repo.GetById(id);
    }
}
```

## C\$1 Lambda 関数のコードのベストプラクティス
<a name="csharp-best-practices"></a>

Lambda 関数をビルドするときは、次のリストのガイドラインに従って、コーディングのベストプラクティスを実行してください。
+ **Lambda ハンドラーをコアロジックから分離します。**これにより、関数の単体テストが実行しやすくなります。
+ **関数のデプロイパッケージ内で依存関係を制御します。**AWS Lambda 実行環境には多数のライブラリが含まれています。最新の機能やセキュリティ更新プログラムを有効にするために、Lambda はこれらのライブラリを定期的に更新します。この更新により、Lambda 関数の動作が微妙に変化する場合があります。関数で使用する依存関係を完全に制御するには、すべての依存関係をデプロイパッケージでパッケージングします。
+ **依存関係の複雑さを最小限に抑えます。**フレームワークを単純化して、[実行環境](lambda-runtime-environment.md)起動時のロードを高速化します。
+ **デプロイパッケージをランタイムに必要な最小限のサイズにします。**これにより、呼び出しに先立ってデプロイパッケージをダウンロードして解凍する所要時間が短縮されます。.NET で記述された関数の場合は、デプロイパッケージの一部として AWS SDK ライブラリ全体をアップロードしないようにします。代わりに、SDK のコンポーネントを必要に応じて選別するモジュール (DynamoDB、Amazon S3 SDK モジュール、Lambda コアライブラリなど) を使用します。

**実行環境の再利用を活用して関数のパフォーマンスを向上させます。**関数ハンドラー外で 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 の内部 API にセキュリティと機能面の更新を定期的に適用します。これらの内部 API 更新には後方互換性がないことがあり、関数にこれらの非公開 API に対する依存関係がある場合、呼び出しの失敗などの意図しない結果につながります。公開されている API のリストについては、「[API リファレンス](https://docs.aws.amazon.com/lambda/latest/api/welcome.html)」を参照してください。

**冪等性コードを記述します**。関数の記述に冪等性コードを使用すると、重複するイベントが同じ方法で処理されるようになります。コードでは、イベントを適切に検証し、重複するイベントを適切に処理する必要があります。詳細については、「[Lambda 関数を冪等にするにはどうすればよいですか?](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-idempotent/)」を参照してください。

# .zip ファイルアーカイブを使用して C\$1 Lambda 関数を構築し、デプロイする
<a name="csharp-package"></a>

.NET デプロイパッケージ (.zip ファイルアーカイブ) は、関数のコンパイル済みアセンブリと、そのアセンブリのすべての依存関係で構成されています。このパッケージには、`proj.deps.json` ファイルも含まれています。これは、関数のすべての依存関係と、.NET ランタイムを設定するために使用される `proj.runtimeconfig.json` ファイルを、.NET ランタイムに伝達します。

個々の Lambda 関数をデプロイするには、`Amazon.Lambda.Tools` .NET Lambda Global CLI を使用できます。`dotnet lambda deploy-function` コマンドを使用すると、.zip デプロイパッケージが自動的に作成され、Lambda にデプロイされます。ただし、.NET アプリケーションを AWS にデプロイするには、AWS Serverless Application Model (AWS SAM) や AWS Cloud Development Kit (AWS CDK) などのフレームワークを使用することをお勧めします。

サーバーレスアプリケーションは通常、Lambda 関数とその他のマネージド AWS のサービスを組み合わせて構成され、連携して特定のビジネスタスクを実行します。AWS SAM と AWS CDK は、Lambda 関数を大規模に他の AWS のサービスと組み合わせて構築し、デプロイするのを簡略化します。[AWS SAM テンプレート仕様](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification.html)は、サーバーレスアプリケーションを構成する Lambda 関数、API、アクセス許可、設定、およびその他の AWS リソースを記述するためのシンプルで簡潔な構文を提供します。[AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/home.html) を使用すると、クラウドインフラストラクチャをコードとして定義し、最新のプログラミング言語と .NET などのフレームワークを使用して、信頼性が高く、スケーラブルで、コスト効率の高いアプリケーションをクラウドで構築することができます。AWS CDK と AWS SAM はどちらも、.NET Lambda Global CLI を使用して関数をパッケージ化します。

[.NET Core CLI を使用](csharp-package-cli.md#csharp-layers)することで、C\$1 の関数で [Lambda レイヤー](chapter-layers.md)を使用することは可能ですが、使用しないことをお勧めします。レイヤーを使用する C\$1 の関数では、[初期化フェーズ](lambda-runtime-environment.md#runtimes-lifecycle-ib) 中に共有アセンブリを手動でメモリに読み込みます。これにより、コールドスタート時間が長くなる可能性があります。代わりに、コンパイル時にすべての共有コードを含めて、実行時のアセンブリの読み込みによるパフォーマンスへの影響を回避してください。

AWS SAM、AWS CDK、および .NET Lambda Global CLI を使用して .NET Lambda 関数を構築およびデプロイする手順については、以下のセクションを参照してください。

**Topics**
+ [

# .NET Lambda Global CLI を使用する
](csharp-package-cli.md)
+ [

# AWS SAM を使用した C\$1 Lambda 関数のデプロイ
](csharp-package-sam.md)
+ [

# AWS CDK を使用した C\$1 Lambda 関数のデプロイ
](csharp-package-cdk.md)
+ [

# ASP.NET アプリケーションのデプロイ
](csharp-package-asp.md)

# .NET Lambda Global CLI を使用する
<a name="csharp-package-cli"></a>

.NET CLI および .NET Lambda Global Tools 拡張機能 (`Amazon.Lambda.Tools`) は、.NET ベースの Lambda アプリケーションを作成し、パッケージ化して、Lambda にデプロイするためのクロスプラットフォームな方法を提供します。このセクションでは、.NET CLI と Amazon Lambda テンプレートを使用して新しい Lambda .NET プロジェクトを作成する方法と、`Amazon.Lambda.Tools` を使用してそれらをパッケージ化してデプロイする方法を学習します。

**Topics**
+ [

## 前提条件
](#csharp-package-cli-prerequisites)
+ [

## .NET CLI を使用して .NET プロジェクトを作成する
](#csharp-package-cli-create)
+ [

## .NET CLI を使用して .NET プロジェクトをデプロイする
](#csharp-package-cli-deploy)
+ [

## .NET CLI で Lambda レイヤーを使用する
](#csharp-layers)

## 前提条件
<a name="csharp-package-cli-prerequisites"></a>

**.NET 8 SDK**  
まだインストールしていない場合は、[.NET 8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) SDK とランタイムをインストールします。

**AWS Amazon.Lambda.Templates .NET プロジェクトテンプレート**  
Lambda 関数コードを生成するには、[https://www.nuget.org/packages/Amazon.Lambda.Templates](https://www.nuget.org/packages/Amazon.Lambda.Templates) NuGet パッケージを使用します。このテンプレートパッケージをインストールするには、以下のコマンドを実行します。  

```
dotnet new install Amazon.Lambda.Templates
```

**AWS Amazon.Lambda.Tools .NET Global CLI Tools**  
Lambda 関数を作成するには、[https://www.nuget.org/packages/Amazon.Lambda.Tools](https://www.nuget.org/packages/Amazon.Lambda.Tools) [.NET Global Tools 拡張機能](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/)を使用します。Amazon.Lambda.Tools をインストールするには、以下のコマンドを実行します。  

```
dotnet tool install -g Amazon.Lambda.Tools
```
Amazon.Lambda.Tools .NET CLI 拡張機能の詳細については、GitHub の「[AWS Extensions for .NET CLI](https://github.com/aws/aws-extensions-for-dotnet-cli)」リポジトリを参照してください。

## .NET CLI を使用して .NET プロジェクトを作成する
<a name="csharp-package-cli-create"></a>

.NET CLI では、コマンドラインから .NET プロジェクトを作成するために `dotnet new` コマンドを使用します。Lambda には、[https://www.nuget.org/packages/Amazon.Lambda.Templates](https://www.nuget.org/packages/Amazon.Lambda.Templates) NuGet パッケージを使用する追加のテンプレートが用意されています。

このパッケージをインストールしたら、次のコマンドを実行して、使用可能なテンプレートのリストを表示します。

```
dotnet new list
```

テンプレートに関する詳細を確認するには、`help` オプションを使用します。例えば、`lambda.EmptyFunction` テンプレートの詳細を表示するには、以下のコマンドを実行します。

```
dotnet new lambda.EmptyFunction --help
```

.NET Lambda 関数の基本テンプレートを作成するには、`lambda.EmptyFunction` テンプレートを使用します。これにより、入力として文字列を受け取り、`ToUpper` メソッドを使用して大文字に変換する単純な関数が作成されます。このテンプレートでは、以下のオプションがサポートされています。
+ `--name` － 関数の名前。
+ `--region` － 関数を作成する AWS リージョン。
+ `--profile` － AWS SDK for .NET 認証情報ファイルにあるプロファイルの名前。.NET の認証情報プロファイルの詳細については、「.NET 用 AWS SDK 開発者ガイド」の「[AWS 認証情報を設定](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-config-creds.html)」を参照してください。

この例では、デフォルトのプロファイルと AWS リージョン設定を使用して、`myDotnetFunction` という名前の新しい空の関数を作成します。

```
dotnet new lambda.EmptyFunction --name myDotnetFunction
```

このコマンドは、プロジェクトディレクトリに以下のファイルとディレクトリを作成します。

```
└── myDotnetFunction
    ├── src
    │   └── myDotnetFunction
    │       ├── Function.cs
    │       ├── Readme.md
    │       ├── aws-lambda-tools-defaults.json
    │       └── myDotnetFunction.csproj
    └── test
        └── myDotnetFunction.Tests
            ├── FunctionTest.cs
            └── myDotnetFunction.Tests.csproj
```

`src/myDotnetFunction` ディレクトリで次のファイルを調べます。
+ **aws-lambda-tools-defaults.json**: Lambda 関数をデプロイするときに指定するコマンドラインオプションの場所です。以下に例を示します。

  ```
    "profile" : "default",
    "region" : "us-east-2",
    "configuration" : "Release",
    "function-architecture": "x86_64",
    "function-runtime":"dotnet8",
    "function-memory-size" : 256,
    "function-timeout" : 30,
    "function-handler" : "myDotnetFunction::myDotnetFunction.Function::FunctionHandler"
  ```
+ **Function.cs**: Lambda ハンドラの関数コード。これは、デフォルトの `Amazon.Lambda.Core`ライブラリ とデフォルトの `LambdaSerializer` 属性が含まれる C\$1 テンプレートです。要件とオプションのシリアル化に関する詳細は、「[C\$1 Lambda 関数のシリアル化](csharp-handler.md#csharp-handler-serializer)」を参照してください。これには、Lambda 関数コードに適用するために編集できるサンプル関数も含まれています。

  ```
  using Amazon.Lambda.Core;
  
  // Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
  [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
  
  namespace myDotnetFunction;
  
  public class Function
  {
  
      /// <summary>
      /// A simple function that takes a string and does a ToUpper
      /// </summary≫
      /// <param name="input"></param>
      /// <param name="context"></param>
      /// <returns></returns>
      public string FunctionHandler(string input, ILambdaContext context)
      {
          return input.ToUpper();
      }
  }
  ```
+ **myDotnetFunction.csproj**: アプリケーションを構成するファイルとアセンブリをリスト表示する [MSBuild](https://msdn.microsoft.com/en-us/library/dd393574.aspx) ファイル。

  ```
  <Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
      <TargetFramework>net8.0</TargetFramework>
      <ImplicitUsings>enable</ImplicitUsings>
      <Nullable>enable</Nullable>
      <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
      <AWSProjectType>Lambda</AWSProjectType>
      <!-- This property makes the build directory similar to a publish directory and helps the AWS .NET Lambda Mock Test Tool find project dependencies. -->
      <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
      <!-- Generate ready to run images during publishing to improve cold start time. -->
      <PublishReadyToRun>true</PublishReadyToRun>
    </PropertyGroup>
    <ItemGroup>
      <PackageReference Include="Amazon.Lambda.Core" Version="2.2.0" />
      <PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.4.0" />
    </ItemGroup>
  </Project>
  ```
+ **Readme**: このファイルを使用して Lambda 関数をドキュメント化します。

`myfunction/test` ディレクトリで次のファイルを調べます。
+ **myDotnetFunction.Tests.csproj**: 既に説明したように、これは、テストプロジェクトを構成するファイルとアセンブリをリスト表示するための、[MSBuild](https://msdn.microsoft.com/en-us/library/dd393574.aspx) ファイルです。`Amazon.Lambda.Core` ライブラリが含まれているため、関数のテストに必要な Lambda テンプレートをシームレスに統合できることにも留意してください。

  ```
  <Project Sdk="Microsoft.NET.Sdk">
     ... 
  
      <PackageReference Include="Amazon.Lambda.Core" Version="2.2.0 " />
     ...
  ```
+ **FunctionTest.cs**: `src` ディレクトリに含まれているのと同様の C\$1 コードテンプレートファイルです。このファイルを編集して関数の本番稼働コードを写し、本番稼働環境にアップロードする前に Lambda 関数をテストします。

  ```
  using Xunit;
  using Amazon.Lambda.Core;
  using Amazon.Lambda.TestUtilities;
  
  using MyFunction;
  
  namespace MyFunction.Tests
  {
      public class FunctionTest
      {
          [Fact]
          public void TestToUpperFunction()
          {
  
              // Invoke the lambda function and confirm the string was upper cased.
              var function = new Function();
              var context = new TestLambdaContext();
              var upperCase = function.FunctionHandler("hello world", context);
  
              Assert.Equal("HELLO WORLD", upperCase);
          }
      }
  }
  ```

## .NET CLI を使用して .NET プロジェクトをデプロイする
<a name="csharp-package-cli-deploy"></a>

デプロイパッケージを構築して Lambda にデプロイするには、`Amazon.Lambda.Tools` CLI ツールを使用します。前のステップで作成したファイルから関数をデプロイするには、まず、関数の `.csproj` ファイルが含まれるフォルダに移動します。

```
cd myDotnetFunction/src/myDotnetFunction
```

コードを .zip デプロイパッケージとして Lambda にデプロイするには、以下のコマンドを実行します。独自の関数名を選択してください。

```
dotnet lambda deploy-function myDotnetFunction
```

デプロイ中、ウィザードでは [[実行ロールを使用した Lambda 関数のアクセス許可の定義](lambda-intro-execution-role.md)] を選択するよう求められます。この例では、`lambda_basic_role` を選択します。

関数をデプロイしたら、`dotnet lambda invoke-function` コマンドを使用してクラウドでテストできます。`lambda.EmptyFunction` テンプレートのサンプルコードでは、`--payload` オプションを使用して文字列を渡すことで関数をテストできます。

```
dotnet lambda invoke-function myDotnetFunction --payload "Just checking if everything is OK"
```

関数が正常にデプロイされると、以下のような出力が表示されます。

```
dotnet lambda invoke-function myDotnetFunction --payload "Just checking if everything is OK"
Amazon Lambda Tools for .NET Core applications (5.8.0)
Project Home: https://github.com/aws/aws-extensions-for-dotnet-cli, https://github.com/aws/aws-lambda-dotnet

Payload:
"JUST CHECKING IF EVERYTHING IS OK"

Log Tail:
START RequestId: id Version: $LATEST
END RequestId: id
REPORT RequestId: id  Duration: 0.99 ms       Billed Duration: 1 ms         Memory Size: 256 MB     Max Memory Used: 12 MB
```

## .NET CLI で Lambda レイヤーを使用する
<a name="csharp-layers"></a>

**注記**  
.NET の関数で[レイヤー](chapter-layers.md)を使用することは可能ですが、使用しないことをお勧めします。レイヤーを使用する .NET の関数では、`Init` 中に共有アセンブリを手動でメモリに読み込みます。これにより、コールドスタート時間が長くなる可能性があります。代わりに、コンパイル時にすべての共有コードを含めて、.NET コンパイラの組み込み最適化機能を活用してください。

.NET CLI では、レイヤーの公開や、レイヤーを使用する C\$1 関数のデプロイに役立つコマンドがサポートされています。指定した Amazon S3 バケットにレイヤーを公開するには、自身の `.csproj` と同じディレクトリで次のコマンドを実行します。

```
dotnet lambda publish-layer <layer_name> --layer-type runtime-package-store --s3-bucket <s3_bucket_name>
```

その後、.NET CLI を使用して関数をデプロイする際に、次のコマンドで使用するレイヤーの ARN を指定します。

```
dotnet lambda deploy-function <function_name> --function-layers arn:aws:lambda:us-east-1:123456789012:layer:layer-name:1
```

Hello World 関数の完全な例については、[blank-csharp-with-layer](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-csharp-with-layer) のサンプルを参照してください。

# AWS SAM を使用した C\$1 Lambda 関数のデプロイ
<a name="csharp-package-sam"></a>

AWS Serverless Application Model (AWS SAM) は、AWS のサーバーレスアプリケーションの構築と実行のプロセスを合理化するのに役立つツールキットです。YAML または JSON テンプレートでアプリケーションのリソースを定義し、AWS SAM コマンドラインインターフェイス (AWS SAM CLI) を使用して、アプリケーションを構築、パッケージ化、デプロイします。AWS SAM テンプレートから Lambda 関数を構築すると、AWS SAM は関数コードと指定した任意の依存関係を含む .zip デプロイパッケージまたはコンテナイメージを自動的に作成します。そして、AWS SAM は [CloudFormation スタック](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacks.html)を使用して関数をデプロイします。AWS SAM を使用して Lambda 関数を構築およびデプロイする方法の詳細については、「AWS Serverless Application Model 開発者ガイドの」の「[AWS SAM の開始方法](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started.html)」を参照してください。

以下の手順は、AWS SAM を使用してサンプルの .NET Hello World アプリケーションをダウンロード、構築、およびデプロイする方法を示しています。このサンプルアプリケーションは、Lambda 関数と Amazon API Gateway エンドポイントを使用して基本的な API バックエンドを実装します。API Gateway エンドポイントに HTTP GET リクエストを送信すると、API Gateway が Lambda 関数を呼び出します。この関数は、リクエストを処理する Lambda 関数インスタンスの IP アドレスと共に「hello world」メッセージを返します。

AWS SAM を使用してアプリケーションを構築し、デプロイする場合、AWS SAM CLI は背後で `dotnet lambda package` コマンドを使用して、個々の Lambda 関数コードバンドルをパッケージ化します。

## 前提条件
<a name="csharp-package-sam-prerequisites"></a>

**.NET 8 SDK**  
[.NET 8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) SDK とランタイムをインストールします。

**AWS SAM CLI バージョン 1.39 以降**  
AWS SAM CLI の最新バージョンをインストールする方法については、「[AWS SAM CLI のインストール](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)」を参照してください。

## AWS SAM サンプルアプリケーションをデプロイする
<a name="csharp-package-sam-deploy"></a>

1. 次のコマンドを使用し、Hello World .NET テンプレートを使用して、アプリケーションを初期化します。

   ```
   sam init --app-template hello-world --name sam-app \
   --package-type Zip --runtime dotnet8
   ```

   このコマンドは、プロジェクトディレクトリに以下のファイルとディレクトリを作成します。

   ```
   └── sam-app
       ├── README.md
       ├── events
       │   └── event.json
       ├── omnisharp.json
       ├── samconfig.toml
       ├── src
       │   └── HelloWorld
       │       ├── Function.cs
       │       ├── HelloWorld.csproj
       │       └── aws-lambda-tools-defaults.json
       ├── template.yaml
       └── test
           └── HelloWorld.Test
               ├── FunctionTest.cs
               └── HelloWorld.Tests.csproj
   ```

1. `template.yaml file` が含まれるディレクトリに移動します。このファイルは、Lambda 関数や API Gateway API など、アプリケーションの AWS リソースを定義するテンプレートです。

   ```
   cd sam-app
   ```

1. アプリケーションのソースを構築するには、次のコマンドを実行します。

   ```
   sam build
   ```

1. AWS にアプリケーションをデプロイするには、次のコマンドを実行します。

   ```
   sam deploy --guided
   ```

   このコマンドは、次の一連のプロンプトを使用してアプリケーションをパッケージ化し、デプロイします。デフォルトのオプションを受け入れるには、[Enter] キーを押します。
**注記**  
**[HelloWorldFunction には権限が定義されていない場合がありますが、問題ありませんか?]** には、必ず `y` を入力してください。
   + **[スタック名]**: CloudFormation にデプロイするスタックの名前。この名前は AWS アカウントと AWS リージョンに対して一意である必要があります。
   + **[AWS リージョン]**: アプリをデプロイしたい AWS リージョン。
   + **[デプロイ前に変更を確認]**: [はい] を選択すると、AWS SAM がアプリケーションの変更をデプロイする前に、変更セットを手動でレビューできます。[いいえ] を選択すると、AWS SAM CLI はアプリケーションの変更を自動的にデプロイします。
   + **[SAM CLI の IAM ロールの作成を許可]**: この例の Hello World のものを含む、多くの AWS SAM テンプレートで AWS Identity and Access Management (IAM) ロールが作成され、Lambda 関数に他の AWS のサービスへのアクセス権限が付与されます。IAM ロールを作成または変更する CloudFormation スタックをデプロイする権限を付与するには、[はい] を選択します。
   + **[ロールバックを無効化]**: デフォルトでは、スタックの作成またはデプロイ中に AWS SAM でエラーが発生すると、スタックは以前のバージョンにロールバックされます。このデフォルトを受け入れるには [いいえ] を選択します。
   + **[HelloWorldFunction には権限が定義されていない場合がありますが、問題ありませんか?]**: [`y`] を入力します。
   + **[引数を samconfig.toml に保存]**: [はい] を選択して設定内容を保存します。今後は、パラメータなしで `sam deploy` を再実行して、アプリケーションに変更をデプロイできます。

1. アプリケーションのデプロイが完了すると、CLI は Hello World Lambda 関数の Amazon リソースネーム (ARN) と、その関数用に作成された IAM ロールを返します。API Gateway API のエンドポイントも表示されます。アプリケーションをテストするには、ブラウザでエンドポイントを開きます。次のようなレスポンスが表示されます。

   ```
   {"message":"hello world","location":"34.244.135.203"}
   ```

1. リソースを削除するには、次のコマンドを実行します。作成した API エンドポイントは、インターネット経由でアクセス可能なパブリックエンドポイントであることに注意してください。テスト後に、このエンドポイントを削除することを推奨します。

   ```
   sam delete
   ```

## 次のステップ
<a name="csharp-package-sam-next"></a>

AWS SAM を使用し、.NET を使用して Lambda 関数を構築し、デプロイする方法については、以下のリソースを参照してください。
+ [AWS Serverless Application Model (AWS SAM) 開発者ガイド](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html)
+ [Building Serverless .NET Applications with AWS Lambda and the SAM CLI](https://aws.amazon.com/blogs/dotnet/building-serverless-net-applications-with-aws-lambda-and-the-sam-cli/)

# AWS CDK を使用した C\$1 Lambda 関数のデプロイ
<a name="csharp-package-cdk"></a>

AWS Cloud Development Kit (AWS CDK) は、最新のプログラミング言語と .NET などのフレームワークを使用して、クラウドインフラストラクチャをコードとして定義するためのオープンソースソフトウェア開発フレームワークです。AWS CDK プロジェクトを実行して CloudFormation テンプレートを生成し、そのテンプレートを使用してコードをデプロイします。

AWS CDK を使用してサンプルの Hello World .NET アプリケーションを構築し、デプロイするには、以下のセクションの指示に従ってください。サンプルアプリケーションは、API Gateway エンドポイントと Lambda 関数で構成される基本的な API バックエンドを実装しています。エンドポイントに HTTP GET リクエストを送信すると、API Gateway によって Lambda 関数が呼び出されます。この関数は、リクエストを処理する Lambda インスタンスの IP アドレスと共に Hello World メッセージを返します。

## 前提条件
<a name="csharp-package-cdk-prereqs"></a>

**.NET 8 SDK**  
[.NET 8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) SDK とランタイムをインストールします。

**AWS CDK バージョン 2**  
AWS CDK の最新バージョンをインストールする方法については、「AWS Cloud Development Kit (AWS CDK) v2 開発者ガイド」の「[AWS CDK の開始方法](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html)」を参照してください。

## AWS CDK サンプルアプリケーションをデプロイする
<a name="csharp-package-cdk-deploy"></a>

1. サンプルアプリケーションのプロジェクトディレクトリを作成して、そこに移動します。

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

1. 以下のコマンドを実行して、新しい AWS CDK アプリケーションを初期化します。

   ```
   cdk init app --language csharp
   ```

   このコマンドは、プロジェクトディレクトリに以下のファイルとディレクトリを作成します。

   ```
   ├── README.md
   ├── cdk.json
   └── src
       ├── HelloWorld
       │   ├── GlobalSuppressions.cs
       │   ├── HelloWorld.csproj
       │   ├── HelloWorldStack.cs
       │   └── Program.cs
       └── HelloWorld.sln
   ```

1. `src` ディレクトリを開き、.NET CLI を使用して新しい Lambda 関数を作成します。これは、AWS CDK を使用してデプロイする関数です。この例では、`lambda.EmptyFunction` テンプレートを使用して、`HelloWorldLambda` という名前の Hello World 関数を作成します。

   ```
   cd src
   dotnet new lambda.EmptyFunction -n HelloWorldLambda
   ```

   このステップ完了後のプロジェクトディレクトリ内のディレクトリ構造は、次のようになります。

   ```
   ├── README.md
   ├── cdk.json
   └── src
       ├── HelloWorld
       │   ├── GlobalSuppressions.cs
       │   ├── HelloWorld.csproj
       │   ├── HelloWorldStack.cs
       │   └── Program.cs
       ├── HelloWorld.sln
       └── HelloWorldLambda
           ├── src
           │   └── HelloWorldLambda
           │       ├── Function.cs
           │       ├── HelloWorldLambda.csproj
           │       ├── Readme.md
           │       └── aws-lambda-tools-defaults.json
           └── test
               └── HelloWorldLambda.Tests
                   ├── FunctionTest.cs
                   └── HelloWorldLambda.Tests.csproj
   ```

1. `src/HelloWorld` ディレクトリの `HelloWorldStack.cs` ファイルを開きます。ファイルの内容を次のコードに置き換えます。

   ```
   using Amazon.CDK;
   using Amazon.CDK.AWS.Lambda;
   using Amazon.CDK.AWS.Logs;
   using Constructs;
   
   namespace CdkTest
   {
       public class HelloWorldStack : Stack
       {
           internal HelloWorldStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
           {
               var buildOption = new BundlingOptions()
               {
                   Image = Runtime.DOTNET_8.BundlingImage,
                   User = "root",
                   OutputType = BundlingOutput.ARCHIVED,
                   Command = new string[]{
               "/bin/sh",
                   "-c",
                   " dotnet tool install -g Amazon.Lambda.Tools"+
                   " && dotnet build"+
                   " && dotnet lambda package --output-package /asset-output/function.zip"
                   }
               };
   
                var helloWorldLambdaFunction = new Function(this, "HelloWorldFunction", new FunctionProps
               {
                   Runtime = Runtime.DOTNET_8,
                   MemorySize = 1024,
                   LogRetention = RetentionDays.ONE_DAY,
                   Handler = "HelloWorldLambda::HelloWorldLambda.Function::FunctionHandler",
                   Code = Code.FromAsset("./src/HelloWorldLambda/src/HelloWorldLambda", new Amazon.CDK.AWS.S3.Assets.AssetOptions
                   {
                       Bundling = buildOption
                   }),
               });
           }
       }
   }
   ```

   これは、アプリケーションコードをコンパイルしてバンドルするコードであり、Lambda 関数自体の定義でもあります。この `BundlingOptions` オブジェクトにより、zip ファイルの内容を生成するために使用される一連のコマンドと共に zip ファイルを作成できます。この場合、`dotnet lambda package` コマンドは zip ファイルのコンパイルと生成に使用されます。

1. アプリケーションをデプロイするには、次のコマンドを実行します。

   ```
   cdk deploy
   ```

1. .NET Lambda CLI を使用して、デプロイした Lambda 関数を呼び出します。

   ```
   dotnet lambda invoke-function HelloWorldFunction -p "hello world"
   ```

1. テストの完了後、作成したリソースは、保持することを希望しない限り削除できます。リソースを削除するには、次のコマンドを実行します。

   ```
   cdk destroy
   ```

## 次のステップ
<a name="csharp-package-cdk-next"></a>

AWS CDK を使用し、.NET を使用して Lambda 関数を構築し、デプロイする方法については、以下のリソースを参照してください。
+ [C\$1 で AWS CDK を操作](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-csharp.html)
+ [Build, package, and publish .NET C\$1 Lambda functions with the AWS CDK](https://aws.amazon.com/blogs/modernizing-with-aws/build-package-publish-dotnet-csharp-lambda-functions-aws-cdk/)

# ASP.NET アプリケーションのデプロイ
<a name="csharp-package-asp"></a>

イベント駆動型関数をホストするだけでなく、.NET と Lambda を組み合わせて軽量な ASP.NET アプリケーションをホストすることもできます。`Amazon.Lambda.AspNetCoreServer` NuGet パッケージを使用して ASP.NET アプリケーションを構築し、デプロイすることができます。このセクションでは、.NET Lambda CLI ツールを使用して ASP.NET ウェブ API を Lambda にデプロイする方法について説明します。

**Topics**
+ [

## 前提条件
](#csharp-package-asp-prerequisites)
+ [

## ASP.NET ウェブ API を Lambda にデプロイする
](#csharp-package-asp-deploy-api)
+ [

## ASP.NET の最小限の API を Lambda にデプロイする
](#csharp-package-asp-deploy-minimal)

## 前提条件
<a name="csharp-package-asp-prerequisites"></a>

**.NET 8 SDK**  
[.NET 8](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) SDK と ASP.NET Core ランタイムをインストールします。

**Amazon.Lambda.Tools**  
Lambda 関数を作成するには、[https://www.nuget.org/packages/Amazon.Lambda.Tools](https://www.nuget.org/packages/Amazon.Lambda.Tools) [.NET Global Tools 拡張機能](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/)を使用します。Amazon.Lambda.Tools をインストールするには、以下のコマンドを実行します。  

```
dotnet tool install -g Amazon.Lambda.Tools
```
Amazon.Lambda.Tools .NET CLI 拡張機能の詳細については、GitHub の「[AWS Extensions for .NET CLI](https://github.com/aws/aws-extensions-for-dotnet-cli)」リポジトリを参照してください。

**Amazon.Lambda.Templates**  
Lambda 関数コードを生成するには、[https://www.nuget.org/packages/Amazon.Lambda.Templates](https://www.nuget.org/packages/Amazon.Lambda.Templates) NuGet パッケージを使用します。このテンプレートパッケージをインストールするには、以下のコマンドを実行します。  

```
dotnet new --install Amazon.Lambda.Templates
```

## ASP.NET ウェブ API を Lambda にデプロイする
<a name="csharp-package-asp-deploy-api"></a>

ASP.NET を使用してウェブ API をデプロイするには、.NET Lambda テンプレートを使用して新しいウェブ API プロジェクトを作成します。次のコマンドを使用して、新しい ASP.NET ウェブ API プロジェクトを初期化します。このコマンド例では、プロジェクトに `AspNetOnLambda` という名前を付けています。

```
dotnet new serverless.AspNetCoreWebAPI -n AspNetOnLambda
```

このコマンドは、プロジェクトディレクトリに以下のファイルとディレクトリを作成します。

```
.
└── AspNetOnLambda
    ├── src
    │   └── AspNetOnLambda
    │       ├── AspNetOnLambda.csproj
    │       ├── Controllers
    │       │   └── ValuesController.cs
    │       ├── LambdaEntryPoint.cs
    │       ├── LocalEntryPoint.cs
    │       ├── Readme.md
    │       ├── Startup.cs
    │       ├── appsettings.Development.json
    │       ├── appsettings.json
    │       ├── aws-lambda-tools-defaults.json
    │       └── serverless.template
    └── test
        └── AspNetOnLambda.Tests
            ├── AspNetOnLambda.Tests.csproj
            ├── SampleRequests
            │   └── ValuesController-Get.json
            ├── ValuesControllerTests.cs
            └── appsettings.json
```

Lambda が関数を呼び出すとき、使用するエントリポイントは `LambdaEntryPoint.cs` ファイルです。.NET Lambda テンプレートによって作成されたファイルには、次のコードが含まれています。

```
namespace AspNetOnLambda;

public class LambdaEntryPoint : Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction
{
    protected override void Init(IWebHostBuilder builder)
    {
        builder
            .UseStartup≪Startup≫();
    }

    protected override void Init(IHostBuilder builder)
    {
    }
}
```

Lambda が使用するエントリポイントは、`Amazon.Lambda.AspNetCoreServer` パッケージ内の 3 つの基本クラスのいずれかから継承する必要があります。この 3 つの基本クラスは以下のとおりです。
+ `APIGatewayProxyFunction`
+ `APIGatewayHttpApiV2ProxyFunction`
+ `ApplicationLoadBalancerFunction`

提供されている .NET Lambda テンプレートを使用して `LambdaEntryPoint.cs` ファイルを作成するときに使用されるデフォルトクラスは `APIGatewayProxyFunction` です。関数で使用する基本クラスは、Lambda 関数の前にある API レイヤーによって異なります。

3 つの基本クラスにはそれぞれ、`FunctionHandlerAsync` という名前のパブリックメソッドが含まれています。このメソッドの名前は、Lambda が関数を呼び出すために使用する[ハンドラー文字列](csharp-handler.md#csharp-class-library-handlers)の一部になります。この `FunctionHandlerAsync` メソッドは、受信イベントペイロードを正しい ASP.NET 形式に変換し、ASP.NET レスポンスを Lambda レスポンスペイロードに戻します。示されているサンプル `AspNetOnLambda` プロジェクトでは、ハンドラー文字列は次のようになります。

```
AspNetOnLambda::AspNetOnLambda.LambdaEntryPoint::FunctionHandlerAsync
```

API を Lambda にデプロイするには、次のコマンドを実行して、ソースコードファイルが含まれるディレクトリに移動し、CloudFormation を使用して関数をデプロイします。

```
cd AspNetOnLambda/src/AspNetOnLambda
dotnet lambda deploy-serverless
```

**ヒント**  
`dotnet lambda deploy-serverless` コマンドを使用して API をデプロイすると、CloudFormation によりデプロイ時に指定したスタック名に基づき Lambda 関数に名前が付けられます。Lambda 関数にカスタム名を付けるには、`serverless.template` ファイルを編集して `AWS::Serverless::Function` リソースに `FunctionName` プロパティを追加します。詳細については、「CloudFormation ユーザーガイド」の「[Name タイプ](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html)」を参照してください。

## ASP.NET の最小限の API を Lambda にデプロイする
<a name="csharp-package-asp-deploy-minimal"></a>

ASP.NET の最小限の API を Lambda にデプロイするには、.NET Lambda テンプレートを使用して、新しい最小限の API プロジェクトを作成します。次のコマンドを使用して、新しい最小限の API プロジェクトを初期化します。この例では、プロジェクトに `MinimalApiOnLambda` という名前を付けています。

```
dotnet new serverless.AspNetCoreMinimalAPI -n MinimalApiOnLambda
```

このコマンドは、プロジェクトディレクトリに以下のファイルとディレクトリを作成します。

```
└── MinimalApiOnLambda
    └── src
        └── MinimalApiOnLambda
            ├── Controllers
            │   └── CalculatorController.cs
            ├── MinimalApiOnLambda.csproj
            ├── Program.cs
            ├── Readme.md
            ├── appsettings.Development.json
            ├── appsettings.json
            ├── aws-lambda-tools-defaults.json
            └── serverless.template
```

`Program.cs` ファイルには次のコードが含まれています。

```
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();

// Add AWS Lambda support. When application is run in Lambda Kestrel is swapped out as the web server with Amazon.Lambda.AspNetCoreServer. This
// package will act as the webserver translating request and responses between the Lambda event source and ASP.NET Core.
builder.Services.AddAWSLambdaHosting(LambdaEventSource.RestApi);

var app = builder.Build();


app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.MapGet("/", () => "Welcome to running ASP.NET Core Minimal API on AWS Lambda");

app.Run();
```

最小限の API を Lambda で実行するように設定するには、Lambda と ASP.NET Core 間のリクエストとレスポンスが正しく変換されるように、このコードを編集する必要がある場合があります。デフォルトでは、この関数は REST API イベントソース用に設定されます。HTTP API または Application Load Balancer の場合は、以下のオプションのいずれかに `(LambdaEventSource.RestApi)` を置き換えてください。
+ `(LambdaEventSource.HttpAPi)`
+ `(LambdaEventSource.ApplicationLoadBalancer)`

最小限の API を Lambda にデプロイするには、次のコマンドを実行して、ソースコードファイルが含まれるディレクトリに移動し、CloudFormation を使用して関数をデプロイします。

```
cd MinimalApiOnLambda/src/MinimalApiOnLambda
dotnet lambda deploy-serverless
```

# .NET Lambda 関数のレイヤーを操作する
<a name="dotnet-layers"></a>

.NET で書かれた Lambda 関数の依存関係を[レイヤー](chapter-layers.md)で管理する方法はお勧めしません。.NET はコンパイル済み言語なので、関数は[初期化](lambda-runtime-environment.md#runtimes-lifecycle-ib)フェーズで共有アセンブリを手動でメモリに読み込む必要があり、コールドスタート時間が長くなる可能性があります。レイヤーを使用すると、デプロイプロセスが複雑になるだけでなく、組み込みのコンパイラ最適化機能を活用できなくなります。

.NET ハンドラーで外部の依存関係を使用するには、コンパイル時にその依存関係をデプロイパッケージに直接含めます。デプロイプロセスが簡素化されるうえ、組み込みの .NET コンパイラ最適化機能を活用できます。NuGet パッケージ のように依存関係を関数にインポートして使用する方法の例については、「[C\$1 の Lambda 関数ハンドラーの定義](csharp-handler.md)」を参照してください。

# コンテナイメージを使用して.NET の Lambda 関数をデプロイする
<a name="csharp-image"></a>

.NET Lambda 関数のコンテナイメージを構築するには 3 つの方法があります。
+ [.NET の AWS ベースイメージを使用する](#csharp-image-instructions)

  [AWS ベースイメージ](images-create.md#runtimes-images-lp)には、言語ランタイム、Lambda と関数コード間のやり取りを管理するランタイムインターフェースクライアント、ローカルテスト用のランタイムインターフェースエミュレーターがあらかじめロードされています。
+ [AWS の OS 専用ベースイメージを使用する](images-create.md#runtimes-images-provided)

  [AWS OS 専用ベースイメージ](https://gallery.ecr.aws/lambda/provided)には、Amazon Linux ディストリビューションおよび[ランタイムインターフェイスエミュレータ](https://github.com/aws/aws-lambda-runtime-interface-emulator/)が含まれています。これらのイメージは、[Go](go-image.md#go-image-provided) や [Rust](lambda-rust.md) などのコンパイル済み言語や、Lambda がベースイメージを提供していない言語または言語バージョン (Node.js 19 など) のコンテナイメージの作成によく使用されます。OS 専用のベースイメージを使用して[カスタムランタイム](runtimes-custom.md)を実装することもできます。イメージに Lambda との互換性を持たせるには、[.NET のランタイムインターフェイスクライアント](#csharp-image-clients)をイメージに含める必要があります。
+ [非 AWS ベースイメージを使用する](#csharp-image-clients)

  Alpine Linux や Debian など、別のコンテナレジストリの代替ベースイメージを使用することもできます。組織が作成したカスタムイメージを使用することもできます。イメージに Lambda との互換性を持たせるには、[.NET のランタイムインターフェイスクライアント](#csharp-image-clients)をイメージに含める必要があります。

**ヒント**  
Lambda コンテナ関数がアクティブになるまでの時間を短縮するには、「Docker ドキュメント」の「[マルチステージビルドを使用する](https://docs.docker.com/build/building/multi-stage/)」を参照してください。効率的なコンテナイメージを構築するには、「[Dockerfiles を記述するためのベストプラクティス](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)」に従ってください。

このページでは、Lambda のコンテナイメージを構築、テスト、デプロイする方法について説明します。

**Topics**
+ [

## .NET 用の AWS ベースイメージ
](#csharp-image-base)
+ [

## .NET の AWS ベースイメージを使用する
](#csharp-image-instructions)
+ [

## ランタイムインターフェイスクライアントで代替ベースイメージを使用する
](#csharp-image-clients)

## .NET 用の AWS ベースイメージ
<a name="csharp-image-base"></a>

AWS には、.NET 用に次のようなベースイメージが利用できます。


| タグ | ランタイム | オペレーティングシステム | Dockerfile | 非推奨 | 
| --- | --- | --- | --- | --- | 
| 10 | .NET 10 | Amazon Linux 2023 | [GitHub 上の .NET 10 用の Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/dotnet10/Dockerfile.dotnet10) |   2028 年 11 月 14 日   | 
| 9 | .NET 9 | Amazon Linux 2023 | [GitHub 上の .NET 9 用の Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/dotnet9/Dockerfile.dotnet9) |   2026 年 11 月 10 日   | 
| 8 | .NET 8 | Amazon Linux 2023 | [GitHub 上の .NET 8 用の Dockerfile](https://github.com/aws/aws-lambda-base-images/blob/dotnet8/Dockerfile.dotnet8) |   2026 年 11 月 10 日   | 

Amazon ECR リポジトリ: [gallery.ecr.aws/lambda/dotnet](https://gallery.ecr.aws/lambda/dotnet)

## .NET の AWS ベースイメージを使用する
<a name="csharp-image-instructions"></a>

### 前提条件
<a name="dotnet-csharp-image-prerequisites"></a>

このセクションの手順を完了するには、以下が必要です。
+ 「[.NET SDK](https://dotnet.microsoft.com/download)」 — 以下の手順では .NET 8 ベースイメージを使用します。.NET のバージョンが、Dockerfile で指定した「[ベースイメージ](https://gallery.ecr.aws/lambda/dotnet)」のバージョンと一致することを確認してください。
+ [Docker](https://docs.docker.com/get-docker) (最小バージョン 25.0.0)
+ Docker [buildx プラグイン](https://github.com/docker/buildx/blob/master/README.md)。

### ベースイメージを使用したイメージの作成およびデプロイ
<a name="dotnet-image-create"></a>

次のステップでは、「[Amazon.Lambda.Templates](https://github.com/aws/aws-lambda-dotnet#dotnet-cli-templates)」および「[Amazon.Lambda.Tools](https://github.com/aws/aws-extensions-for-dotnet-cli#aws-lambda-amazonlambdatools)」を使用して .NET プロジェクトを作成します。次に、Docker イメージを構築し、イメージを Amazon ECR にアップロードして Lambda 関数にデプロイします。

1. [Amazon.Lambda.Templates](https://github.com/aws/aws-lambda-dotnet#dotnet-cli-templates) の NuGet パッケージをインストールします。

   ```
   dotnet new install Amazon.Lambda.Templates
   ```

1. `lambda.image.EmptyFunction` テンプレートを使用して.NET プロジェクトを作成します。

   ```
   dotnet new lambda.image.EmptyFunction --name MyFunction --region us-east-1
   ```

   このプロジェクトファイルは `MyFunction/src/MyFunction` ディレクトリに保存されます。
   + **aws-lambda-tools-defaults.json**: Lambda 関数をデプロイするためのコマンドラインオプションを指定します。
   + **Function.cs**: Lambda ハンドラの関数コード。これは、デフォルトの `Amazon.Lambda.Core` ライブラリおよびデフォルトの `LambdaSerializer` 属性が含まれる C\$1 テンプレートです。シリアル化の要件およびオプションの詳細は、[C\$1 Lambda 関数のシリアル化](csharp-handler.md#csharp-handler-serializer) を参照してください。提供されるコードをテストに使用することも、独自のコードで置き換えることもできます。
   + **MyFunction.csproj**: アプリケーションを構成するファイルおよびアセンブリを一覧表示する .NET 「[プロジェクトファイル](https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview#project-files)」。
   + **Dockerfile**: 提供される Dockerfile をテストに使用したり、独自の Dockerfile に置き換えたりすることができます。独自のものを使用する場合、必ず次のことを行ってください。
     + `FROM` プロパティを「[ベースイメージの URI](https://gallery.ecr.aws/lambda/dotnet)」に設定します。ベースイメージと `MyFunction.csproj` ファイルの `TargetFramework` は、どちらも同じ .NET バージョンを使用する必要があります。例えば、.NET 9 を使用する場合は、次のようにします。
       + Dockerfile: `FROM public.ecr.aws/lambda/dotnet:9`
       + MyFunction.csproj: `<TargetFramework>net9.0</TargetFramework>`
     + `CMD` 引数を Lambda 関数ハンドラーに設定します。これは「`aws-lambda-tools-defaults.json`」内の `image-command` と一致している必要があります。

1. Amazon.Lambda.Tools の「[.NET Global Tool](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/)」をインストールします。

   ```
   dotnet tool install -g Amazon.Lambda.Tools
   ```

   Amazon.Lambda.Tools が既にインストールされている場合、最新バージョンであることを確認します。

   ```
   dotnet tool update -g Amazon.Lambda.Tools
   ```

1. まだディレクトリが MyFunction ではない場合、ディレクトリを `MyFunction/src/MyFunction` に変更します。

   ```
   cd src/MyFunction
   ```

1. Amazon.Lambda.Tools を使用して Docker イメージを構築し、新しい Amazon ECR リポジトリにプッシュして Lambda 関数をデプロイします。

   `--function-role` では、Amazon リソースネーム（ARN）ではなく、関数の「[実行ロール](lambda-intro-execution-role.md)」のロール名を指定します。例えば、`lambda-role`。

   ```
   dotnet lambda deploy-function MyFunction --function-role lambda-role
   ```

   Amazon.Lambda.Tools の .NET Global Tool の詳細については、GitHub の [AWS Extensions for .NET CLI](https://github.com/aws/aws-extensions-for-dotnet-cli) リポジトリを参照してください。

1. 関数を呼び出します。

   ```
   dotnet lambda invoke-function MyFunction --payload "Testing the function"
   ```

   すべてが成功すると、次のようなレスポンスが表示されます。

   ```
   Payload:
   {"Lower":"testing the function","Upper":"TESTING THE FUNCTION"}
   
   Log Tail:
   INIT_REPORT Init Duration: 9999.81 ms   Phase: init     Status: timeout
   START RequestId: 12378346-f302-419b-b1f2-deaa1e8423ed Version: $LATEST
   END RequestId: 12378346-f302-419b-b1f2-deaa1e8423ed
   REPORT RequestId: 12378346-f302-419b-b1f2-deaa1e8423ed  Duration: 3173.06 ms    Billed Duration: 3174 ms        Memory Size: 512 MB     Max Memory Used: 24 MB
   ```

1. Lambda 関数を削除します。

   ```
   dotnet lambda delete-function MyFunction
   ```

## ランタイムインターフェイスクライアントで代替ベースイメージを使用する
<a name="csharp-image-clients"></a>

[OS 専用ベースイメージ](images-create.md#runtimes-images-provided)または代替のベースイメージを使用する場合、イメージにランタイムインターフェイスクライアントを含める必要があります。ランタイムインターフェイスクライアントは、Lambda と関数コード間の相互作用を管理する [ランタイム API](runtimes-api.md) を拡張します。

次の例は、非 AWS ベースイメージを使用して .NET 用のコンテナイメージを構築する方法と、.NET 用の Lambda ランタイムインターフェースクライアントである [Amazon.Lambda.RuntimeSupport パッケージ](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.RuntimeSupport/README.md#using-amazonlambdaruntimesupport-as-a-class-library)を追加する方法を示しています。Dockerfile の例では、Microsoft .NET 8 ベースイメージを使用します。

### 前提条件
<a name="dotnet-csharp-alt-prerequisites"></a>

このセクションの手順を完了するには、以下が必要です。
+ 「[.NET SDK](https://dotnet.microsoft.com/download)」 — 以下の手順では .NET 9 ベースイメージを使用します。.NET のバージョンが、Dockerfile で指定した「ベースイメージ」のバージョンと一致することを確認してください。
+ [Docker](https://docs.docker.com/get-docker) (最小バージョン 25.0.0)
+ Docker [buildx プラグイン](https://github.com/docker/buildx/blob/master/README.md)。

### 代替的なベースイメージを使用したイメージの作成およびデプロイ
<a name="dotnet-alt-create"></a>

1. [Amazon.Lambda.Templates](https://github.com/aws/aws-lambda-dotnet#dotnet-cli-templates) の NuGet パッケージをインストールします。

   ```
   dotnet new install Amazon.Lambda.Templates
   ```

1. `lambda.CustomRuntimeFunction` テンプレートを使用して.NET プロジェクトを作成します。このテンプレートには [Amazon.Lambda.RuntimeSupport](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.RuntimeSupport/README.md#using-amazonlambdaruntimesupport-as-a-class-library) パッケージが含まれています。

   ```
   dotnet new lambda.CustomRuntimeFunction --name MyFunction --region us-east-1
   ```

1. `MyFunction/src/MyFunction` ディレクトリに移動します。ここにプロジェクトファイルが保存されます。次のファイルを確認します。
   + **aws-lambda-tools-defaults.json** - このファイルで、Lambda 関数をデプロイするときにコマンドラインオプションを指定します。
   + **Function.cs** — コードには、`Amazon.Lambda.RuntimeSupport` ライブラリをブートストラップとして初期化する `Main` メソッドを持つクラスが含まれています。`Main` メソッドは、関数のプロセスのエントリポイントです。この `Main` メソッドは、ブートストラップが処理できるラッパーで関数ハンドラをラップします。詳細については、GitHub リポジトリの「[Amazon.Lambda.RuntimeSupport をクラスライブラリとして使用する](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.RuntimeSupport/README.md#using-amazonlambdaruntimesupport-as-a-class-library)」を参照してください。
   + **MyFunction.csproj** - アプリケーションを構成するファイルおよびアセンブリを一覧表示する .NET 「[プロジェクトファイル](https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview#project-files)」。
   + **Readme.md** — このファイルには、サンプル Lambda 関数に関する詳細が含まれています。

1. `aws-lambda-tools-defaults.json` ファイルを開き、次の行を追加します。

   ```
     "package-type": "image",
     "docker-host-build-output-dir": "./bin/Release/lambda-publish"
   ```
   + **package-type**: デプロイパッケージをコンテナイメージとして定義します。
   + **docker-host-build-output-dir**: ビルドプロセスの出力ディレクトリを設定します。  
**Example aws-lambda-tools-defaults.json**  

   ```
   {
     "Information": [
       "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
       "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
       "dotnet lambda help",
       "All the command line options for the Lambda command can be specified in this file."
     ],
     "profile": "",
     "region": "us-east-1",
     "configuration": "Release",
     "function-runtime": "provided.al2023",
     "function-memory-size": 256,
     "function-timeout": 30,
     "function-handler": "bootstrap",
     "msbuild-parameters": "--self-contained true",
     "package-type": "image",
     "docker-host-build-output-dir": "./bin/Release/lambda-publish"
   }
   ```

1. `MyFunction/src/MyFunction` ディレクトリに Dockerfile を作成します。次の Dockerfile の例では、[AWS ベースイメージ](#csharp-image-base)の代わりに Microsoft .NET ベースイメージを使用します。
   + ベースイメージ識別子に `FROM` プロパティを設定します。ベースイメージと `MyFunction.csproj` ファイルの `TargetFramework` は、どちらも同じ .NET バージョンを使用する必要があります。
   + `COPY` コマンドを使用して、関数を `/var/task` ディレクトリにコピーします。
   + `ENTRYPOINT` を、Docker コンテナの起動時に実行させるモジュールに設定します。この場合、モジュールは `Amazon.Lambda.RuntimeSupport` ライブラリを初期化するブートストラップです。

   この例の Dockerfile には [USER 命令](https://docs.docker.com/reference/dockerfile/#user)が含まれていないことに注意してください。コンテナイメージを Lambda にデプロイすると、最小特権のアクセス許可を付与したデフォルトの Linux ユーザーを Lambda が自動的に定義します。これは標準の Docker 動作とは異なります。標準の動作とは、`USER` 命令を指定しなかったときに `root` ユーザーのデフォルトとなる動作のことです。  
**Example Dockerfile**  

   ```
   # You can also pull these images from DockerHub amazon/aws-lambda-dotnet:8
   FROM mcr.microsoft.com/dotnet/runtime:9.0
   
   # Set the image's internal work directory
   WORKDIR /var/task
     
   # Copy function code to Lambda-defined environment variable
   COPY "bin/Release/net9.0/linux-x64"  .
     
   # Set the entrypoint to the bootstrap
   ENTRYPOINT ["/usr/bin/dotnet", "exec", "/var/task/bootstrap.dll"]
   ```

1. Amazon.Lambda.Tools の「[.NET Global Tool](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/)」拡張機能をインストールします。

   ```
   dotnet tool install -g Amazon.Lambda.Tools
   ```

   Amazon.Lambda.Tools が既にインストールされている場合、最新バージョンであることを確認します。

   ```
   dotnet tool update -g Amazon.Lambda.Tools
   ```

1. Amazon.Lambda.Tools を使用して Docker イメージを構築し、新しい Amazon ECR リポジトリにプッシュして Lambda 関数をデプロイします。

   `--function-role` では、Amazon リソースネーム（ARN）ではなく、関数の「[実行ロール](lambda-intro-execution-role.md)」のロール名を指定します。例えば、`lambda-role`。

   ```
   dotnet lambda deploy-function MyFunction --function-role lambda-role
   ```

   Amazon.Lambda.Tools の .NET CLI 拡張機能の詳細については、GitHub の [AWS Extensions for .NET CLI](https://github.com/aws/aws-extensions-for-dotnet-cli) リポジトリを参照してください。

1. 関数を呼び出します。

   ```
   dotnet lambda invoke-function MyFunction --payload "Testing the function"
   ```

   すべてが成功すると、次のメッセージが表示されます。

   ```
   Payload:
   "TESTING THE FUNCTION"
   
   Log Tail:
   START RequestId: id Version: $LATEST
   END RequestId: id
   REPORT RequestId: id  Duration: 0.99 ms       Billed Duration: 1 ms         Memory Size: 256 MB     Max Memory Used: 12 MB
   ```

1. Lambda 関数を削除する

   ```
   dotnet lambda delete-function MyFunction
   ```

# .NET Lambda 関数コードをネイティブランタイム形式にコンパイルする
<a name="dotnet-native-aot"></a>

.NET 8 はネイティブ ahead-of-time (AOT) コンパイルをサポートします。ネイティブ AOT を使用することで、Lambda 関数コードをネイティブなランタイム形式にコンパイルできるので、実行時に .NET コードをコンパイルする必要がなくなります。ネイティブ AOT コンパイルは、.NET で記述する Lambda 関数のコールドスタート時間を短縮できます。詳細については、AWS コンピューティングブログの「[Introducing the .NET 8 runtime for AWS Lambda](https://aws.amazon.com/blogs/compute/introducing-the-net-8-runtime-for-aws-lambda/)」を参照してください。

**Topics**
+ [

## Lambda ランタイム
](#dotnet-native-aot-runtime)
+ [

## 前提条件
](#dotnet-native-aot-prerequisites)
+ [

## 使用開始
](#dotnet-native-aot-getting-started)
+ [

## シリアル化
](#dotnet-native-aot-serialization)
+ [

## トリミング
](#dotnet-native-aot-trimming)
+ [

## トラブルシューティング
](#dotnet-native-aot-troubleshooting)

## Lambda ランタイム
<a name="dotnet-native-aot-runtime"></a>

ネイティブ AOT コンパイルで構築された Lambda 関数をデプロイするには、 マネージド .NET 8 Lambda ランタイムを使用します。このランタイムは、x86\$164 アーキテクチャと arm64 アーキテクチャの両方の使用をサポートします。

AOT を使用せずに .NET Lambda 関数をデプロイすると、アプリケーションが中間言語 (IL) コードにコンパイルされます。実行時、Lambda ランタイム just-in-time (JIT) コンパイラが、必要に応じて IL コードを取得してマシンコードにコンパイルします。ネイティブ AOT で事前にコンパイルされた Lambda 関数では、関数をデプロイするときにコードをマシンコードにコンパイルするため、Lambda ランタイムの .NET ランタイムや SDK に依存しずに、実行前にコードをコンパイルできます。

AOT の制限の 1 つは、アプリケーションコードを、.NET 8 ランタイムが使用するのと同じ Amazon Linux 2023 (AL2023) オペレーティングシステムを使用する環境でコンパイルする必要があることです。.NET Lambda CLI には、AL2023 イメージを使用して Docker コンテナでアプリケーションをコンパイルする機能があります。

アーキテクチャ間の互換性に関する潜在的な問題を避けるため、関数用に設定したのと同じプロセッサアーキテクチャの環境でコードをコンパイルすることを強くお勧めします。クロスアーキテクチャコンパイルの制限の詳細については、Microsoft .NET ドキュメントの「[クロスコンパイル](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/cross-compile)」を参照してください。

## 前提条件
<a name="dotnet-native-aot-prerequisites"></a>

**Docker**  
ネイティブ AOT を使用するには、関数コードを、 ランタイムと同じ AL2023 オペレーティングシステムの環境でコンパイルする必要があります。以下のセクションで説明する .NET CLI コマンドは、Docker を使用して AL2023 環境で Lambda 関数を開発および構築します。

**.NET 8 SDK**  
ネイティブ AOT コンパイルは .NET 8 の機能です。ビルドマシンには、ランタイムだけでなく、[.NET 8 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) もインストールする必要があります。

**Amazon.Lambda.Tools**  
Lambda 関数を作成するには、[https://www.nuget.org/packages/Amazon.Lambda.Tools](https://www.nuget.org/packages/Amazon.Lambda.Tools) [.NET Global Tools 拡張機能](https://aws.amazon.com/blogs/developer/net-core-global-tools-for-aws/)を使用します。Amazon.Lambda.Tools をインストールするには、以下のコマンドを実行します。  

```
dotnet tool install -g Amazon.Lambda.Tools
```
Amazon.Lambda.Tools .NET CLI 拡張機能の詳細については、GitHub の「[AWS Extensions for .NET CLI](https://github.com/aws/aws-extensions-for-dotnet-cli)」リポジトリを参照してください。

**Amazon.Lambda.Templates**  
Lambda 関数コードを生成するには、[https://www.nuget.org/packages/Amazon.Lambda.Templates](https://www.nuget.org/packages/Amazon.Lambda.Templates) NuGet パッケージを使用します。このテンプレートパッケージをインストールするには、以下のコマンドを実行します。  

```
dotnet new install Amazon.Lambda.Templates
```

## 使用開始
<a name="dotnet-native-aot-getting-started"></a>

.NET Global CLI と AWS Serverless Application Model (AWS SAM) はどちらも、ネイティブ AOT を使用してアプリケーションを構築するための開始用テンプレートを提供します。最初のネイティブ AOT Lambda 関数を構築するには、以下の手順を実行します。

**ネイティブ AOT コンパイル済み Lambda 関数を初期化してデプロイするには**

1. ネイティブ AOT テンプレートを使用して新しいプロジェクトを初期化し、作成した `.cs` ファイルと `.csproj` ファイルが含まれるディレクトリに移動します。この例では、関数に `NativeAotSample` という名前を付けています。

   ```
   dotnet new lambda.NativeAOT -n NativeAotSample
   cd ./NativeAotSample/src/NativeAotSample
   ```

   ネイティブ AOT テンプレートによって作成された `Function.cs` ファイルには、次の関数コードが含まれています。

   ```
   using Amazon.Lambda.Core;
   using Amazon.Lambda.RuntimeSupport;
   using Amazon.Lambda.Serialization.SystemTextJson;
   using System.Text.Json.Serialization;
   
   namespace NativeAotSample;
   
   public class Function
   {
       /// <summary>
       /// The main entry point for the Lambda function. The main function is called once during the Lambda init phase. It
       /// initializes the .NET Lambda runtime client passing in the function handler to invoke for each Lambda event and
       /// the JSON serializer to use for converting Lambda JSON format to the .NET types.
       /// </summary>
       private static async Task Main()
       {
           Func<string, ILambdaContext, string> handler = FunctionHandler;
           await LambdaBootstrapBuilder.Create(handler, new SourceGeneratorLambdaJsonSerializer<LambdaFunctionJsonSerializerContext>())
               .Build()
               .RunAsync();
       }
   
       /// <summary>
       /// A simple function that takes a string and does a ToUpper.
       ///
       /// To use this handler to respond to an AWS event, reference the appropriate package from
       /// https://github.com/aws/aws-lambda-dotnet#events
       /// and change the string input parameter to the desired event type. When the event type
       /// is changed, the handler type registered in the main method needs to be updated and the LambdaFunctionJsonSerializerContext
       /// defined below will need the JsonSerializable updated. If the return type and event type are different then the
       /// LambdaFunctionJsonSerializerContext must have two JsonSerializable attributes, one for each type.
       ///
       // When using Native AOT extra testing with the deployed Lambda functions is required to ensure
       // the libraries used in the Lambda function work correctly with Native AOT. If a runtime
       // error occurs about missing types or methods the most likely solution will be to remove references to trim-unsafe
       // code or configure trimming options. This sample defaults to partial TrimMode because currently the AWS
       // SDK for .NET does not support trimming. This will result in a larger executable size, and still does not
       // guarantee runtime trimming errors won't be hit.
       /// </summary>
       /// <param name="input"></param>
       /// <param name="context"></param>
       /// <returns></returns>
       public static string FunctionHandler(string input, ILambdaContext context)
       {
           return input.ToUpper();
       }
   }
   
   /// <summary>
   /// This class is used to register the input event and return type for the FunctionHandler method with the System.Text.Json source generator.
   /// There must be a JsonSerializable attribute for each type used as the input and return type or a runtime error will occur
   /// from the JSON serializer unable to find the serialization information for unknown types.
   /// </summary>
   [JsonSerializable(typeof(string))]
   public partial class LambdaFunctionJsonSerializerContext : JsonSerializerContext
   {
       // By using this partial class derived from JsonSerializerContext, we can generate reflection free JSON Serializer code at compile time
       // which can deserialize our class and properties. However, we must attribute this class to tell it what types to generate serialization code for.
       // See https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-source-generation
   ```

   ネイティブ AOT は、アプリケーションを単一のネイティブバイナリにコンパイルします。このバイナリのエントリポイントは `static Main` メソッドです。`static Main` 内部では、Lambda ランタイムがブートストラップされ、`FunctionHandler` メソッドが設定されます。ランタイムブートストラップの一部として、ソース生成のシリアライザーは `new SourceGeneratorLambdaJsonSerializer<LambdaFunctionJsonSerializerContext>()` を使用して設定されます。

1. アプリケーションを Lambda にデプロイするには、Docker がローカル環境で実行されていることを確認し、次のコマンドを実行します。

   ```
   dotnet lambda deploy-function
   ```

   バックグラウンドでは、.NET Global CLI が AL2023 Docker イメージをダウンロードし、実行中のコンテナ内でアプリケーションコードをコンパイルしています。コンパイルされたバイナリは、Lambda にデプロイされる前にローカルファイルシステムに出力されます。

1. 次のコマンドを実行して関数をテストします。`<FUNCTION_NAME>` を、デプロイウィザードで関数に選択した名前に置き換えます。

   ```
   dotnet lambda invoke-function <FUNCTION_NAME> --payload "hello world"
   ```

   CLI からの応答には、コールドスタートのパフォーマンスの詳細 (初期化時間) と関数呼び出しの合計実行時間が含まれます。

1. 前の手順で作成した AWS リソースを削除するには、次のコマンドを実行します。`<FUNCTION_NAME>` を、デプロイウィザードで関数に選択した名前に置き換えます。使用しなくなった AWS リソースを削除することで、AWS アカウントに請求される料金の発生を防ぎます。

   ```
   dotnet lambda delete-function <FUNCTION_NAME>
   ```

## シリアル化
<a name="dotnet-native-aot-serialization"></a>

ネイティブ AOT を使用して Lambda に関数をデプロイするには、関数コードで[ソース生成のシリアル化](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation-modes?pivots=dotnet-8-0)を使用する必要があります。ランタイムリフレクションを使用し、シリアル化のためにオブジェクトプロパティにアクセスするのに必要なメタデータを収集する代わりに、ソースジェネレーターは、アプリケーションの構築時にコンパイルされる C\$1 ソースファイルを生成します。ソース生成のシリアライザーを正しく設定するには、関数が使用する入力オブジェクトと出力オブジェクト、およびカスタムタイプが含まれていることを確認します。例えば、API Gateway REST API からイベントを受信してカスタム `Product` タイプを返す Lambda 関数には、次のように定義されたシリアライザーが含まれます。

```
[JsonSerializable(typeof(APIGatewayProxyRequest))]
[JsonSerializable(typeof(APIGatewayProxyResponse))]
[JsonSerializable(typeof(Product))]
public partial class CustomSerializer : JsonSerializerContext
{
}
```

## トリミング
<a name="dotnet-native-aot-trimming"></a>

ネイティブ AOT は、バイナリができるだけ小さくなるように、コンパイルの一部としてアプリケーションコードをトリミングします。.NET 8 for Lambda は、以前のバージョンの .NET と比較して、トリミングサポートが改善されています。[Lambda ランタイムライブラリ](https://github.com/aws/aws-lambda-dotnet/pull/1596)、[AWS .NET SDK ](https://github.com/aws/aws-sdk-net/pulls?q=is%3Apr+trimming)、[.NET Lambda アノテーション](https://github.com/aws/aws-lambda-dotnet/pull/1610) 、.NET 8 自体にサポートが追加されました。

これらの改善により、ビルド時のトリミング警告を排除できる可能性がありますが、.NET が完全にトリムセーフになることはありません。つまり、関数が依存するライブラリの一部が、コンパイルステップの一部としてトリミングされる可能性があるということです。これを管理するには、次の例に示すように、`TrimmerRootAssemblies` を `.csproj` ファイルの一部として定義することでこれを管理できます。

```
<ItemGroup>
    <TrimmerRootAssembly Include="AWSSDK.Core" />
    <TrimmerRootAssembly Include="AWSXRayRecorder.Core" />
    <TrimmerRootAssembly Include="AWSXRayRecorder.Handlers.AwsSdk" />
    <TrimmerRootAssembly Include="Amazon.Lambda.APIGatewayEvents" />
    <TrimmerRootAssembly Include="bootstrap" />
    <TrimmerRootAssembly Include="Shared" />
</ItemGroup>
```

トリミング警告が表示された場合は、警告を生成するクラスを `TrimmerRootAssembly` に追加しても、問題は解決しない可能性があります。トリミング警告は、ランタイムまで決定できない他のクラスにクラスがアクセスしようとしていることを示します。ランタイムエラーを回避するには、この 2 番目のクラスを `TrimmerRootAssembly` に追加します。

トリミング警告の管理の詳細については、Microsoft .NET ドキュメントの「[Introduction to trim warnings](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/fixing-warnings)」を参照してください。

## トラブルシューティング
<a name="dotnet-native-aot-troubleshooting"></a>

**Error: Cross-OS native compilation is not supported.(エラー: クロス OS のネイティブコンパイルはサポートされません。)**  
使用している Amazon.Lambda.Tools .NET Core グローバルツールのバージョンが古くなっています。最新のバージョンにアップデートしてから、再試行してください。

**Docker: image operating system "linux" cannot be used on this platform. (Docker: このプラットフォームでイメージオペレーティングシステム「linux」を使用することはできません。)**  
システム上の Docker は、Windows コンテナを使用するように設定されています。Linux コンテナに切り替えて、ネイティブ AOT 構築環境を実行してください。

一般的なエラーの詳細については、GitHub の [AWS NativeAOT for .NET](https://github.com/awslabs/dotnet-nativeaot-labs#common-errors) リポジトリを参照してください。

# Lambda コンテキストオブジェクトを使用して C\$1 関数の情報を取得する
<a name="csharp-context"></a>

Lambda で関数が実行されると、コンテキストオブジェクトが[ハンドラー](csharp-handler.md)に渡されます。このオブジェクトは、呼び出し、関数、および実行関数に関する情報を含むプロパティです。

**context プロパティ**
+ `FunctionName` － Lambda 関数の名前。
+ `FunctionVersion` － 関数の[バージョン](configuration-versions.md)。
+ `InvokedFunctionArn` － 関数を呼び出すために使用される Amazon リソースネーム (ARN)。呼び出し元でバージョン番号またはエイリアスが指定されているかどうかを示します。
+ `MemoryLimitInMB` － 関数に割り当てられたメモリの量。
+ `AwsRequestId` － 呼び出しリクエストの ID。
+ `LogGroupName` － 関数のロググループ。
+ `LogStreamName` － 関数インスタンスのログストリーム。
+ `RemainingTime` (`TimeSpan`) － 実行がタイムアウトするまでの残りのミリ秒数。
+ `Identity` － (モバイルアプリケーション) リクエストを認可した Amazon Cognito ID に関する情報。
+ `ClientContext` － (モバイルアプリケーション) クライアントアプリケーションが Lambda に提供したクライアントコンテキスト。
+ `Logger` 関数の[ロガーオブジェクト](csharp-logging.md)。

モニタリング目的として、`ILambdaContext` オブジェクトの情報を使用して関数の呼び出しに関する情報を出力できます。次のコードは、構造化ログ記録フレームワークにコンテキスト情報を追加する方法の例を示しています。この例では、関数はログ出力に `AwsRequestId` を追加します。また、この関数は `RemainingTime` プロパティを使用して、Lambda 関数のタイムアウトに達しそうな場合にインフライトタスクをキャンセルします。

```
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetProductHandler;

public class Function
{
    private readonly IDatabaseRepository _repo;
    
    public Function()
    {
        this._repo = new DatabaseRepository();
    }
    
    public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
    {
        Logger.AppendKey("AwsRequestId", context.AwsRequestId);
        
        var id = request.PathParameters["id"];

        using var cts = new CancellationTokenSource();
        
        try
        {
            cts.CancelAfter(context.RemainingTime.Add(TimeSpan.FromSeconds(-1)));
            
            var databaseRecord = await this._repo.GetById(id, cts.Token);
            
            return new APIGatewayProxyResponse 
            {
                StatusCode = (int)HttpStatusCode.OK,
                Body = JsonSerializer.Serialize(databaseRecord)
            };
        }
        catch (Exception ex)
        {
            return new APIGatewayProxyResponse 
            {
                StatusCode = (int)HttpStatusCode.InternalServerError,
                Body = JsonSerializer.Serialize(new { error = ex.Message })
            };
        }
        finally
        {
            cts.Cancel();
        }
    }
}
```

# C\$1 Lambda 関数のログ記録とモニタリング
<a name="csharp-logging"></a>

AWS Lambda は、Lambda 関数を自動的にモニタリングし、Amazon CloudWatch にログエントリを送信します。Lambda 関数には、関数のインスタンスごとに CloudWatch Logs ロググループとログストリームが用意されています。Lambda のランタイム環境は、各呼び出しの詳細や、関数のコードからのその他の出力をログストリームに送信します。CloudWatch Logs の詳細については、「[Lambda 関数ログを CloudWatch Logs に送信する](monitoring-cloudwatchlogs.md)」を参照してください。

**Topics**
+ [

## ログを返す関数の作成
](#csharp-logging-output)
+ [

## .NET での Lambda の高度なログ記録コントロールの使用
](#csharp-logging-advanced)
+ [

## その他のログ記録ツールとライブラリ
](#csharp-tools-libraries)
+ [

## 構造化されたログ記録に Powertools for AWS Lambda (.NET) と AWS SAM を使用する
](#dotnet-logging-sam)
+ [

## Lambda コンソールでログを表示する
](#csharp-logging-console)
+ [

## CloudWatch コンソールでの ログの表示
](#csharp-logging-cwconsole)
+ [

## AWS Command Line Interface (AWS CLI) を使用してログを表示する
](#csharp-logging-cli)
+ [

## ログの削除
](#csharp-logging-delete)

## ログを返す関数の作成
<a name="csharp-logging-output"></a>

関数コードからログを出力する場合は、コンテキストオブジェクトの [ILambdaLogger](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.Core/ILambdaLogger.cs)、[Console クラス](https://docs.microsoft.com/en-us/dotnet/api/system.console)のメソッド、または `stdout` か `stderr` に書き込む任意のログライブラリを使用できます。

.NET ランタイムは、呼び出しごとに `START`、`END`、`REPORT` の各行を記録します。レポート行には、次の詳細が示されます。

**REPORT 行のデータフィールド**
+ **RequestId** － 呼び出しの一意のリクエスト ID。
+ **所要時間** － 関数のハンドラーメソッドがイベントの処理に要した時間。
+ **課金期間** － 呼び出しの課金対象の時間。
+ **メモリサイズ** － 関数に割り当てられたメモリの量。
+ **使用中の最大メモリ** － 関数によって使用されているメモリの量。呼び出しが実行環境を共有すると、Lambda はすべての呼び出しで使用される最大メモリを報告します。この動作により、予想よりも高い報告値が発生する可能性があります。
+ **初期所要時間** － 最初に処理されたリクエストについて、ハンドラーメソッド外で関数をロードしてコードを実行するためにランタイムにかかった時間。
+ **XRAY TraceId** － トレースされたリクエストの場合、[AWS X-Ray のトレース ID](services-xray.md)。
+ **SegmentId** － トレースされたリクエストの場合、X-Ray のセグメント ID。
+ **サンプリング済み** － トレースされたリクエストの場合、サンプリング結果。

## .NET での Lambda の高度なログ記録コントロールの使用
<a name="csharp-logging-advanced"></a>

関数のログのキャプチャ、処理、使用方法をより細かく制御できるように、サポートされている .NET ランタイムに以下のログ記録オプションを設定できます。
+ **ログの形式** - 関数のログをプレーンテキスト形式と構造化された JSON 形式から選択します
+ **ログレベル** - JSON 形式のログの場合、Lambda が CloudWatch に送信するログの詳細レベル (ERROR、DEBUG、INFO など) を選択します。
+ **ロググループ** - 関数がログを送信する CloudWatch ロググループを選択します

これらのログ記録オプションの詳細と、それらのオプションを使用するように関数を設定する方法については、「[Lambda 関数の高度なログ記録コントロールの設定](monitoring-logs.md#monitoring-cloudwatchlogs-advanced)」を参照してください。

.NET Lambda 関数でログ形式とログレベルのオプションを使用するには、以下のセクションのガイダンスを参照してください。

### .NET での構造化された JSON ログ形式の使用
<a name="csharp-logging-advanced-JSON"></a>

関数のログ形式に JSON を選択した場合、Lambda は [ILambdaLogger](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.Core/ILambdaLogger.cs) を使用してログ出力を構造化された JSON として送信します。各 JSON ログオブジェクトには、少なくとも 5 つのキーと値のペアが含まれます。これらのペアには以下のキーが含まれます。
+ `"timestamp"` - ログメッセージが生成された時刻
+ `"level"` - メッセージに割り当てられたログレベル
+ `"requestId"` - 関数呼び出しの一意のリクエスト ID
+ `"traceId"` - `_X_AMZN_TRACE_ID` 環境変数
+ `"message"` - ログメッセージの内容

`ILambdaLogger` インスタンスは、例外のログ記録時などに、キーと値のペアを追加できます。セクション「[ユーザー指定のログパラメータ](#csharp-logging-advanced-JSON-user-supplied)」で説明されているように、独自の追加パラメータを指定することもできます。

**注記**  
コードが既に別のログ記録ライブラリを使用して JSON 形式のログを生成している場合は、関数のログ形式がプレーンテキストに設定されていることを確認してください。ログ形式を JSON に設定すると、ログ出力が二重にエンコードされます。

次のログ記録コマンドの例は、レベル `INFO` でログメッセージを書き込む方法を示しています。

**Example .NET ログ記録コード**  

```
context.Logger.LogInformation("Fetching cart from database");
```

次の例に示すように、ログレベルを引数とする汎用ログメソッドを使用することもできます。

```
context.Logger.Log(LogLevel.Information, "Fetching cart from database");
```

これらのサンプルコードスニペットによるログ出力は、次のように CloudWatch Logs にキャプチャされます。

**Example JSON ログレコード**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Information",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "Fetching cart from database"
}
```

**注記**  
JSON ではなくプレーンテキストを使用するように関数のログ形式を設定した場合、メッセージにキャプチャされるログレベルには Microsoft の規則に従って 4 文字のラベルが使用されます。例えば、`Debug` のログレベルはメッセージに `dbug` と表示されます。  
JSON 形式のログを使用するように関数を設定すると、ログにキャプチャされるログレベルには、JSON ログレコードの例に示すように、完全なラベルが使用されます。

ログ出力にレベルを割り当てない場合、Lambda は自動的に INFO レベルを割り当てます。

#### JSON の例外の記録
<a name="csharp-logging-advanced-JSON-exceptions"></a>

`ILambdaLogger` で構造化 JSON ログ記録を使用する場合、次の例に示すように、コードで例外をログに記録できます。

**Example 例外ログ記録の使用**  

```
try
{
    connection.ExecuteQuery(query);
}
catch(Exception e)
{
    context.Logger.LogWarning(e, "Error executing query");
}
```

このコードによるログ形式の出力を次の JSON の例に示します。JSON の `message` プロパティは `LogWarning` 呼び出しで指定されたメッセージ引数を使用して入力され、`errorMessage` プロパティは例外自体の `Message` プロパティから取得されることに注意してください。

**Example JSON ログレコード**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Warning",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "Error executing query",
    "errorType": "System.Data.SqlClient.SqlException",
    "errorMessage": "Connection closed",
    "stackTrace": ["<call exception.StackTrace>"]
}
```

関数のログ記録形式が JSON に設定されている場合、未対応の例外をコードがスローしたときにも Lambda は JSON 形式のログメッセージ出力します。次のコードスニペットとログメッセージの例は、未対応の例外がどのようにログに記録されるかを示しています。

**Example 例外コード**  

```
throw new ApplicationException("Invalid data");
```

**Example JSON ログレコード**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Error",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "Invalid data",
    "errorType": "System.ApplicationException",
    "errorMessage": "Invalid data",
    "stackTrace": ["<call exception.StackTrace>"]
}
```

#### ユーザー指定のログパラメータ
<a name="csharp-logging-advanced-JSON-user-supplied"></a>

JSON 形式のログメッセージでは、追加のログパラメータを指定し、それらをログ `message` に含めることができます。次のコードスニペットの例は、`retryAttempt` と `uri` というラベルが付いた 2 つのユーザー指定のパラメータを追加するコマンドを示しています。この例では、これらのパラメータの値は、ログ記録コマンドに渡される `retryAttempt` および `uriDestination` 引数から取得されます。

**Example 追加パラメータを使用した JSON ログ記録コマンド**  

```
context.Logger.LogInformation("Starting retry {retryAttempt} to make GET request to {uri}", retryAttempt, uriDestination);
```

このコマンドによるログメッセージ出力を次の JSON の例に示します。

**Example JSON ログレコード**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Information",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "Starting retry 1 to make GET request to http://example.com/",
    "retryAttempt": 1,
    "uri": "http://example.com/"
}
```

**ヒント**  
追加のパラメータを指定するときに、名前の代わりに位置プロパティを使用することもできます。例えば、前の例のログ記録コマンドは次のように記述することもできます。  

```
context.Logger.LogInformation("Starting retry {0} to make GET request to {1}", retryAttempt, uriDestination);
```

追加のログ記録パラメータを指定すると、Lambda はそれらを JSON ログレコードの最上位プロパティとしてキャプチャすることに注意してください。このアプローチは、個々の子オブジェクトで追加パラメータをキャプチャする `Serilog` などの一般的な .NET ログ記録ライブラリとは異なります。

追加パラメータに指定する引数が複雑なオブジェクトの場合、Lambda はデフォルトで `ToString()` メソッドを使用して値を指定します。引数を JSON シリアル化する必要があることを示すには、次のコードスニペットに示すように `@` プレフィックスを使用します。この例では、`User` は `FirstName` および `LastName` プロパティを持つオブジェクトです。

**Example JSON シリアル化されたオブジェクトを使用した JSON ログ記録コマンド**  

```
context.Logger.LogInformation("User {@user} logged in", User);
```

このコマンドによるログメッセージ出力を次の JSON の例に示します。

**Example JSON ログレコード**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Information",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "User {@user} logged in",
    "user": 
    {
        "FirstName": "John",
        "LastName": "Doe"
    }
}
```

追加パラメータの引数が配列であるか、`IList` または `IDictionary` を実装している場合、Lambda は、次の JSON ログレコードの例に示すように、引数を配列として JSON ログメッセージに追加します。この例では、`{users}` は前の例と同じ形式の `User` プロパティのインスタンスを含む `IList` を引数にします。Lambda はこの `IList` を配列に変換し、各値は `ToString` メソッドを使用して作成されます。

**Example `IList` 引数を含む JSON ログレコード**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Information",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "{users} have joined the group",
    "users": 
    [
        "Rosalez, Alejandro",
        "Stiles, John"       
    ] 
}
```

ログ記録コマンドで `@` プレフィックスを使用して、リストを JSON シリアル化することもできます。次の JSON ログレコードの例では、`users` プロパティは JSON シリアル化されています。

**Example JSON シリアル化された `IList` 引数を含む JSON ログレコード**  

```
{
    "timestamp": "2025-09-07T01:30:06.977Z",
    "level": "Information",
    "requestId": "8f711428-7e55-46f9-ae88-2a65d4f85fc5",
    "traceId": "1-6408af34-50f56f5b5677a7d763973804",
    "message": "{@users} have joined the group",
    "users": 
    [
        {
            "FirstName": "Alejandro",
            "LastName": "Rosalez"
        },
        {
            "FirstName": "John",
            "LastName": "Stiles"
        }        
    ] 
}
```

### .NET でのログレベルフィルタリングの使用
<a name="csharp-logging-advanced-levels"></a>

ログレベルのフィルタリングを設定することで、特定の詳細レベル以下のログのみを CloudWatch Logs に送信するように選択できます。関数にログレベルのフィルタリングを設定する方法については、「[ログレベルのフィルタリング](monitoring-cloudwatchlogs-log-level.md)」を参照してください。

AWS Lambda でログレベルでログメッセージをフィルタリングする場合は、JSON 形式のログを使用するか、.NET の `Console` メソッドを使用してログメッセージを出力します。JSON 形式のログを作成するには、[関数のログタイプを JSON に設定](monitoring-cloudwatchlogs-logformat.md#monitoring-cloudwatchlogs-set-format)し、`ILambdaLogger` インスタンスを使用します。

JSON 形式のログでは、Lambda は「[.NET での構造化された JSON ログ形式の使用](#csharp-logging-advanced-JSON)」で説明されている JSON オブジェクトの「level」キーと値のペアを使用してログ出力をフィルタリングします。

.NET の `Console` メソッドを使用して CloudWatch Logs にメッセージを書き込む場合、Lambda は次のようにログレベルをメッセージに適用します。
+ **Console.WriteLine メソッド** - Lambda は `INFO` のログレベルを適用します
+ **Console.Error メソッド** - Lambda は `ERROR` のログレベルを適用します

ログレベルのフィルタリングを使用するように関数を設定する場合、Lambda が CloudWatch Logs に送信するログのレベルを以下のオプションから選択する必要があります。Lambda で使用されるログレベルと、.NET の `ILambdaLogger` で使用される標準の Microsoft レベルのマッピングに注意してください。


| Lambda ログレベル | 同等の Microsoft レベル | 標準的な使用状況 | 
| --- | --- | --- | 
| TRACE (最も詳細) | トレース | コードの実行パスを追跡するために使用される最も詳細な情報 | 
| DEBUG | デバッグ | システムデバッグの詳細情報 | 
| 情報 | 情報 | 関数の通常の動作を記録するメッセージ | 
| WARN | 警告 | 対処しないと予期しない動作を引き起こす可能性がある潜在的なエラーに関するメッセージ | 
| エラー | エラー | コードが期待どおりに動作しなくなる問題に関するメッセージ | 
| FATAL (詳細度が最も低い) | 重大 | アプリケーションの機能停止を引き起こす重大なエラーに関するメッセージ | 

Lambda は、選択した詳細レベル以下のログを CloudWatch に送信します。例えば、ログレベルを WARN に設定すると、Lambda は WARN、ERROR、FATAL の各レベルに対応するログを送信します。

## その他のログ記録ツールとライブラリ
<a name="csharp-tools-libraries"></a>

[Powertools for AWS Lambda (.NET)](https://docs.aws.amazon.com/powertools/dotnet/) は、サーバーレスのベストプラクティスを実装し、デベロッパーの作業速度を向上させるためのデベロッパーツールキットです。[ログ記録ユーティリティ](https://docs.aws.amazon.com/powertools/dotnet/core/logging/)には、Lambda に最適化されたロガーを提供し、すべての関数を通して関数コンテキストに関する追加情報が含まれ、JSON 形式で構成した出力を行います。このユーティリティを使用して次のことができます。
+ Lambda の コンテキスト、コールドスタート、構造から主要キーをキャプチャし、JSON 形式でログ出力する
+ 指示された場合 Lambda 呼び出しイベントをログ記録する (デフォルトでは無効)
+ ログサンプリングにより、特定の割合の呼び出しにのみすべてのログを出力する (デフォルトでは無効)
+ 任意のタイミングで、構造化されたログにキーを追加する
+ カスタムログフォーマッター (Bring Your Own Formatter) を使用して、組織の ログ記録 RFC と互換性のある構造でログを出力する

## 構造化されたログ記録に Powertools for AWS Lambda (.NET) と AWS SAM を使用する
<a name="dotnet-logging-sam"></a>

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

**前提条件**

このセクションの手順を完了するには、以下が必要です。
+ .NET 8
+ [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-dotnet --name sam-app --package-type Zip --runtime dotnet6 --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 -X GET <URL_FROM_PREVIOUS_STEP>
   ```

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

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

1. 関数のログを取得するには、[sam logs](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/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:27.988000 INIT_START Runtime Version: dotnet:6.v13        Runtime Version ARN: arn:aws:lambda:ap-southeast-2::runtime:699f346a05dae24c58c45790bc4089f252bf17dae3997e79b17d939a288aa1ec
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:28.229000 START RequestId: bed25b38-d012-42e7-ba28-f272535fb80e Version: $LATEST
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:29.259000 2025-09-20T14:15:29.201Z        bed25b38-d012-42e7-ba28-f272535fb80e    info   {"_aws":{"Timestamp":1676902528962,"CloudWatchMetrics":[{"Namespace":"sam-app-logging","Metrics":[{"Name":"ColdStart","Unit":"Count"}],"Dimensions":[["FunctionName"],["Service"]]}]},"FunctionName":"sam-app-HelloWorldFunction-haKIoVeose2p","Service":"PowertoolsHelloWorld","ColdStart":1}
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:30.479000 2025-09-20T14:15:30.479Z        bed25b38-d012-42e7-ba28-f272535fb80e    info   {"ColdStart":true,"XrayTraceId":"1-63f3807f-5dbcb9910c96f50742707542","CorrelationId":"d3d4de7f-4ccc-411a-a549-4d67b2fdc015","FunctionName":"sam-app-HelloWorldFunction-haKIoVeose2p","FunctionVersion":"$LATEST","FunctionMemorySize":256,"FunctionArn":"arn:aws:lambda:ap-southeast-2:123456789012:function:sam-app-HelloWorldFunction-haKIoVeose2p","FunctionRequestId":"bed25b38-d012-42e7-ba28-f272535fb80e","Timestamp":"2025-09-20T14:15:30.4602970Z","Level":"Information","Service":"PowertoolsHelloWorld","Name":"AWS.Lambda.Powertools.Logging.Logger","Message":"Hello world API - HTTP 200"}
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:30.599000 2025-09-20T14:15:30.599Z        bed25b38-d012-42e7-ba28-f272535fb80e    info   {"_aws":{"Timestamp":1676902528922,"CloudWatchMetrics":[{"Namespace":"sam-app-logging","Metrics":[{"Name":"ApiRequestCount","Unit":"Count"}],"Dimensions":[["Service"]]}]},"Service":"PowertoolsHelloWorld","ApiRequestCount":1}
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:30.680000 END RequestId: bed25b38-d012-42e7-ba28-f272535fb80e
   2025/02/20/[$LATEST]4eaf8445ba7a4a93b999cb17fbfbecd8 2025-09-20T14:15:30.680000 REPORT RequestId: bed25b38-d012-42e7-ba28-f272535fb80e  Duration: 2450.99 ms   Billed Duration: 2692 ms Memory Size: 256 MB     Max Memory Used: 74 MB  Init Duration: 240.05 ms
   XRAY TraceId: 1-63f3807f-5dbcb9910c96f50742707542       SegmentId: 16b362cd5f52cba0
   ```

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

   ```
   sam delete
   ```

### ログ保持の管理
<a name="csharp-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
```

## Lambda コンソールでログを表示する
<a name="csharp-logging-console"></a>

Lambda コンソールを使用して、Lambda 関数を呼び出した後のログ出力を表示できます。

組み込み **Code** エディタからコードがテスト可能である場合、**[実行結果]** でログを確認できます。コンソールのテスト機能を使用して関数を呼び出すと、**[詳細]** セクションで **[ログ出力]** を確認できます。

## CloudWatch コンソールでの ログの表示
<a name="csharp-logging-cwconsole"></a>

Amazon CloudWatch コンソールを使用して、すべての Lambda 関数呼び出しのログを表示できます。

**CloudWatch コンソールでログを表示するには**

1. CloudWatch コンソールの [[Log groups (ロググループ)] ページ](https://console.aws.amazon.com/cloudwatch/home?#logs:)を開きます。

1. 機能のロググループを選択します( **/aws/lambda/*関数名***)

1. ログストリームを選択します

各ログストリームは、[関数のインスタンス](lambda-runtime-environment.md)に相当します。ログストリームは、Lambda 関数を更新したとき、および同時呼び出しを処理するために追加のインスタンスが作成されたときに表示されます。特定の呼び出しのログを検索するために、AWS X-Ray を使って関数をインストルメント化することをお勧めします。　 X-Ray は、リクエストとログストリームの詳細をトレースに記録します。

## AWS Command Line Interface (AWS CLI) を使用してログを表示する
<a name="csharp-logging-cli"></a>

AWS CLI は、コマンドラインシェルでコマンドを使用して AWS サービスとやり取りするためのオープンソースツールです。このセクションの手順を完了するには、[AWS CLIバージョン 2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) が必要です。

[AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) および `--log-type` コマンドオプションを使用して、呼び出しのログを取得します。レスポンスには、`LogResult`フィールドが含まれ、このフィールドには、呼び出しから base64 コードされた最大 4 KB のログが含まれます。

**Example ログ ID を取得します**  
次の例は、`LogResult`という名前の関数の`my-function`フィールドから*ログ ID * を取得する方法を示しています。  

```
aws lambda invoke --function-name my-function out --log-type Tail
```
次のような出力が表示されます。  

```
{
    "StatusCode": 200,
    "LogResult": "U1RBUlQgUmVxdWVzdElkOiA4N2QwNDRiOC1mMTU0LTExZTgtOGNkYS0yOTc0YzVlNGZiMjEgVmVyc2lvb...",
    "ExecutedVersion": "$LATEST"
}
```

**Example ログをデコードします**  
同じコマンドプロンプトで、`base64` ユーティリティを使用してログをデコードします。次の例は、`my-function`の base64 でエンコードされたログを取得する方法を示しています 。  

```
aws lambda invoke --function-name my-function out --log-type Tail \
--query 'LogResult' --output text --cli-binary-format raw-in-base64-out | base64 --decode
```
AWS CLI バージョン 2 を使用している場合、**cli-binary-format** オプションは必須です。これをデフォルト設定にするには、`aws configure set cli-binary-format raw-in-base64-out` を実行します。詳細については、「*AWS Command Line Interface バージョン 2 用ユーザーガイド*」の「[AWS CLI でサポートされているグローバルコマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)」を参照してください。  
以下の出力が表示されます。  

```
START RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8 Version: $LATEST
"AWS_SESSION_TOKEN": "AgoJb3JpZ2luX2VjELj...", "_X_AMZN_TRACE_ID": "Root=1-5d02e5ca-f5792818b6fe8368e5b51d50;Parent=191db58857df8395;Sampled=0"",ask/lib:/opt/lib",
END RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8
REPORT RequestId: 57f231fb-1730-4395-85cb-4f71bd2b87b8  Duration: 79.67 ms      Billed Duration: 80 ms         Memory Size: 128 MB     Max Memory Used: 73 MB
```
`base64`このユーティリティは、Linux、macOS、および [ Windows の Ubuntu ](https://docs.microsoft.com/en-us/windows/wsl/install-win10) で使用できます。macOS ユーザーは、`base64 -D`を使用する必要があります 。

**Example get-logs.sh スクリプト**  
同じコマンドプロンプトで、次のスクリプトを使用して、最後の 5 つのログイベントをダウンロードします。このスクリプトは `sed` を使用して出力ファイルから引用符を削除し、ログが使用可能になるまで 15 秒待機します。この出力には Lambda からのレスポンスと、`get-log-events` コマンドからの出力が含まれます。  
次のコードサンプルの内容をコピーし、Lambda プロジェクトディレクトリに `get-logs.sh` として保存します。  
AWS CLI バージョン 2 を使用している場合、**cli-binary-format** オプションは必須です。これをデフォルト設定にするには、`aws configure set cli-binary-format raw-in-base64-out` を実行します。詳細については、「*AWS Command Line Interface バージョン 2 用ユーザーガイド*」の「[AWS CLI でサポートされているグローバルコマンドラインオプション](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list)」を参照してください。  

```
#!/bin/bash
aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"key": "value"}' out
sed -i'' -e 's/"//g' out
sleep 15
aws logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name stream1 --limit 5
```

**Example macOS および Linux (専用)**  
同じコマンドプロンプトで、macOS と Linux ユーザーが次のコマンドを実行して、スクリプトが実行可能であることを確認する必要があります。  

```
chmod -R 755 get-logs.sh
```

**Example 最後の 5 つのログイベントを取得します**  
同じコマンドプロンプトで、次のスクリプトを実行して、最後の 5 つのログイベントを取得します。  

```
./get-logs.sh
```
次のような出力が表示されます。  

```
{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}
{
    "events": [
        {
            "timestamp": 1559763003171,
            "message": "START RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf Version: $LATEST\n",
            "ingestionTime": 1559763003309
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tENVIRONMENT VARIABLES\r{\r  \"AWS_LAMBDA_FUNCTION_VERSION\": \"$LATEST\",\r ...",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003173,
            "message": "2019-06-05T19:30:03.173Z\t4ce9340a-b765-490f-ad8a-02ab3415e2bf\tINFO\tEVENT\r{\r  \"key\": \"value\"\r}\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "END RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\n",
            "ingestionTime": 1559763018353
        },
        {
            "timestamp": 1559763003218,
            "message": "REPORT RequestId: 4ce9340a-b765-490f-ad8a-02ab3415e2bf\tDuration: 26.73 ms\tBilled Duration: 27 ms \tMemory Size: 128 MB\tMax Memory Used: 75 MB\t\n",
            "ingestionTime": 1559763018353
        }
    ],
    "nextForwardToken": "f/34783877304859518393868359594929986069206639495374241795",
    "nextBackwardToken": "b/34783877303811383369537420289090800615709599058929582080"
}
```

## ログの削除
<a name="csharp-logging-delete"></a>

関数を削除しても、ロググループは自動的には削除されません。ログが無期限に保存されないようにするには、ロググループを削除するか、ログが自動的に削除されるまでの[保存期間を設定](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html#SettingLogRetention)します。

# AWS Lambda での C\$1 コードの作成
<a name="csharp-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 .NET](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-dotnet.html) - トレースデータを生成して X-Ray に送信するための SDK です。
+ [Powertools for AWS Lambda (.NET)](https://docs.aws.amazon.com/powertools/dotnet/) — サーバーレスのベストプラクティスを実装し、開発者の作業速度を向上させるための開発者ツールキットです。

各 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 (.NET) と AWS SAM を使用する
](#dotnet-tracing-sam)
+ [

## X-Ray SDK を使用して .NET 関数を計装する
](#dotnet-xray-sdk)
+ [

## Lambda コンソールを使用してトレースを有効化する
](#dotnet-tracing-console)
+ [

## Lambda API でのトレースのアクティブ化
](#dotnet-tracing-api)
+ [

## CloudFormation によるトレースのアクティブ化
](#dotnet-tracing-cloudformation)
+ [

## X-Ray トレースの解釈
](#dotnet-tracing-interpretation)

## トレーシングに Powertools for AWS Lambda (.NET) と AWS SAM を使用する
<a name="dotnet-tracing-sam"></a>

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

**前提条件**

このセクションの手順を完了するには、以下が必要です。
+ .NET 8
+ [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-dotnet --name sam-app --package-type Zip --runtime dotnet6 --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
   ```

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

   ```
   New XRay Service Graph
     Start time: 2023-02-20 23:05:16+08:00
     End time: 2023-02-20 23:05:16+08:00
     Reference Id: 0 - AWS::Lambda - sam-app-HelloWorldFunction-pNjujb7mEoew - Edges: [1]
      Summary_statistics:
        - total requests: 1
        - ok count(2XX): 1
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 2.814
     Reference Id: 1 - AWS::Lambda::Function - sam-app-HelloWorldFunction-pNjujb7mEoew - Edges: []
      Summary_statistics:
        - total requests: 1
        - ok count(2XX): 1
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 2.429
     Reference Id: 2 - (Root) AWS::ApiGateway::Stage - sam-app/Prod - Edges: [0]
      Summary_statistics:
        - total requests: 1
        - ok count(2XX): 1
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 2.839
     Reference Id: 3 - client - sam-app/Prod - Edges: [2]
      Summary_statistics:
        - total requests: 0
        - ok count(2XX): 0
        - error count(4XX): 0
        - fault count(5XX): 0
        - total response time: 0
   
   XRay Event [revision 3] at (2023-02-20T23:05:16.521000) with id (1-63f38c2c-270200bf1d292a442c8e8a00) and duration (2.877s)
    - 2.839s - sam-app/Prod [HTTP: 200]
      - 2.836s - Lambda [HTTP: 200]
    - 2.814s - sam-app-HelloWorldFunction-pNjujb7mEoew [HTTP: 200]
    - 2.429s - sam-app-HelloWorldFunction-pNjujb7mEoew
      - 0.230s - Initialization
      - 2.389s - Invocation
        - 0.600s - ## FunctionHandler
          - 0.517s - Get Calling IP
      - 0.039s - Overhead
   ```

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

   ```
   sam delete
   ```

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

## X-Ray SDK を使用して .NET 関数を計装する
<a name="dotnet-xray-sdk"></a>

関数コードを実装して、メタデータを記録し、ダウンストリームコールをトレースできます。関数が他のリソースやサービスに対して行うコールの詳細を記録するには、AWS X-Ray SDK for .NET を使用します。SDK を取得するには、`AWSXRayRecorder` パッケージをプロジェクトファイルに追加します。

```
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
    <AWSProjectType>Lambda</AWSProjectType>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Amazon.Lambda.Core" Version="2.1.0" />
    <PackageReference Include="Amazon.Lambda.SQSEvents" Version="2.1.0" />
    <PackageReference Include="Amazon.Lambda.Serialization.Json" Version="2.1.0" />
    <PackageReference Include="AWSSDK.Core" Version="3.7.103.24" />
    <PackageReference Include="AWSSDK.Lambda" Version="3.7.104.3" />
    <PackageReference Include="AWSXRayRecorder.Core" Version="2.13.0" />
    <PackageReference Include="AWSXRayRecorder.Handlers.AwsSdk" Version="2.11.0" />
  </ItemGroup>
</Project>
```

AWS SDK、Entity Framework、HTTP リクエストに自動計測を提供するさまざまな Nuget パッケージがあります。設定オプションの完全なセットについては、「AWS X-Ray 開発者ガイド」の「[AWS X-Ray SDK for .NET](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-dotnet.html)」を参照してください。

目的の Nuget パッケージを追加したら、自動計測を設定します。ベストプラクティスは、この設定を関数のハンドラー関数の外部で実行することです。これにより、実行環境の再利用を活用して関数のパフォーマンスを向上させることができます。次のコード例では、`RegisterXRayForAllServices` メソッドを関数コンストラクタで呼び出して、すべての AWS SDK 呼び出しに計測を追加しています。

```
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetProductHandler;

public class Function
{
    private readonly IDatabaseRepository _repo;
    
    public Function()
    {
        // Add auto instrumentation for all AWS SDK calls
        // It is important to call this method before initializing any SDK clients
        AWSSDKHandler.RegisterXRayForAllServices();
        this._repo = new DatabaseRepository();
    }
    
    public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request)
    {
        var id = request.PathParameters["id"];
        
        var databaseRecord = await this._repo.GetById(id);
        
        return new APIGatewayProxyResponse 
        {
            StatusCode = (int)HttpStatusCode.OK,
            Body = JsonSerializer.Serialize(databaseRecord)
        };
    }
}
```

## Lambda コンソールを使用してトレースを有効化する
<a name="dotnet-tracing-console"></a>

コンソールを使用して、Lambda 関数のアクティブトレースをオンにするには、次のステップに従います。

**アクティブトレースをオンにするには**

1. Lambda コンソールの [[関数ページ]](https://console.aws.amazon.com/lambda/home#/functions) を開きます。

1. 関数を選択します。

1. **[設定]** を選択してから、**[モニタリングおよび運用ツール]** を選択します。

1. **[その他の監視ツール]** で、**[編集]** を選択します。

1. **[CloudWatch Application Signals と AWS X-Ray]** で、**[Lambda サービストレース]** の **[有効]** を選択します。

1. **[保存]** を選択します。

## Lambda API でのトレースのアクティブ化
<a name="dotnet-tracing-api"></a>

AWS CLI または AWS SDK で Lambda 関数のトレースを設定するには、次の API オペレーションを使用します。
+ [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html)
+ [GetFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html)
+ [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html)

以下の例の AWS CLI コマンドは、**my-function** という名前の関数に対するアクティブトレースを有効にします。

```
aws lambda update-function-configuration --function-name my-function \
--tracing-config Mode=Active
```

トレースモードは、関数のバージョンを公開するときのバージョン固有の設定の一部です。公開後のバージョンのトレースモードを変更することはできません。

## CloudFormation によるトレースのアクティブ化
<a name="dotnet-tracing-cloudformation"></a>

CloudFormation テンプレート内で `AWS::Lambda::Function` リソースに対するアクティブトレースを有効化するには、`TracingConfig` プロパティを使用します。

**Example [function-inline.yml](https://github.com/awsdocs/aws-lambda-developer-guide/blob/master/templates/function-inline.yml) － トレース設定**  

```
Resources:
  function:
    Type: [AWS::Lambda::Function](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)
    Properties:
      TracingConfig:
        Mode: Active
      ...
```

AWS Serverless Application Model (AWS SAM) `AWS::Serverless::Function` リソースに、`Tracing` プロパティを使用します。

**Example [template.yml](https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-nodejs/template.yml) － トレース設定**  

```
Resources:
  function:
    Type: [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)
    Properties:
      Tracing: Active
      ...
```

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

関数には、トレースデータを X-Ray にアップロードするためのアクセス許可が必要です。Lambda コンソールでトレースを有効にすると、Lambda は必要な権限を関数の [[実行ロール]](lambda-intro-execution-role.md) に追加します。それ以外の場合は、[AWSXRayDaemonWriteAccess](https://console.aws.amazon.com/iam/home#/policies/arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess) ポリシーを実行ロールに追加します。

アクティブトレースの設定後は、アプリケーションを通じて特定のリクエストの観測が行えるようになります。[[X-Ray サービスグラフ]](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html#xray-concepts-servicegraph) には、アプリケーションとそのすべてのコンポーネントに関する情報が表示されます。次の例は、2 つの関数を持つアプリケーションを示しています。プライマリ関数はイベントを処理し、エラーを返す場合があります。上位 2 番目の関数は、最初のロググループに表示されるエラーを処理し、AWS SDK を使用して X-Ray、Amazon Simple Storage Service (Amazon S3)、および Amazon CloudWatch Logs を呼び出します。

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


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

X-Ray では、*トレース*は 1 つ以上の*サービス*によって処理されるリクエストに関する情報を記録します。Lambda はトレースごとに 2 つのセグメントを記録します。これにより、サービスグラフに 2 つのノードが作成されます。次の図は、これら 2 つのノードを強調表示しています。

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


左に示された 1 つめのノードは、呼び出しリクエストを受信する Lambda サービスを表しています。2 つめのノードは、特定の Lambda 関数を表しています。次の例は、これら 2 つのセグメントを使用したトレースを示しています。いずれも **my-function** と名付けられていますが、1 つは `AWS::Lambda` の起点があり、もう 1 つは `AWS::Lambda::Function` の起点があります。`AWS::Lambda` セグメントにエラーが表示される場合は、Lambda サービスに問題があります。`AWS::Lambda::Function` セグメントにエラーが表示される場合、関数に問題があります。

![\[\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/V2_sandbox_images/my-function-2-v1.png)


この例では、`AWS::Lambda::Function` セグメントを展開して、それの 3 つのサブセグメントが表示されています。

**注記**  
AWS は現在、Lambda サービスに変更を実装しています。これらの変更により、AWS アカウント のさまざまな Lambda 関数によって出力されるシステムログメッセージとトレースセグメントの構造と内容にわずかな違いが生じる場合があります。  
ここで示すトレースの例は、古いスタイルの関数セグメントを示しています。古いスタイルのセグメントと新しいスタイルのセグメントの違いについては、次の段落で説明します。  
これらの変更は今後数週間に実装され、中国および GovCloud リージョンを除くすべての AWS リージョンのすべての関数は、新しい形式のログメッセージとトレースセグメントを使用するように移行されます。

古いスタイルの関数セグメントには、次のサブセグメントが含まれます。
+ **初期化** － 関数のロードと[初期化コード](foundation-progmodel.md)の実行に要した時間を表します。このサブセグメントは、関数の各インスタンスが処理する最初のイベントに対してのみ表示されます。
+ **[呼び出し]** - ハンドラーコードの実行に要した時間を表します。
+ **[オーバーヘッド]** - Lambda ランタイムが次のイベントを処理するための準備に要する時間を表します。

新しいスタイルの関数セグメントには `Invocation` サブセグメントが含まれていません。代わりに、顧客サブセグメントが関数セグメントに直接アタッチされます。古いスタイルの関数セグメントと新しいスタイルの関数セグメントの構造の詳細については、「」を参照してください[X-Ray トレースを理解する](services-xray.md#services-xray-traces)。

HTTP クライアントをインストルメント化し、SQL クエリを記録して、注釈とメタデータからカスタムサブセグメントを作成することもできます。詳細については、「AWS X-Ray デベロッパーガイド」の「[AWS X-Ray SDK for .NET](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-dotnet.html)」を参照してください。

**料金**  
X-Ray トレースは、毎月、AWS 無料利用枠で設定された一定限度まで無料で利用できます。X-Ray の利用がこの上限を超えた場合は、トレースによる保存と取得に対する料金が発生します。詳細については、「[AWS X-Ray 料金表](https://aws.amazon.com/xray/pricing/)」を参照してください。

# C\$1 での AWS Lambda 関数テスト
<a name="dotnet-csharp-testing"></a>

**注記**  
サーバーレスソリューションをテストするための手法とベストプラクティスの詳細については、「[関数のテスト](testing-guide.md)」の章を参照してください。

 サーバーレス関数のテストでは、従来のテストタイプと手法を使用しますが、サーバーレスアプリケーション全体のテストも検討する必要があります。クラウドベースのテストでは、関数とサーバーレスアプリケーションの両方の品質を**最も正確に**測定できます。

 サーバーレスアプリケーションアーキテクチャには、API 呼び出しを通じて重要なアプリケーション機能を提供するマネージドサービスが含まれます。このため、開発サイクルには、関数とサービスが相互に作用する際に機能を検証する自動テストを含める必要があります。

 クラウドベースのテストを作成しない場合、ローカル環境とデプロイされた環境の違いにより問題が発生する可能性があります。継続的な統合プロセスでは、コードをQA、ステージング、本番稼働などの次のデプロイ環境に昇格する前に、クラウドにプロビジョニングされた一連のリソースに対してテストを実行する必要があります。

 サーバーレスアプリケーションのテスト戦略に関する詳細については、このショートガイドを引き続きご覧ください。また、[サーバーレステストサンプルリポジトリ](https://github.com/aws-samples/serverless-test-samples)にアクセスして、選択した言語とランタイムに固有の実用的な例を調べることもできます。

 ![\[illustration showing the relationship between types of tests\]](http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/images/test-type-illustration2.png) 

 サーバーレステストの場合も、*ユニット*テスト、*統合*テスト、*エンドツーエンド*テストを書くことになります。
+ **ユニットテスト** - 分離されたコードブロックに対して実行されるテスト。例えば、特定の商品と配送先を指定して配送料を計算するビジネスロジックを検証する場合です。
+ **統合テスト** - 通常はクラウド環境で相互作用する 2 つ以上のコンポーネントまたはサービスを対象としたテスト。例えば、キューからのイベントを処理する関数を検証する場合です。
+ **エンドツーエンドテスト** - アプリケーション全体の動作を検証するテスト。例えば、インフラストラクチャが正しくセットアップされ、顧客の注文を記録するためにイベントがサービス間で想定どおりに流れることを確認する場合です。

## サーバーレスアプリケーションのテスト
<a name="dotnet-csharp-testing-techniques-for-serverless-applications"></a>

 通常、サーバーレスアプリケーションコードのテストには、クラウドでのテスト、モックを使ったテスト、場合によってはエミュレーターでのテストなど、さまざまな方法を組み合わせます。

### クラウドでのテスト
<a name="dotnet-csharp-testing-in-the-cloud"></a>

 クラウドでのテストは、ユニットテスト、統合テスト、エンドツーエンドテストなど、テストのあらゆる段階で役立ちます。クラウドにデプロイされたコードやクラウドベースのサービスとやり取りするコードに対してテストを実行します。この方法では、コードの品質を**最も正確に**測定できます。

 クラウドで Lambda 関数をデバッグする便利な方法は、コンソールからテストイベントを行うことです。*テストイベント*とは、関数への JSON 入力のことです。関数が入力を必要としない場合、イベントは空の JSON ドキュメント `({})` にすることができます。コンソールには、さまざまなサービス統合のサンプルイベントが用意されています。コンソールでイベントを作成したら、それをチームと共有して、テストを簡単かつ一貫性のあるものにすることができます。

**注記**  
[コンソールで関数をテストする](testing-functions.md)のが簡単な方法ですが、テストサイクルを自動化することでアプリケーションの品質と開発スピードが保証されます。

### テストツール
<a name="dotnet-csharp-testing-tools"></a>

開発サイクルを能率化するために、関数のテスト時に使用できるツールやテクニックは数多くあります。例えば、[AWS SAM Accelerate](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-sync.html) と [AWS CDK 監視モード](https://docs.aws.amazon.com/cdk/v2/guide/cli.html#cli-deploy-watch)は、いずれもクラウド環境の更新に要する時間を短縮します。

Lambda 関数コードを定義する方法により、ユニットテストを簡単に追加できます。Lambda では、クラスを初期化するためのパラメータなしのパブリックコンストラクタが必要です。2 つ目の内部コンストラクタを導入すると、アプリケーションが使用する依存関係を制御できるようになります。

```
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetProductHandler;

public class Function
{
    private readonly IDatabaseRepository _repo;
    
    public Function(): this(null)
    {
    }
    
    internal Function(IDatabaseRepository repo)
    {
        this._repo = repo ?? new DatabaseRepository();
    }
    
    public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request)
    {
        var id = request.PathParameters["id"];
        
        var databaseRecord = await this._repo.GetById(id);
        
        return new APIGatewayProxyResponse 
        {
            StatusCode = (int)HttpStatusCode.OK,
            Body = JsonSerializer.Serialize(databaseRecord)
        };
    }
}
```

この関数のテストを作成するには、`Function` クラスの新しいインスタンスを初期化し、`IDatabaseRepository` のモック実装を渡します。以下の例では、`XUnit`、`Moq`、`FluentAssertions` を使用して、`FunctionHandler` がステータスコード 200 を返すことを確認する簡単なテストを記述しています。

```
using Xunit;
using Moq;
using FluentAssertions;

public class FunctionTests
{
    [Fact]
    public async Task TestLambdaHandler_WhenInputIsValid_ShouldReturn200StatusCode()
    {
        // Arrange
        var mockDatabaseRepository = new Mock<IDatabaseRepository>();
        
        var functionUnderTest = new Function(mockDatabaseRepository.Object);
        
        // Act
        var response = await functionUnderTest.FunctionHandler(new APIGatewayProxyRequest());
        
        // Assert
        response.StatusCode.Should().Be(200);
    }
}
```

非同期テストの例を含む詳細な例については、GitHub の「[.NET testing samples repository](https://github.com/aws-samples/serverless-test-samples/tree/main/dotnet-test-samples)」を参照してください。