AWS LambdaからEvent Bridgeに通知してみる

# はじめに
[前回](https://qiita.com/drafts/a49da460fd67e197a5b7/edit)、MackerelのアラートをAWS Event Bridgeに通知してみたので、
今回は、Lambda A→EventBridge→Lambda B&Cの構成を試します。
自作のアプリケーションから、カスタムイベントを発火させるイメージですね。

# 構築手順

## Lambda B&C（EventBridge受信側）
* Lambda B  
    * Lambda Function名：register-item  
    * 実行ロール：CloudWatch Logsの権限があれば良いので、「基本的な Lambda アクセス権限で新しいロールを作成」を選択
    * 処理内容：DBに商品を登録するというイメージだが、今回はログ出力するのみとします。

```python
import json

def lambda_handler(event, context):
    print(Register a new item.)
    print(event)
    return {
        'statusCode': 200,
        'body': json.dumps('Completed to register a new item.')
    }

```
* Lambda C
    * Lambda Function名：upload-log-data
    * 実行ロール：※Lambda Bと同様
    * 処理内容：登録イベントログをデータレイクにアップロードするイメージだが、今回はログ出力するのみとします。

```python
import json

def lambda_handler(event, context):
    print(f'Upload a new log in DataLake system. {event}')
    return {
        'statusCode': 200,
        'body': json.dumps('Completed to upload a new log.')
    }
```

## EventBridgeに定義の追加
1. 新規のイベントパスを追加
![custom-event-01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428042/43baf4c4-ef55-881a-0f09-01fe205aa4e1.png)

2. 上記のイベントパスを選択し、「ルールを作成」を押下
![custom-event-02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428042/8ebb5938-774b-d26d-a4c5-66743f4da987.png)

3. 必要な情報を入力し、ルールを作成![custom-event-03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428042/281061c3-d235-76d7-adb3-e263342f89e0.png)

イベントパターンに設定した値と一致するイベントが送信された時にルールが適用されます。
今回はシンプルに以下のように定義します。
![custom-event-03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428042/5ec7ae5d-d864-bcac-2993-221dd881a3f3.png)

![custom-event-05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428042/e8141f96-046f-5a10-7710-5aee1bc22b6e.png)

ターゲットに事前に作成したLambda B&Cを設定します。 
![custom-event-06.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428042/cecf805c-789b-2141-742d-c0af673ad886.png)


## Lambda A（Event通知側）の準備
本来は自作のアプリ部分になりますが、今回はLambdaで代用です。

* Lambda A
    * Lambda Function名：send-registration-event  
    * 実行ロール：LogsとEventBridge用に、以下のManagedPolicyを付与したロールを割り当て
        * AWSLambdaBasicExecutionRole
        * AmazonEventBridgeFullAccess
 
```python
import json
import boto3

def lambda_handler(event, context):
    client = boto3.client('events')
    # Source,EventBusNameは上記で作成したリソース名を指定する
    # DetailType,Detailを指定しないとエラーになったため、イベントの種類と内容というイメージで設定する
    response = client.put_events(
        Entries=[
            {
                'Source': 'custom.event.item.registration',
                'DetailType': 'registration-event',
                'Detail': '{"itemNo:":"0001", "itemName:":"Juice"}',
                'EventBusName': 'custom-application-event-bus'
            },
        ]
    )
    
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }
```


# Event通知とLambda起動の確認
今回はテストなので、Lambda A（send-registration-event ）をテスト実行しました。
EventBridge経由でLambda B&Cが起動されていることを確認します。

## CloudWatch Logsの確認
以下のLogGroupにログが出力されていることを確認できました！
`DetailType`や`Detail`には、put_eventsから送信したデータが出力されていますね。


* Lambda B（register-item ）`/aws/lambda/register-item`

```json
Register a new item.
{
    "version": "0",
    "id": "bf15bdad-2748-f9df-d351-d01f72523316",
    "detail-type": "registration-event",
    "source": "custom.event.item.registration",
    "account": "xxxxxxxxxxx",
    "time": "2020-02-28T12:10:37Z",
    "region": "us-west-2",
    "resources": [],
    "detail": {
        "itemNo:": "0001",
        "itemName:": "Juice"
    }
}
```

* Lambda C（upload-log-data）`/aws/lambda/upload-log-data`

```json
Upload a new log in DataLake system.
{
    "version": "0",
    "id": "bf15bdad-2748-f9df-d351-d01f72523316",
    "detail-type": "registration-event",
    "source": "custom.event.item.registration",
    "account": "xxxxxxxxxxx",
    "time": "2020-02-28T12:10:37Z",
    "region": "us-west-2",
    "resources": [],
    "detail": {
        "itemNo:": "0001",
        "itemName:": "Juice"
    }
}
```

# 最後に
同じAWSサービスのSQSやSNSを使っても同じようなことは実現できると思いますが、
割と簡単にPubSubの仕組みが実現できますので、使ってみてはいかがでしょうか。