こんにちは!エンジニア3年目、フロントエンド&AWSサーバーレス系エンジニアを目指し勉強中のmiuraです。
サーバーレス構成だと簡単に立ち上げられる一方で、ある程度の開発規模になってくると非同期に連携したり、複数のサービスが関係したりするので、
エラーになった際にどこで失敗しているのか、デバッグしていくのが大変になることがありませんか?
または、レンスポンスが遅いと感じるがどのAWSサービスが起因して遅くなっているか確認するのが大変だと思ったことがありませんか?
そこで活躍するのがAWS X-Rayです。
AWS X-Rayはトレース対象であるサービスのリクエスト・レスポンス情報を収集するサービスで、
AWSコンソールにて収集した結果をマップ形式で見ることができ、各サービスの実行時間をグラフで可視化することができます。
今回はサーバーレスアプリへのX-Rayの適用を、Serverless Frameworkを用いて簡単に追加し、AWS上で可視化するところまでを紹介します。
以前使用したServerless Frameworkを今回も使います。
まずはPython3系用のサンプルプロジェクトを作成します。
serverless create --template aws-python3 --path aws-x-ray-serverless
cd aws-x-ray-serverless
次に、Serverless FrameworkのX-Ray用プラグインをインストールし、serverless.ymlにAWS X-Rayを有効にする設定と
API Gatewayの設定を行います。
npm install aws-sdk aws-xray-sdk serverless-plugin-tracing
aws-x-ray-serverless/serverless.yml
service: aws-x-ray-serverless
plugins:
- serverless-plugin-tracing
provider:
name: aws
runtime: python3.6
region: us-west-2
apiKeys:
- aws-x-ray-serverless-api-key
tracing: true
iamRoleStatements:
- Effect: Allow
Action:
- xray:PutTraceSegments
- xray:PutTelemetryRecords
Resource: "*"
functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get
private: true
以上で、AWS X-RayおよびAPI Gatewayの設定ができました!
このようにプラグインをインストールし、serverless.ymlにたった数行設定を書くだけでX-Rayを適用することが出来ます。
早速、AWSにデプロイをしましょう。
sls deploy
デプロイが完了したら、curlコマンドやRestClientなどでAPI Gatewayを呼び出してLambdaを実行させます。
curl -s 【API GatewayのURl】 -H "x-api-key:【APIキー】"
すると、実行結果をAWSコンソールのX-Rayのサービスにて見ることが出来ます。
緑色の円が表示されていることからLambdaの実行は成功したことが分かります。
5xxエラーや4xxエラーなどがある場合、赤色や黄色で表示してくれるのでひと目でどこに問題があるかを確認できます。
中央の数字はそのサービスでの平均レスポンス時間と 1 分間に送信したトレース数を表しており、どこで処理に時間が掛かっているのかなども確認することが出来ます。
本格的なプロダクトともなると、多くのLambdaを互いに呼び出す形で作ることになります。
その際にどこでエラーになっているかを上図のようなサービスマップで簡単に確認できるのは、私のような開発者にとっては嬉しい機能ですよね。
また、円グラフをクリックすればさらに詳細なトレース情報を見ることが可能です。
トレースについては次の構成での結果で説明します。
②AWS LambdaからAWS SNSやDynamoDBの呼び出し
①でClient、API Gatewayを通してLambdaを実行する流れをAWS X-Rayで表示しました。
そこで次に、①の続きとしてAWS LambdaからAWS SNSやDynamoDBを呼び出して、それをAWS X-Rayで表示してみましょう。
まずは、AWS LambdaでのAWS SNSやDynamo DBの呼び出しをトレースをするためにPython用 AWS X-Ray SDKをインストールします。
pip install aws-xray-sdk -t .
次に自動生成したhandler.pyとserverless.ymlの一部を編集します。
aws-x-ray-serverless/handler.py
import json
import boto3
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all
patch_all()
def hello(event, context):
body = {
"message": "Go Serverless v1.0! Your function executed successfully!",
"input": event
}
sns = boto3.client('sns')
try:
sns.publish(
TopicArn="arn:aws:sns:us-west-2:471043657237:hello",
Subject=body['message'],
Message=json.dumps(body['input'])
)
except Exception:
raise
response = {
"statusCode": 200,
"body": json.dumps(body)
}
return response
def put_hello(event, context):
sns = event['Records'][0]['Sns']
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('hello_log')
try:
table.put_item(
Item={
"timestamp": sns['Timestamp'],
"id": sns['MessageId'],
"subject": sns['Subject'],
"message": sns['Message']
})
except Exception:
raise
aws-x-ray-serverless/serverless.yml
provider:
name: aws
runtime: python3.6
region: us-west-2
apiKeys:
- aws-x-ray-serverless-api-key
tracing: true
iamRoleStatements:
- Effect: Allow
Action:
- xray:PutTraceSegments
- xray:PutTelemetryRecords
- sns:Publish
- dynamodb:PutItem
Resource: "*"
functions:
hello:
...
putHello:
handler: handler.put_hello
events:
- sns: hello
resources:
Resources:
helloLogTable:
Type: 'AWS::DynamoDB::Table'
Properties:
TableName: hello_log
AttributeDefinitions:
- AttributeName: timestamp
AttributeType: S
KeySchema:
- AttributeName: timestamp
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 2
WriteCapacityUnits: 1
気づきましたでしょうか?
AWS LambdaでのAWS SNSやDynamo DBの呼び出しをトレースすると聞くといろいろな設定が必要そうと感じますが、
実際にX-Rayの適用として追加で記述したのは、
だけ。
これだけでAWS SNSやDynamo DBを呼び出すboto3などのライブラリにX-Ray用のパッチが適用されてトレースが出来るようになります。
この手軽さは正直異常ですね(^^;
実際に再度デプロイコマンドを実行して、curlコマンドやRestClientなどでAPI Gatewayを呼び出してみます。
sls deploy
curl -s 【API GatewayのURl】 -H "x-api-key:【APIキー】"
結果、AWSコンソールのX-RayのサービスにてAWS SNSやDynamoDBへのフローも表示されるようになりました。
Service Mapの下段にあるClientはAPI Gatewayを通してAWS Lambda、そしてAWS SNSを呼び出しており、次のトリガーとなっています。
上段のClientがそのAWS SNSから呼び出されたことを表しており、AWS Lambdaを通してDynamo DBにエラーなくアクセスしていることが分かります。
そして、赤い枠にあるような円グラフをクリックするとサービスの所要時間をヒストグラムで確認することができます。
これにより、レスポンスとしては正常な200ステータスとなっているが、異様に時間が掛かっている場合がないかを確認することが出来ます。
さらに、Tracesの詳細を見ることでクライアント呼び出しからレスポンスまでの流れをタイムラインで見ることが出来ます。
上記で異様に時間が掛かっている場合の原因が、DynamoDBの呼び出しで時間が掛かっているのかそれ以外なのかをこれで調査することが出来ます。
実際に、Lambdaのレスポンスが異常に遅いことが発覚し調査を行った際、Tracesの詳細を見ることでDynamoDBの呼び出しに時間が掛かっていることが分かったことがありました。
その時の原因としては、あるDynamoDBのテーブルがいろんなところから呼び出されており、設定していたスループットを超過して制限が掛かっていたことが判明しました。
こういったこともX-Rayを見れば簡単に調査することが魅力的ですね。