さて、AWS Lambdaの続きです。
Lambdaというかサーバーレスに限らず、ローカル実行ができるか、言語機能の対応状況、ログ確認方法は開発の基本となります。NuGetパッケージの対応状況や他を見る前にざっと確認しておきましょう。
テスト
新規プロジェクトとしてSimpleAsyncFunction
という名前で、SimpleAsyncFunction
で作成します。
with Tests
を選ぶことで、xUnitによるテストプロジェクトが追加されます。あくまでもローカル実行ではなく、テストプロジェクトの追加であるということに気を付けてください。
前回同様、dotnet restore
をして新規プロジェクトのパッケージを復元したら、Test Explorerでテストを実行してみましょう。Empty Projectなので、全部大文字になることを期待していますので、適当に絶対に通らないテストも追加してみて失敗することを確認します。
https://gist.github.com/guitarrapc/a137c143ce8d1f880962d07f4066df97
通らなかったところを、Assert.NotEqual("hogemoge", upperCase);
にすれば当然通りますね。*1
いたって普通のユニットテストと分かります。TestLambdaContext
がTestLambdaContext
名前空間に存在しますが、いい感じで扱えそうですね。
ローカル実行
Node.jsにおいてローカルでイベント送信を検証するときには、_testdriver.js
を作っていましたね。*2
https://aws.amazon.com/jp/blogs/developer/aws-lambda-support-in-visual-studio/
https://aws.typepad.com/sajp/2015/03/aws-lambda-support-in-visual-studio.html
.NET Core版のLambdaは、単純なコンソールアプリです。そこで、project.jsonでbuildOptions
にbuildOptions
を true にした上で、エントリポイントとして、buildOptions
クラスのbuildOptions
スタティックメソッドを用意してあげればokです。
https://gist.github.com/guitarrapc/be5fa6e7f38a7855f8aed2960e089158
Lambda内部の関数はローカル変数の状態が見えない
Program内はローカル変数もバッチリです。が、Lambda本体の関数においてはブレークポイントは貼れるもののローカル変数が見えません。Watch Windowで変数を見ようとするとerror CS0012: The type 'ILambdaContext' is defined in an assembly that is not referenced. You must add a reference to assembly 'Amazon.Lambda.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=885c28607f98e604'.
となっています。
project.jsonでもAmazon.Lambda.Coreは参照しているのですが、何じゃろほい...。
async/await しているときの注意
AWS Lambdaは、async/awaitな関数でも呼べます。いいですね。とても嬉しいです。Loggerを組まない限りは落ちることなくローカル実行できています。
https://gist.github.com/guitarrapc/5bfb764f2efbc1d7441f9ad6eb901f94
ただ、後述のロガーを仕込んでおいてローカル実行で.Result
するとnullぽります。
System.NullReferenceException: Object reference not set to an instance of an object.
これはProgram.csのローカル実行時にnullではなくLambdaContext
を渡せばokです。具体的には次の記事に書きました。
async/await
サンプルがドキュメントにあります。
時間のかかる処理があるという前提で、Task.Delay
を組んだメソッドを非同期に実行させるなら次のようになります。
https://gist.github.com/guitarrapc/f8a6279e8a4760c04a6dc2ff19f1fa3e
普通ですね。何も違和感なくつかえます。
ロギング
ロギングがどれだけスムーズかは開発効率に重大な影響を及ぼします。今回は最もシンプルでデフォルトで設定されているCloudWatch Logsへのログ出力を見てみます。
C# からのログ出力は、3つあるとドキュメントにあります。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/dotnet-logging.html
https://gist.github.com/guitarrapc/15de1d4363833f05f96997dd4b6e7014
確認してみると次の動作になります。
ロガー | Lambdaコンソールでの出力 | CloudWatch Logs への出力 | Line出力の可否 |
---|---|---|---|
Console.Write | X | O | X |
Console.WirteLine | X | O | O |
LambdaLogger.Log | O | O | X |
ILambdaContext.Logger.LogLine | O | O | O |
ILambdaContext.Logger.Log | O | O | X |
結果、私はILambdaContext.Logger.LogLineを使うことが多いです。AzureFunctionsと似てますね。
まとめ
テスト、ローカルデバッグ、async/await、ロギングと気になるポイントを見てみました。
なかなか素直な作りなので、安心ですね。.csxと違ってローカル実行に制限がほぼないのは素晴らしいです。
今回のサンプルもリポジトリに追加しておきました。