[AWS] ローカルのWindows機で X-Ray を使う



# はじめに
AWS の [X-Rayのトップページ](https://aws.amazon.com/jp/xray/) を見ると

> AWS との連携
> AWS X-Ray は、Amazon EC2、Amazon EC2 Container Service (Amazon ECS)、AWS Lambda、AWS Elastic Beanstalk と連携します。Java、Node.js、および .NET で記述し、上記のサービスにデプロイされたアプリケーションに、X-Ray を使用できます。

と書かれていて「その環境でしか使えないの？」と思ってしまいましたが、ローカルPCでも使えます。オンプレのサーバーでも使えます。対応OSでインターネットに繋がっていれば。
というわけで、ローカルのWindows機で動かしてみます。

# 環境構築
[こちら](https://docs.aws.amazon.com/ja_jp/xray/latest/devguide/aws-xray.html) のX-Rayの構成図に描かれていますが、X-Ray は SDK から `X-Ray daemon` にデータが送信され、daemon が AWS にデータを送信する仕組みになっています。
ローカルPCで daemon が動いていればOKです。

## デーモンのダウンロード
[こちら](https://docs.aws.amazon.com/ja_jp/xray/latest/devguide/xray-daemon.html) の `デーモンのダウンロード` から。
今回は `Windows (実行可能ファイル)` を選択しました。

## Credential の設定
daemon がどのAWSアカウントにデータを送信するのかを設定しないといけません。
[先ほどのページ](https://docs.aws.amazon.com/ja_jp/xray/latest/devguide/xray-daemon.html) の `X-Ray にデータを送信するアクセス権限をデーモンに付与する` に書かれている通り、credentials ファイルにIAMユーザーのアクセスキーを設定します。
credentialsファイルは、通常は `<ホームディレクトリ>/.aws/credentials` になります。

```ini
[default]
aws_access_key_id = アクセスキー
aws_secret_access_key = シークレットキー
```

どうやら自動的に `[default]` プロファイルが使われるようで、複数のAWSアカウント・IAMユーザーを利用している人は、設定切り替えが少し面倒になるケースもあるかもしれません。

## デーモン実行
ダウンロードしたzipを解凍。
`cfg.yaml`で動作設定ができますが、ここでは変更なしで。
`DOS` でデーモンのexeを実行。

```dos
> cd <xray_windows.exeのあるディレクトリ>
> .\xray_windows.exe -o -n ap-northeast-1
2019-06-19T14:20:19+09:00 [Info] Initializing AWS X-Ray daemon 3.0.1
2019-06-19T14:20:19+09:00 [Info] Using buffer memory limit of 80 MB
2019-06-19T14:20:19+09:00 [Info] 1280 segment buffers allocated
2019-06-19T14:20:19+09:00 [Info] Using region: ap-northeast-1
2019-06-19T14:20:19+09:00 [Info] Starting proxy http server on 127.0.0.1:2000
```

コマンドラインオプションについて。
`-o` はローカルモード。ローカルPCで実行する場合は必須。
`-n` でリージョン指定。どのリージョンの X-Ray にデータを送信するかをここで指定します。

このDOS窓は開きっぱなしにしておきます。


# テストプログラム

Python3.6 のプログラムでお試しします。

### 必須ライブラリ
`aws-xray-sdk` をインストール。

```dos
> pip install aws-xray-sdk
```
[「LambdaでX-Rayを使ってみた」の記事](https://qiita.com/n-ishida/items/480dc9248ebdb000a582) と同じように、インストールせずに必要なライブラリだけ配置する方法でもOKです。

### ソース
[「LambdaでX-Rayを使ってみた」の記事](https://qiita.com/n-ishida/items/480dc9248ebdb000a582) と同じ処理内容。
SNSをpublishするたけのプログラムです。

```python:test_xray.py
import json
import boto3
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch
patch(['boto3'])


def lambda_handler(event, context):

    client = boto3.client("sns", region_name="ap-northeast-1")
    print(client)

    request = {
        'TopicArn': "<SNS Topic の ARN>",
        'Message': "test",
        'Subject': "test"
    }
    response = client.publish(**request)
    status_code = response['ResponseMetadata']['HTTPStatusCode']

    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }


if __name__ == '__main__':
    xray_recorder.begin_segment("local-test_x-ray")
    lambda_handler(None, None)
    xray_recorder.end_segment()
```

Lambda function でお試ししたソースとの違いは、
　`xray_recorder.begin_segment("local-test_x-ray")`
　`xray_recorder.end_segment()`
を明示するところ。
そのため
　`from aws_xray_sdk.core import xray_recorder`
も必須です。

`begin_segment` が無いと、実行時にエラーになります。
`end_segment` が無いと、エラーにはなりませんが、いつまでたってもデータ送信が行われません。


# 実行 & 結果

デーモンを動かしているDOSとは別にDOS窓を開いて、テストプログラムを実行

```dos
> python test_xray.py
```

正常に動作すれば、デーモンのDOSに以下のようなログが表示されます。

```dos
2019-06-19T14:48:13+09:00 [Info] Successfully sent batch of 1 segments (0.097 seconds)
```

デーモンで指定したAWSアカウント、リージョンの X-Ray 画面を見ると、このように計測データがputされています。
![2019-06-19 14_55_15-タスク ビュー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193715/65153e86-eb8d-662e-9871-c1ceab1ba7e8.jpeg)