X-Rayとは
分散アプリケーションの分析とデバッグのためのサービスです。
詳細は、こちら。
AWS X-Ray
前提
今回も、以下構成でサンプルを構築してみようと思います。
- SAM
- Python3.8
SAMをはじめとする基本知識は、こちらを参照願います。
- [AWS] Serverless Application Model (SAM) の基本まとめ
- [AWS] Serverless Application Model (SAM) でAPI Gateway + Lambda + DynamoDBなサンプルを作成してみる
サンプルを作ってみよう
プロジェクト作成
例によって、SAMでHello Worldベースのプロジェクトを作成していきます。
$ sam init --runtime=python3.8
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Project name [sam-app]:
Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.git
AWS quick start application templates:
1 - Hello World Example
2 - EventBridge Hello World
3 - EventBridge App from scratch (100+ Event Schemas)
4 - Step Functions Sample App (Stock Trader)
5 - Elastic File System Sample App
Template selection: 1
-----------------------
Generating application:
-----------------------
Name: sam-app
Runtime: python3.8
Dependency Manager: pip
Application Template: hello-world
Output Directory: .
Next steps can be found in the README file at ./sam-app/README.md
X-Rayの追加
ソースコードへのデコレータ追加
まず、コードにX-Rayのデコレータを追記します。
デフォルトで生成されるhello_world/app.py
をリファクタリングも含めて、以下のようにしてみます。
import json
from aws_xray_sdk.core import xray_recorder
@xray_recorder.capture('hello world')
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": json.dumps({
"message": "hello world",
})
}
SDKの取り込み
LambdaにX-Ray SDKのライブラリを取り込むため、hello_world/requirements.txt
を以下のように修正します。
aws-xray-sdk
SAMテンプレートの修正
最後に、Lambda関数、API Gatewayのトレーシングを有効にするため、Globalsの箇所を以下のように修正します。
Globals:
Function:
Timeout: 3
Globals:
Function:
Timeout: 3
Tracing: Active
Api:
TracingEnabled: True
ビルド
$ sam build
Building function 'HelloWorldFunction'
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided
デプロイ
$ sam deploy --guided
Configuring SAM deploy
======================
Looking for samconfig.toml : Found
Reading default arguments : Success
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]:
AWS Region [us-east-1]: ap-northeast-1
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [Y/n]: y
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: y
HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
Save arguments to samconfig.toml [Y/n]: y
Looking for resources needed for deployment: Found!
Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-1rzppw621dkka
A different default S3 bucket can be set in samconfig.toml
Deploying with following values
===============================
Stack name : sam-app
Region : ap-northeast-1
Confirm changeset : True
Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-1rzppw621dkka
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}
Initiating deployment
=====================
Saved arguments to config file
Running 'sam deploy' for future deployments will use the parameters saved above.
The above parameters can be changed by modifying samconfig.toml
Learn more about samconfig.toml syntax at
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
Deploying with following values
===============================
Stack name : sam-app
Region : ap-northeast-1
Confirm changeset : True
Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-1rzppw621dkka
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}
Initiating deployment
=====================
HelloWorldFunction may not have authorization defined.
Uploading to sam-app/8476bddd8c14756a7c801a61352b828d.template 1142 / 1142.0 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType
------------------------------------------------------------------------------------------------
+ Add HelloWorldFunctionHelloWorldPe AWS::Lambda::Permission
rmissionProd
+ Add HelloWorldFunctionRole AWS::IAM::Role
+ Add HelloWorldFunction AWS::Lambda::Function
+ Add ServerlessRestApiDeployment47f AWS::ApiGateway::Deployment
c2d5f9d
+ Add ServerlessRestApiProdStage AWS::ApiGateway::Stage
+ Add ServerlessRestApi AWS::ApiGateway::RestApi
------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:************:changeSet/samcli-deploy1597324152/18c44433-12d1-4e03-9fb8-00737d018991
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y
2020-08-13 22:09:28 - Waiting for stack create/update to complete
CloudFormation events from changeset
-------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole Resource creation
Initiated
CREATE_COMPLETE AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction Resource creation
Initiated
CREATE_COMPLETE AWS::Lambda::Function HelloWorldFunction -
CREATE_IN_PROGRESS AWS::ApiGateway::RestA ServerlessRestApi Resource creation
pi Initiated
CREATE_IN_PROGRESS AWS::ApiGateway::RestA ServerlessRestApi -
pi
CREATE_COMPLETE AWS::ApiGateway::RestA ServerlessRestApi -
pi
CREATE_IN_PROGRESS AWS::ApiGateway::Deplo ServerlessRestApiDeplo -
yment yment47fc2d5f9d
CREATE_IN_PROGRESS AWS::ApiGateway::Deplo ServerlessRestApiDeplo Resource creation
yment yment47fc2d5f9d Initiated
CREATE_IN_PROGRESS AWS::Lambda::Permissio HelloWorldFunctionHell Resource creation
n oWorldPermissionProd Initiated
CREATE_IN_PROGRESS AWS::Lambda::Permissio HelloWorldFunctionHell -
n oWorldPermissionProd
CREATE_COMPLETE AWS::ApiGateway::Deplo ServerlessRestApiDeplo -
yment yment47fc2d5f9d
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdS -
tage
CREATE_COMPLETE AWS::Lambda::Permissio HelloWorldFunctionHell -
n oWorldPermissionProd
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdS Resource creation
tage Initiated
CREATE_COMPLETE AWS::ApiGateway::Stage ServerlessRestApiProdS -
tage
CREATE_COMPLETE AWS::CloudFormation::S sam-app -
tack
-------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
-------------------------------------------------------------------------------------------------
Outputs
-------------------------------------------------------------------------------------------------
Key HelloWorldFunctionIamRole
Description Implicit IAM Role created for Hello World function
Value arn:aws:iam::************:role/sam-app-HelloWorldFunctionRole-IIPXQC9S1XKJ
Key HelloWorldApi
Description API Gateway endpoint URL for Prod stage for Hello World function
Value https://tws0qc6nbc.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
Key HelloWorldFunction
Description Hello World Lambda Function ARN
Value arn:aws:lambda:ap-northeast-1:************:function:sam-app-
HelloWorldFunction-1OH75PSLQUSLC
-------------------------------------------------------------------------------------------------
Successfully created/updated stack - sam-app in ap-northeast-1
## 実行
curl https://tws0qc6nbc.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world"}
成功しました。
確認
では、マネジメントコンソールで、X-RayのService Map、Traces、アナリティクスを確認してみましょう。
Service Map
クライアントから呼び出され、API Gateway、Lambdaと順に呼び出されていく様子と、それぞれのレイテンシーを確認することができます。
Traces
こちらでは、トレースの状況を確認することができます。
ここでは、それぞれの条件に応じてフィルタリングすることができます。
- URL
- StatusCOde
- Method
- User
- UserAgent
- ClientIP
- InstanceId
- ResourceARN
- Response time root causes
- Error root causes
- Error root cause messages
- Fault root causes
- Fault root cause messages
- Annotation aws:api id
アナリティクス
最後にアナリティクスは、その名の通り、さまざまな分析をしたり、比較を行ったりすることができます。
AWSサービスをトレースしてみる
では、AWSサービスのトレースをしてみましょう。
今回は、DynamoDBにPutItemする時のトレースを追加してみます。
細かい内容は、「[AWS] Serverless Application Model (SAM) でAPI Gateway + Lambda + DynamoDBなサンプルを作成してみる」を参照いただきたいて、X-Rayに関する部分だけポイントで説明したいと思います。
コードの追加
まず、HelloWorldとは別に、Function用のディレクトリを作成し、その中にファイルを作成していきます。
$ mkdir sam_ddb
$ touch sam_ddb/app.py
$ touch sam_ddb/requirements.txt
まずは、Lambda関数の本体ですが、ここで重要なのが、patch['boto3']
の部分です。
これを行うことによって、boto3のAWSサービス呼び出しのトレースが行えるようになります。
import json
import boto3
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch
from datetime import datetime
patch(['boto3'])
@xray_recorder.capture('put_item ddb')
def lambda_handler(event, context):
event_body = json.loads(event["body"])
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("Demo")
table.put_item(
Item={
"Key": event_body["key"],
"CreateDate": datetime.utcnow().isoformat()
}
)
return {
"statusCode": 200,
"body": json.dumps({
"message": "succeeded",
}),
}
aws-xray-sdk
boto3
最後に、template.yml
を編集します。
変更が必要なのは、Resources
と、Outputs
の部分です。
IAM Roleで、X-Rayに関する権限が必要なので注意してください。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sam-app
Sample SAM Template for sam-app
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
Tracing: Active
Api:
TracingEnabled: True
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.8
Events:
HelloWorld:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /hello
Method: get
Outputs:
# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
# Find out more about other implicit resources you can reference within SAM
# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
HelloWorldApi:
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
Description: "Hello World Lambda Function ARN"
Value: !GetAtt HelloWorldFunction.Arn
HelloWorldFunctionIamRole:
Description: "Implicit IAM Role created for Hello World function"
Value: !GetAtt HelloWorldFunctionRole.Arn
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sam-app
Sample SAM Template for sam-app
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
Tracing: Active
Api:
TracingEnabled: True
Resources:
DynamoTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: Demo
AttributeDefinitions:
- AttributeName: Key
AttributeType: S
- AttributeName: CreateDate
AttributeType: S
KeySchema:
- AttributeName: Key
KeyType: HASH
- AttributeName: CreateDate
KeyType: RANGE
ProvisionedThroughput:
ReadCapacityUnits: 5
WriteCapacityUnits: 5
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.8
Events:
HelloWorld:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /hello
Method: get
SamDdbFunction:
Type: AWS::Serverless::Function
Properties:
Role: !GetAtt SamDdbFunctionIamRole.Arn
CodeUri: sam_ddb/
Handler: app.lambda_handler
Runtime: python3.8
Events:
SamDdb:
Type: Api
Properties:
Path: /ddb
Method: post
SamDdbFunctionIamRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- 'lambda.amazonaws.com'
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/CloudWatchLogsFullAccess'
Policies:
- PolicyName: 'SamDdbPolicy'
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- dynamodb:PutItem
Resource: !GetAtt DynamoTable.Arn
- Effect: Allow
Action:
- xray:PutTraceSegments
- xray:PutTelemetryRecords
Resource: '*'
Outputs:
# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
# Find out more about other implicit resources you can reference within SAM
# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
HelloWorldApi:
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
Description: "Hello World Lambda Function ARN"
Value: !GetAtt HelloWorldFunction.Arn
HelloWorldFunctionIamRole:
Description: "Implicit IAM Role created for Hello World function"
Value: !GetAtt HelloWorldFunctionRole.Arn
SamDdbApi:
Description: "API Gateway endpoint URL for Prod stage for SAM DDB function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/ddb/"
ビルドとデプロイ
sam build
と、sam deploy --guided
を実行してください。
(内容は省略します)
実行
今回はAPIを1個追加しているので、比較のためにHelloWorldのAPIも呼び出してみます。
$ curl https://fp8nyhpv87.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world"}
続いて、DynamoDBに書き込むPostのAPIを呼び出してみます。
$ curl -X POST -H "Content-Type: application/json" -d '{"key": "demo-data"}' https://fp8nyhpv87.execute-api.ap-northeast-1.amazonaws.com/Prod/ddb/
{"message": "succeeded"}
X-Rayの確認
まずは、Service Mapから。
なぜか配置がねじれてますが、DynamoDBへのアクセス部分が切り出されて表示されているのがわかると思います。
DBの書き込み部分が620msかかっていることがわかりますね。
Tracesでも同様です。
DynamoDBの部分が独立してトレースできます。
念のためDynamoDBも確認
ばっちりデータが登録されてます。
まとめ
X-Rayによるトレーシングで、様々な分析、解析が可能になります。
事後でも簡単に追加できますが、できれば、初期の段階から導入されることをおすすめします。
サンプルコードリポジトリ