EventBridge イベント配信エラーログの確認方法【DLQでログを取得する】

# はじめに
AWS EventBridgeルールは、各種サービス間のイベント連携に非常に便利ですが、イベント配信エラーが発生した際にCloudWatchの「`FailedInvocations`」メトリクスで検知できても、実際のエラーログをコンソール上で確認するのは難しい場合があります。

本記事では、主にイベント配信エラーの発生時にDLQ（デッドレターキュー）を活用してエラーログを取得する手法に焦点を当て、マネジメントコンソールとCloudFormationの両パターンでDLQ設定およびログ取得方法を解説します。

# EventBridgeのエラー原因とログ確認の課題

EventBridgeで発生するエラーにはさまざまな原因がありますが、運用現場でよく見受けられる例として、以下の2つのケースが考えられます。

- **(1)ターゲット側エラー**  
  イベント自体は正常に配信されたものの、たとえばECSタスクやSSMオートメーションなど、ターゲット側で処理中にエラーが発生するケースです。  
  この場合、**CloudTrail**のイベントログからエラーの詳細を確認できます。  
  - **ECSタスクの場合:** イベント名「`RunTask`」でフィルタリング  
  - **SSMオートメーションの場合:** イベント名「`StartAutomationExecution`」でフィルタリング

- **(2)イベント配信失敗エラー**  
  EventBridgeからのイベントがそもそもターゲットに届かず、配信自体が失敗するケースです。  
  ※ このケースは、CloudTrailにログが記録されない場合があり、こうした場合はDLQ（デッドレターキュー）を利用してエラーログを取得する方法が有効です。

<br>

【参考】
[AWS公式ドキュメント：EventBridge で配信されていないイベントを処理するためのデッドレターキューの使用](https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-rule-dlq.html)

# DLQ設定方法

EventBridgeのイベント配信エラーログの配信先としてDLQを設定する方法を以下の２パターンでご紹介します。

1. マネジメントコンソールから設定する場合
1. CloudFormationで設定する場合（サンプルコードあり）

### 前提条件
- EventBridgeルールおよびターゲットを作成済み
- EventBridge用のIAMロールも作成済み



## マネジメントコンソールからDLQを設定する場合

### 1. DLQ用のSQSキューを新規作成する

マネジメントコンソールにログインし、「SQS」のサービス画面を開き、「キューの作成」ボタンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/31ee59a1-9293-c2f6-d1af-ecdd3f034844.png)

「名前」欄に任意の名前を入力し、その他の設定はデフォルトのまま一番下の「キューを作成」ボタンをクリックしてSQSキューを作成します。

### 2. EventBridgeルールでDLQを設定する

DLQを設定したいEventBridgeルールの詳細画面を開き、「ターゲット」セクションの「編集」ボタンをクリックします。
![スクリーンショット 2025-02-11 16.31.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/5bb1cf4d-5896-44de-2ee6-d0bf0304fcaa.png)

すると、ターゲット情報の編集画面が開かれるので、一番下の方までスクロールしていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/dae7c267-7624-a7c9-b4a3-8fc731c5598a.png)

下の方に、「追加設定」＞「デッドレターキュー」という項目があるので、
ここで「`デッドレターキューとして使用する、現在の AWS アカウントの Amazon SQS キューを選択`」にチェックを入れ、先ほど作成したSQSキューを選択し、EventBridgeの設定を更新します。

![スクリーンショット 2025-02-11 16.39.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/2cb7c6e8-afd2-95f4-1a41-d5cb61a98bda.png)

設定完了後、EventBridgeルールの詳細画面からDLQが正しく設定されていることを確認できます。

![スクリーンショット 2025-02-11 17.41.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/08dd3fba-47a4-2386-ba79-6cc04d3fa1a0.png)


※ SQSキューはデフォルト設定で作成されるため、初期のキューポリシーは以下のようになります。

```json
{
  "Version": "2012-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__owner_statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<AWSアカウントID>:root"
      },
      "Action": "SQS:*",
      "Resource": "arn:aws:sqs:<リージョン>:<AWSアカウントID>:<SQS名>"
    }
  ]
}
```

このSQSをDLQとして設定すると、以下のポリシーが自動的に追加されます。

```json
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "events.amazonaws.com"
      },
      "Action": "sqs:SendMessage",
      "Resource": "arn:aws:sqs:<リージョン>:<AWSアカウントID>:<SQS名>",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:events:<リージョン>:<AWSアカウントID>:rule/<EventBridgeルール名>"
        }
      }
    }
```

