【初心者】AWS X-Rayを使ってみる

# 目的
- AWS X-Rayについて話題になり、知ったかぶりするため、基本動作を確認することにした。（目標：なんとなく可視化ができること）

# AWS X-Ray とは（自分の理解）
- コンポーネント毎の処理時間を可視化し、ボトルネックの調査等を可能にするサービス。

# やったこと
- 以下の3パターンの構成でX-Rayの見え方を確認する。
    1. API Gateway - Lambda
    2. API Gateway - Lambda(X-Ray設定なし) - DynamoDB
    3. API Gateway - Lambda(X-Ray設定あり) - DynamoDB

# 構成図

![x-ray-001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/d38438bb-dee6-f86e-4656-b5e5f33092f5.png)

- API GatewayではX-Ray設定を有効化する。
- 以下のように設定を行う。
    - パターン1：リソース /test01 へのGETに対しLamdba(mksamba-x-ray01)を紐づける。GETのリクエストに対してLambdaを呼び出して応答を返すだけ。
    - パターン2：リソース /test02 へのGETに対しLambda(mksamba-x-ray02)を紐づける。GETのリクエストに対してLambdaを呼び出し、Lambda内でDynamoDBの検索処理を呼び出す。
    - パターン3: リソース /test03 へのGETに対しLambda(mksamba-x-ray03)を紐づける。パターン2と同じだが、Lambda内でx-rayを有効化し、DynamoDBでの処理に要する時間も可視化する。


# 動作確認
- API Gatewayの作成と基本設定
    - API Gatewayを作成し、上記の通り、3つのリソース(/test01,/test02,/test03)と3つのLambdaをそれぞれ紐づける。

![x-ray-002a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/ba588cb6-18b8-95f9-709c-ea13ce966153.png)


- API GatewayでX-Ray有効化
    - ステージ - ログ/トレース の画面で、「X-Rayトレースの有効化」のチェックをONにする。

![x-ray-003a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/92acb8cf-492c-a9a9-ddef-4aa02cd5794a.png)

- パターン1(API Gateway + Lambda)の実行
    - https://XXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/prod/test01 へのGETを行い、"Hello from Lambda!"を返すだけのLambdaを実行する。

```python:mksamba-x-ray01
import json
def lambda_handler(event, context):
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }
```

- パターン2(API Gateway + Lambda(X-Ray設定なし + DynamoDB)) の実行
    - https://XXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/prod/test02 へのGETを行い、DynamoDBでちょっとだけ検索を行い結果を返すだけのLambdaを実行する。
    
```python:mksamba-x-ray02
import json
import boto3
from boto3.dynamodb.conditions import Key

def lambda_handler(event, context):

    #適当にdynamodbにアクセス
    InputPhoneNumber = "+819011111111"
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table("mksamba-connect-userdb")
    querydata = table.query(
      KeyConditionExpression = Key("PhoneNumber").eq(InputPhoneNumber)
    )
    if querydata["Count"] == 0:
        username = "unknown"
    else:
        username = querydata["Items"][0]["Name"]
    return {
        'statusCode': 200,
        'body' : username
    }
```

- パターン3(API Gateway + Lambda(X-Ray設定あり + DynamoDB)) の実行
    - https://XXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/prod/test03 へのGETを行い、DynamoDBでちょっとだけ検索を行い結果を返すだけのLambdaを実行する。(パターン2と同じ)
    - Lambda内でのX-Rayの有効化を行うため、X-Rayを有効化したLambda Layerを作成し、このLambdaに紐づけた上で、"import layer"でLayerに記載した内容を読み込む。X-Rayを有効化するためのLayerの作成方法については「参考」欄のサイトに詳細あり。

```python:mksamba-x-ray03
import boto3
import layer
import json
from boto3.dynamodb.conditions import Key

def lambda_handler(event, context):

    #適当にdynamodbにアクセス
    InputPhoneNumber = "+819011111111"
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table("mksamba-connect-userdb")
    querydata = table.query(
      KeyConditionExpression = Key("PhoneNumber").eq(InputPhoneNumber)
    )
    if querydata["Count"] == 0:
        username = "unknown"
    else:
        username = querydata["Items"][0]["Name"]
    return {
        'statusCode': 200,
        'body' : username
    }
```

#X-Rayの結果確認
- まず、X-RayのServiceMapの画面で、API Gateway 及びAPI Gatewayから呼び出される3つのLambdaが表示される。Lambda(mksamba-x-ray02)では、X-Rayを有効にしていないためDynamoDBに関する情報が表示されないが、Lambda(mksamba-x-ray03)ではX-Rayを有効化しているため、DynamoDBについてもMAPで可視化される。

![x-ray-004a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/0dd211ad-d526-6f9c-63ba-936af8927a05.png)

- パターン1(API Gateway + Lambda)の実行結果。"Hello from Lambda!"を表示するLambdaが呼び出されるだけなので、299msecで処理が完了。

![x-ray-005a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/f552c5c0-2be7-bdd7-867a-468751f2d338.png)

- パターン2(API Gateway + Lambda(X-Ray設定なし + DynamoDB)) の実行結果。Lambda内でDynamoDBの呼び出しが発生するため、所要時間が2.2secに伸びている。DynamoDBに関する処理時間は見えない。

![x-ray-006a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/def630c5-00de-4182-3b0f-3f70f8ed1489.png)

- パターン3(API Gateway + Lambda(X-Ray設定あり + DynamoDB)) の実行結果。全体の処理時間は3.0sec。（Lambda内でもX-Rayの処理を行うため、所要時間が増加したかも。複数回実行して統計したわけではないので正確なことは言えないが）
- Lambdaから呼び出されるDynamoDBの処理時間についても可視化が行われる。

![x-ray-007a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189302/74fff68f-7b70-ef31-8458-04702447886c.png)

# 所感
- サービスを呼び出す側でX-Rayを有効化すれば、そこから直接呼ばれる側の情報までを取得できる感じ。
- lambda内でX-Rayを有効にするのがまだ少し面倒で、このために初めて lambda layerを使ったので勉強になった。

# 参考記事
- [Lambda Layer と X-Ray]
(https://qiita.com/Ricordanza/items/d68d708e274e28b6bfa2)
- [話題の AWS Lambda Layers を試してみたら、予想以上に便利だった。](https://www.indetail.co.jp/blog/181211/)
- [AWS Lambda Layersでライブラリを共通化] (https://qiita.com/t_okkan/items/394a15577bd1aad46ec3)