AWS DEV DAY 2022 Day2 E-4 コードとデモで理解する!これは便利!AWS Lambda の実装を加速するAWS Lambda Powertools を使いこなそう!
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.コードとデモで理解する︕これは便利︕AWS Lambda の実装を加速するAWS Lambda Powertools を使いこなそう︕A W S D E V D A Y 2 0 2 2 J A P A NAtsushi FukuiE - 4Senior Solutions Architect, Developer Specialist – DevAxAmazon Web Services Japan
View Slide
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.⾃⼰紹介v名前v福井 厚(ふくい あつし)fatsushi@v所属vアマゾン ウェブ サービス ジャパン合同会社vシニアソリューションアーキテクトDeveloper スペシャリスト - DevAxv関⼼領域vソフトウェア アーキテクチャ、オブジェクト指向設計、アジャイル開発v好きなAWSサービスvサーバーレステクノロジー全般、 AWS Code シリーズ、AWS Amplify
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Agenda• AWS Lambda Powertools for Python とは• Tracer ユーティリティー• Logger ユーティリティー• Metrics ユーティリティー• EventHandler – REST API ユーティリティー• まとめ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.AWS Lambda Powertools for Pythonとは
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Lambda関数を開発していて、こんな思いをしたことはありませんか︖• コードを構造化してメソッドを機能単位に分割したのでメソッドごとの実⾏時間をトレースしたい。。。• すべての関数でフォーマット化されたログを⽣成して運⽤時に活⽤したい。。。• Lambda関数の実⾏時に独⾃のメトリクスを取得して想定通りに関数が実⾏されていることを数値として確認したい。。。• でもチーム内で各メンバーがそれぞれ実装するのは⼤変。。。
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.AWS Lambda Powertools for Pythonとは• AWSが開発するオープンソースのユーティリティーライブラリ• AWS Lambda関数⽤の便利な機能を提供§ トレース、構造化ロギング、カスタムメトリックスなどのベストプラクティスの導⼊を容易に• AWS Lambda関数の実⾏環境とサポートされているランタイム専⽤に最適化• Python 以外に以下の⾔語でも提供§ AWS Lambda Powertools for Java§ AWS Lambda Powertools for TypeScript§ AWS Lambda Powertools for .NET
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.AWS builders.flashにシリーズ連載中https://aws.amazon.com/jp/builders-flash/202203/lambda-powertools-python-1/
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.AWS Lambda Powertools for Pythonインストール⽅法• Powertoolsは以下の⽅法でインストールして利⽤することが可能• Lambda Layerとして利⽤• PyPiからインストール
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Lambda Layerとして利⽤• AWS Serverless Application Model(SAM)による指定⽅法(※2022年11⽉8⽇時点の最新版 v2.2.0の場合)– Lambda Layer (x86_64):arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:13– Lambda Layer (arm64):arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2-Arm64:13...TraceDemoFunction:Type: AWS::Serverless::FunctionProperties:Runtime: python3.9Tracing: ActiveArchitectures:- x86_64CodeUri: src/Handler: app.lambda_handlerLayers:- !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:13
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.PyPi からインストール$ pip install aws-lambda-powertoolsrequirements.txt に追加してSAMでデプロイaws-lambda-powertoolsローカル開発環境⽤
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Quick getting started• Hello World サンプルのインストール$ sam init --location \https://github.com/aws-samples/cookiecutter-aws-sam-python
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.提供しているユーティリティー⼀覧CoreUtilitiesTracing Lambda関数ハンドラのトレースのためのデコレーターとユーティリティーLogger 構造化されたJSONの出⼒を⾏うロガーを提供MetricsAmazon CloudWatch Embedded Metrics Format (EMF) に従ってメトリクスを標準出⼒にロギングすることで、カスタムメトリクスを⾮同期に作成Event Handler:APIGateway, ALB and LambdaFunction URLAmazon API Gateway、ALB、Lambda Funcrion URL⽤のイベントハンドラを提供Event Handler: AppSyncLambda Direct ResolverとAmplify GraphQL Transformer関数のためのAppSync イベントハンドラUtilitiesMiddleware factory個々のLambdaの実⾏の前後に同期的にロジックを実⾏するための独⾃のミドルウェアを作成するためのデコレーターファクトリを提供Parameters単⼀、または複数のパラメータ値をAWS Systems Manager Parameter Store、AWS SecretsManager、AWS AppConfig、Amazon DynamoDB、または独⾃設定から取得する⾼レベルの関数を提供Batch Processing SQS、Kinesis、DynamoDB Streamsのバッチ処理で部分的な失敗を処理する⽅法を提供Typing IDEの型ヒントの提供による開発容易性に利⽤可能な静的型付けクラスを提供ValidationイベントとレスポンスのためのJSONスキーマバリデーションを提供。検証する前にイベントをアンラップするためのJMESPathをサポート。Event Source Data Classes ⾃⼰記述型のLambdaイベントソースクラスを提供Parser Pydanticを利⽤したデータのパースとディープバリデーションを提供Idempotency安全なリトライを実⾏するためLambda関数で冪等性を可能にするシンプルなソリューションを提供Feature flagsひとつまたは複数のフィーチャーが⼊⼒に基づいて有効化される⽅法を定義するためのシンプルなルールエンジンを提供JMESPath Functions Lambda関数の⼀般的なエンコード済みJSONペイロードを容易にデシリアライズ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Tracer Utility
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Tracer ユーティリティー• TracerはX-Ray SDKのラッパーで簡単にトレースのアノテーションとメタデータを追加することが可能• 初期化のオーバーヘッドが発⽣しているトレースを容易にフィルタするための ColdStart アノテーションを⾃動的に追加• Tracer をインスタンス化する際にservice アノテーションも追加
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Tracer: capture_lambda_handler デコレーター• ハンドラーのレスポンスまたは例外情報を⾃動的にキャプチャ、トレースのメタデータとして保存from aws_lambda_powertools import Tracertracer = Tracer()@tracer.capture_lambda_handlerdef lambda_handler(event, context):return {"statusCode": 200,"body": "hello, world!"}
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.AWS X-Ray のトレースデータを⽣成
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Tracer Demo
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Tracer: アノテーションとメタデータ• アノテーション– トレースに含まれるKey-Value– AWS X-Rayによってインデックス化– アノテーションを利⽤してトレースをフィルタすることが可能– トランザクションを分析するためのトレースグループを作成するために利⽤することも可能• メタデータ– 同様にトレースに含まれるKey-Valueだが、AWS X-Rayによってインデックス化されない点がアノテーションと異る– ⼀⽅でメタデータはValueにブール値、数値、⽂字列、オブジェクトを含めることができ、また名前空間を指定することも可能– これらの値を運⽤管理のためにトレースに追加して利⽤可能
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.アノテーションでクエリを絞り込むことも可能
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Tracer: capture_method デコレーター• 同期型関数のトレースを取得可能• 関数にデコレーターを指定することで、トレースに関数単位のサブセグメントが作成され、関数単位の実⾏時間も表⽰されるようになる• ⾮同期関数やジェネレータに対してもcapture_methodデコレーターを使⽤することが可能§ 但し、⾮同期Lambdaハンドラーはサポートされない
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.capture_method デコレーターとアノテーションの追加# ② 同期型関数のトレースを取得@tracer.capture_methoddef get_item_data(id):try:response = table.get_item(Key={'id': id})# ② トレースにアノテーションを追加tracer.put_annotation(key="get_item_data", value="SUCCESS")return response['Item']except ClientError as e:# ② トレースにアノテーションを追加tracer.put_annotation(key="get_item_data", value="FAIL")
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.メタデータの追加# ② イベントハンドラに対するトレースの実行@tracer.capture_lambda_handlerdef lambda_handler(event, context):# ② DynamoDBのテーブルからアイテムを取得し、メタデータに出力item = get_item_data("1")# ② トレースにメタデータを出力tracer.put_metadata(key="item_response", value=item)return {"statusCode": 200,# ② レスポンスでアイテムの情報を返す"body": json.dumps(item)}
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Tracer Demo 2
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Logger Utility
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Logger ユーティリティー• 構造化されたログを⽣成• 環境変数またはパラメータでログレベルを指定可能• Pythonのlogging.Logger クラスを継承• リクエストのパーセンテージでログのサンプリングをDEBUGログレベルで有効化(デフォルトは無効)• どの時点でも構造化されたログにキーを追加可能
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.ログレベルとサービス名を環境変数で指定可能(SAMの例)LoggerDemoFunction:Type: AWS::Serverless::FunctionProperties:CodeUri: src/Handler: app.lambda_handlerRuntime: python3.9Architectures:- x86_64Environment:Variables:LOG_LEVEL: INFOPOWERTOOLS_SERVICE_NAME: logger-demo
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Logger: inject_lambda_context デコレーター• Lambdaコンテキスト、コールドスタートの情報をキャプチャし、JSONで構造化されたログを出⼒• 呼び出された時にLambdaのイベントをロギングデフォルトでは無効、log_event=True パラメーターで有効化
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Logger の利⽤例# ① Loggerユーティリティーをインポートfrom aws_lambda_powertools import Logger# ① Loggerユーティリティーのインスタンスを作成logger = Logger()# ① inject_lambda_contextデコレーターを指定@logger.inject_lambda_contextdef lambda_handler(event, context):# ① infoレベルのログを生成 2logger.info("start handler!")# ① infoレベルのログをオブジェクトを追加して生成logger.info({"operation": "logger_demo","custom_key": "builders.flash demo"})
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Logger ユーティリティーのログ出⼒例{"level": "INFO","location": "lambda_handler:8","message": "start handler!","timestamp": "2022-03-25 07:25:54,563+0000","service": "logger-demo","cold_start": true,"function_name": "logger-demo-LoggerDemoFunction-xxxxxxxxxxx","function_memory_size": "128","function_arn": "arn:...:logger-demo-LoggerDemoFunction-xxxxxxxx","function_request_id": "9c5a35c7-552d-46f1-a6a5-3a03a5153ff4","xray_trace_id": "1-623d6e82-6dd0ea50736a04742a5ae904"}
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Logger ユーティリティーのログ出⼒例 2{"level": "INFO","location": "lambda_handler:10","message": {"operation": "logger_demo","custom_key": "builders.flash demo"},"timestamp": "2022-03-25 07:25:54,563+0000","service": "logger-demo","cold_start": true,"function_name": "logger-demo-LoggerDemoFunction-xxxxxxxxx","function_memory_size": "128","function_arn": "arn:...:function:logger-demo-LoggerDemoFunction-xxxxxxxxxx","function_request_id": "9c5a35c7-552d-46f1-a6a5-3a03a5153ff4","xray_trace_id": "1-623d6e82-6dd0ea50736a04742a5ae904"}
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Logger : キーと値の追加# ② inject_lambda_contextデコレーターを指定@logger.inject_lambda_contextdef lambda_handler(event, context):order_id = event["queryStringParameters"]["order_id"]# ② ログにorder_idというキーと値を追加logger.append_keys(order_id=order_id)logger.info("start handler!")• logger.append_keys メソッドでキーと値をログに追加可能
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.キーと値を追加したログの例{"level": "INFO","location": "lambda_handler:11","message": "start handler!","timestamp": "2022-03-27 05:46:05,090+0000","service": "logger-demo","order_id": "0001","xray_trace_id": "1-623ffa1c-63d46f47290e1e8f33c94ef4"}
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Logger Demo
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Metrics Utility
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Metrics ユーティリティー• 埋め込みメトリクスフォーマット Amazon CloudWatch EmbeddedMetric Format (EMF) に従った標準出⼒に対するメトリクスでカスタムメトリクスを⾮同期に作成可能• Amazon CloudWatchのコンソールでビジュアル化が可能• 単⼀のCloudWatch EMFオブジェクト(JSONのblob)を使⽤して100個までのメトリクスを集約可能• メトリクスの⼀般的な定義間違い(メトリクスユニット、値、最⼤ディメンジョン、最⼤メトリクスなど)を検証可能• CloudWatchサービスによってメトリクスは⾮同期に作成される
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.CloudWatch LogsにEMF形式でメトリクスを出⼒する⽅法のメリット• CloudWatch MetricsのPutMetricData APIの呼び出しは秒間150回という上限が設けられていて、それ以上の呼び出しはスロットリングされる• AWS LambdaのCloudWach Logsへの送信は⾮同期に⾏われてスロットリングされることがない• CloudWatch MetricsのPutMetricData APIを呼び出すよりもCloudWatch Logsへの書き込みのほうがコスト的に有利
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Metrics ユーティリティー の利⽤例# ① Metricsユーティリティーをインポートfrom aws_lambda_powertools import Metricsfrom aws_lambda_powertools.metrics import MetricUnit# ① Metricsユーティリティーのインスタンスを作成metrics = Metrics()# ① log_metricsデコレーターを指定@metrics.log_metricsdef lambda_handler(event, context):# ① メトリクスの追加metrics.add_metric(name="SuccessfulCalling",unit=MetricUnit.Count, value=1)
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.CloudWatch Logs にEMF形式のログを出⼒{"_aws": {"Timestamp": 1654233601233,"CloudWatchMetrics": [{"Namespace": "MetricsDemoApp","Dimensions": [[ "service" ]],"Metrics": [{"Name": "SuccessfulCalling","Unit": "Count"}]}]},"service": "metrics-demo","SuccessfulCalling": [ 1 ]}
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Metrics Demo
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.EventHandler Utility
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.EventHandler - REST API ユーティリティー• Amazon API GatewayのREST API、HTTP API、Lambda Function URLs、および Application Load Balancerのためのイベントハンドラを提供• API Gateway REST/HTTP APIとALBに対するボイラープレートを減らす軽量なルーティング• CORS、バイナリーとGzip圧縮、DecimalのJSONエンコーディング、独⾃のJSONシリアライザをサポート• ⾃⼰記述型イベントスキーマのためのEvent Source Data Classesユーティリティーとの統合
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Event リゾルバ• 関数のデコレーターをセットしてリクエストのpathやHTTPのメソッドをハンドルする前に、リゾルバを初期化する必要がある• リゾルバはリクエストを解決するために、1つ以上のルーティング処理を含む• 型付けされたプロパティーを通じて現在のイベントにアクセスできるようにする以下のリゾルバを提供• APIGatewayRestResolver• APIGatewayHttpResolver• ALBResolver• LambdaFunctionUrlResolver
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.SAMテンプレートの定義例AWSTemplateFormatVersion: "2010-09-09"Transform: AWS::Serverless-2016-10-31Globals:Api:TracingEnabled: trueCors:AllowOrigin: "'*'"AllowHeaders: "'Content-Type,Authorization,X-Amz-Date'"...Resources:RestAPiFunction:Type: AWS::Serverless::FunctionProperties:...Events:AnyApiEvent:Type: ApiProperties:Path: /{proxy+}Method: ANY
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.EventHandler ユーティリティー の利⽤例# ① EventHandlerユーティリティーのインポートfrom aws_lambda_powertools.event_handler import APIGatewayRestResolverfrom aws_lambda_powertools.event_handler.api_gateway import CORSConfig# ① Corsの設定とAPIGatewayRestResolverインスタンスの作成cors_config = CORSConfig(allow_origin="*", max_age=300)app = APIGatewayRestResolver(cors=cors_config)# ① /productsパスのGETメソッドに対応@app.get("/products")def get_products():products = {"products": [{"id": "0001", "name": "M01", "price": 1000},{"id": "0002", "name": "M02", "price": 2000},]}return productsdef lambda_handler(event, context):return app.resolve(event, context)
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.API Gateway へのレスポンス{"statusCode": 200,"headers": {"Content-Type": "application/json"},"body":"{\"products\":[{\"id\":\"0001\",\"name\":\"M01\",\"price\":1000},{\"id\":\"0002\",\"name\":\"M02\",\"price\":2000}]}","isBase64Encoded": false}• 前ページのコードを実⾏すると、API Gatewayの公開しているURLに/productsのパスをつけて呼び出した場合、Lambda関数はAPIGatewayに対して以下のレスポンスを返す
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.動的ルーティング• /products/の形式を利⽤可能• 個々の動的ルーティングは関数のシグネチャの⼀部である必要がある• 動的ルーティングにマッチした時に、キーワード引数を利⽤して関数が呼び出される
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.動的ルーティングのコード例# ② /productsのproduct_idパラメーターに動的に対応@app.get("/products/")def get_product_by_id(product_id: str):products = {"products": [{"id": "0001", "name": "M01", "price": 1000},{"id": "0002", "name": "M02", "price": 2000},{"id": "0003", "name": "M03", "price": 1500},]}for product in products["products"]:if product["id"] == product_id:return productreturn {"message": "no match!"}
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.クエリパラメーターやペイロードの取得• API Gatewayから渡されるクエリ⽂字列やBodyのペイロードは以下のメソッドで取得可能# ③ JSON形式のペイロードの取得dict = app.current_event.json_body# ③ クエリ文字列の取得product_id = app.current_event.get_query_string_value(name="id", default_value="")# ③ ヘッダー情報の取得trace_id = app.current_event.get_header_value(name='X-Amzn-Trace-Id', case_sensitive=True, default_value='')
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.REST API EventHandlerDemo
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.提供しているユーティリティー⼀覧(再掲)CoreUtilitiesTracing Lambda関数ハンドラのトレースのためのデコレーターとユーティリティーLogger 構造化されたJSONの出⼒を⾏うロガーを提供MetricsAmazon CloudWatch Embedded Metrics Format (EMF) に従ってメトリクスを標準出⼒にロギングすることで、カスタムメトリクスを⾮同期に作成Event Handler:APIGateway, ALB and LambdaFunction URLAmazon API Gateway、ALB、Lambda Funcrion URL⽤のイベントハンドラを提供Event Handler: AppSyncLambda Direct ResolverとAmplify GraphQL Transformer関数のためのAppSync イベントハンドラUtilitiesMiddleware factory個々のLambdaの実⾏の前後に同期的にロジックを実⾏するための独⾃のミドルウェアを作成するためのデコレーターファクトリを提供Parameters単⼀、または複数のパラメータ値をAWS Systems Manager Parameter Store、AWS SecretsManager、AWS AppConfig、Amazon DynamoDB、または独⾃設定から取得する⾼レベルの関数を提供Batch Processing SQS、Kinesis、DynamoDB Streamsのバッチ処理で部分的な失敗を処理する⽅法を提供Typing IDEの型ヒントの提供による開発容易性に利⽤可能な静的型付けクラスを提供ValidationイベントとレスポンスのためのJSONスキーマバリデーションを提供。検証する前にイベントをアンラップするためのJMESPathをサポート。Event Source Data Classes ⾃⼰記述型のLambdaイベントソースクラスを提供Parser Pydanticを利⽤したデータのパースとディープバリデーションを提供Idempotency安全なリトライを実⾏するためLambda関数で冪等性を可能にするシンプルなソリューションを提供Feature flagsひとつまたは複数のフィーチャーが⼊⼒に基づいて有効化される⽅法を定義するためのシンプルなルールエンジンを提供JMESPath Functions Lambda関数の⼀般的なエンコード済みJSONペイロードを容易にデシリアライズ
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.まとめAWS Lambda Powertools for Pythonは• AWS Lambda関数⽤のユーティリティースイート• トレース、構造化ロギング、カスタムメトリックスなどのベストプラクティスの導⼊を容易に• AWS Lambda関数の実⾏環境とサポートされているランタイム専⽤に最適化• ベストプラクティスに沿ったLambda関数を容易に構築
© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.Thank you!© 2022, Amazon Web Services, Inc. or its affiliates. All rights reserved.