自動追加されたポリシーは、[AWS公式ドキュメント](https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-rule-dlq.html#eb-dlq-perms)に記載のあるものと同じパターンですね。


## CloudFormationでDLQを設定する場合

以下は、EventBridge ルールに DLQ用のSQSキューを指定するサンプル（抜粋）です。
イベント配信が失敗した場合、指定したDLQにエラーログが蓄積され、後から詳細を確認できます。


```yml
AWSTemplateFormatVersion: '2010-09-09'

Resources:
  # EventBridgeで配信失敗したイベントを処理するDLQ
  EventDlq:
    Type: AWS::SQS::Queue
    DeletionPolicy: Delete
    UpdateReplacePolicy: Delete
    Properties:
      QueueName: "Event-DLQ"
      MessageRetentionPeriod: 345600 # 4日

  # EventBridgeのイベント配信失敗時に、DLQへエラーメッセージ送信できるようにするポリシー
  EventDlqPolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      Queues:
        - !Ref EventDlq
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          # @see https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-rule-dlq.html#eb-dlq-perms
          - Sid: "Allow EventBridge Send Message To DLQ"
            Effect: Allow
            Principal:
              Service: "events.amazonaws.com"
            Action: "sqs:SendMessage"
            Resource: !GetAtt EventDlq.Arn
            Condition:
              ArnEquals:
                "aws:SourceArn": !GetAtt EventBridgeRule.Arn

  # デモ用のEventBridgeルール
  EventBridgeRule:
    Type: AWS::Events::Rule
    Properties:
      EventPattern:
        source:
          - "aws.ec2"
        detail-type:
          - "EC2 Instance State-change Notification"
        detail:
          state:
            - "stopped"
      Targets:
        - Id: StartEc2Automation
          Arn: !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}::automation-definition/AWS-StartEC2Instance:$LATEST"
          RoleArn: !GetAtt EventBridgeRole.Arn
          DeadLetterConfig:
            Arn: !GetAtt EventDlq.Arn # <--- ここでDLQを指定する
          InputTransformer:
            InputPathsMap:
              instanceId: "$.detail.instance-id"
            InputTemplate: !Sub |
              {
                "InstanceId": ["<instanceId>"],
                "AutomationAssumeRole": ["${SsmAutomationRole.Arn}"]
              }
```

- [サンプルのCFnテンプレート全体はこちら（当記事の一番下にあります）](#参考cfnサンプルテンプレート全文)

# デモ： 配信失敗エラーログをDLQから確認してみる

本セクションでは、意図的に EventBridge ルールのイベント配信を失敗させ、DLQに蓄積されたエラーログを実際に確認する手順を紹介します。

## シナリオ

**イベントのトリガー:**  
EC2インスタンスの停止イベント

**ターゲット:**  
SSMオートメーション（EC2を起動する処理）

### 本来のフロー

1. EC2インスタンスを手動で停止する  
2. EventBridgeルールが、EC2インスタンスの停止イベントを検知する  
3. EventBridgeが、SSMオートメーションに対してイベントを配信する
4. SSMオートメーションが起動され、EC2インスタンスが自動的に起動される

### 今回のデモの流れ（意図的な設定ミスによる配信失敗）

1. EC2インスタンスを手動で停止する  
2. EventBridgeルールが、EC2インスタンスの停止イベントを検知する  
3. <font color="red">設定に不備があるため、EventBridgeからのイベント配信が失敗する</font>  
4. <font color="red">配信失敗エラーがDLQに蓄積されるので、DLQ内のエラーログを確認する</font>

このデモを通じて、設定ミスやその他の理由でイベント配信が失敗した場合に、DLQを活用してエラーログを取得する方法を確認いただけます。

## デモ


### 1. 意図的にEventBridgeルールの設定を間違える

```yml
  EventBridgeRule:
    Type: AWS::Events::Rule
    Properties:
      EventPattern:
        source:
          - "aws.ec2"
        detail-type:
          - "EC2 Instance State-change Notification"
        detail:
          state:
            - "stopped"
      Targets:
        - Id: StartEc2Automation
          Arn: !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}::automation-definition/AWS-StartEC2Instance:$LATEST"
          RoleArn: !GetAtt EventBridgeRole.Arn
          DeadLetterConfig:
            Arn: !GetAtt EventDlq.Arn
          InputTransformer:
            InputPathsMap:
              instanceId: "$.detail.instance-id"
            InputTemplate: !Sub |
              {
                "InstanceId": ["<instanceId>"],
                ### ↓ ここの設定値を誤ったものに変更する ###
                "AutomationAssumeRole": "${SsmAutomationRole.Arn}"
              }
```
上記は先ほどご紹介したCloudFormationのサンプルコードのEventBridge抜粋部分ですが、
一番最後の値を
`"AutomationAssumeRole": ["${SsmAutomationRole.Arn}"]`
↓
`"AutomationAssumeRole": "${SsmAutomationRole.Arn}"`
に変更しました。（本来は配列であるべきですが、ただの文字列にしました）

- 【参考】
  - [StartAutomationExecution APIのリファレンス](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/APIReference/API_StartAutomationExecution.html#systemsmanager-StartAutomationExecution-request-Parameters)
  - `Parameters`は配列（array）で渡す必要があります

### 2. EC2インスタンスを停止する

マネジメントコンソールなどから、任意のEC2インスタンスを１つ停止させます。

### 3. イベント配信が失敗する

EventBridgeルールの詳細画面の「モニタリング」タブを確認すると、
`FailedInvocations`メトリクスのカウントが１になっていますね。
（反映されるのに５分ほどかかるかもしれません）

![スクリーンショット 2025-02-11 17.52.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/d91f8fbe-daff-2609-a217-6e615b7dc56b.png)


### 4. DLQからエラーメッセージを確認する

DLQ用に作成したSQSキューの詳細画面を開き、「メッセージを送受信」ボタンをクリックします
![スクリーンショット 2025-02-11 17.48.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/398307ce-13b9-f45a-8cf8-71123d77adfd.png)

「メッセージをポーリング」ボタンをクリックすると、イベント配信失敗時のエラーメッセージを取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/205d5f93-4e08-c496-5fde-5d51370f1b52.png)

メッセージの中身を確認してみましょう。
「本文」タブを見てみると、EventBridgeルールに設定したパラメータが表示され、
`"AutomationAssumeRole"`の値が配列でなく文字列になっているのが確認できます。

![スクリーンショット 2025-02-11 18.10.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/f9b01303-8245-49cc-48b4-8806aae8fe40.png)

続いて、「属性」タブを見てみると、以下のエラーメッセージが表示されています。
- ERROR_CODE：`INVALID_JSON`
- ERROR_MESSAGE：`Invalid input for target.`

![スクリーンショット 2025-02-11 18.13.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613419/7e8067c3-fff5-92e2-d7ea-3bbca2aa2a3e.png)

この結果、InputTransformerに指定した値の形式が不正であったため、イベント配信に失敗したことが確認できます。

# 参考：CFnサンプルテンプレート全文

以下は、今回のデモで使用したCloudFormationテンプレート全文です。
※ EventBridgeルールの設定値は、意図的に変更した部分以外は正しい設定になっています。

```yml
AWSTemplateFormatVersion: '2010-09-09'
Description: |
  EventBridgeでEC2停止イベントを受け取り、SSMオートメーションを実行する。
  EventBridgeルールとSSMオートメーションを連携した動作確認用の構成。

Parameters:
  AmiId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64

Resources:
  # EventBridgeルール
  EventBridgeRule:
    Type: AWS::Events::Rule
    Properties:
      EventPattern:
        source:
          - "aws.ec2"
        detail-type:
          - "EC2 Instance State-change Notification"
        detail:
          state:
            - "stopped"
      Targets:
        - Id: StartEc2Automation
          Arn: !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}::automation-definition/AWS-StartEC2Instance:$LATEST"
          RoleArn: !GetAtt EventBridgeRole.Arn
          DeadLetterConfig:
            Arn: !GetAtt EventDlq.Arn
          InputTransformer:
            InputPathsMap:
              instanceId: "$.detail.instance-id"
            InputTemplate: !Sub |
              {
                "InstanceId": ["<instanceId>"],
                "AutomationAssumeRole": ["${SsmAutomationRole.Arn}"]
              }

  # EventBridge用のIAMロール
  EventBridgeRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - events.amazonaws.com
                - ssm.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: "AllowSsmAutomation"
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - ssm:StartAutomationExecution
                  - ssm:GetAutomationExecution
                Resource: !Sub "arn:${AWS::Partition}:ssm:${AWS::Region}::automation-definition/AWS-StartEC2Instance:*"
              - Effect: Allow
                Action: iam:PassRole # SSMオートメーションの引数にロールを渡すために必要
                Resource: !GetAtt SsmAutomationRole.Arn

  # SSMオートメーション用のIAMロール
  SsmAutomationRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: ssm.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: InvokeSSMAutomationPolicy
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action:
                  - ec2:StartInstances
                  - ec2:DescribeInstances
                  - ec2:DescribeInstanceStatus
                Resource: "*"

  # EventBridgeで配信失敗したイベントを処理するDLQ
  EventDlq:
    Type: AWS::SQS::Queue
    DeletionPolicy: Delete
    UpdateReplacePolicy: Delete
    Properties:
      QueueName: "Event-DLQ"
      MessageRetentionPeriod: 345600 # 4日

  # EventBridgeのイベント配信失敗時に、DLQへエラーメッセージ送信できるようにするポリシー
  EventDlqPolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      Queues:
        - !Ref EventDlq
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          # @see https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/eb-rule-dlq.html#eb-dlq-perms
          - Sid: "Allow EventBridge Send Message To DLQ"
            Effect: Allow
            Principal:
              Service: "events.amazonaws.com"
            Action: "sqs:SendMessage"
            Resource: !GetAtt EventDlq.Arn
            Condition:
              ArnEquals:
                "aws:SourceArn": !GetAtt EventBridgeRule.Arn

  Ec2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref AmiId
      InstanceType: t2.micro
      Tags:
        - Key: Name
          Value: !Ref "AWS::StackName"
```