PagerDuty 設定ガイド (トリアージ編4) - Event Orchestrationでアラートへの対処を自動化する

各Eventに対するルールを設定しておくことで、PagerDutyでEventを受け取った際にその処理を自動化することができます。この記事ではEvent Orshestrationを利用して、どのようなルールが設定できるのか説明します。
![IncidentLifecycle_EO.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/bf30daa9-1a56-0e55-944f-f0b2aad8fc07.png)

本記事で説明する機能の一部は、AIOps等の追加ライセンスがないと利用できないものがあります。詳細は[ナレッジベース:Event Orchestration](https://support.pagerduty.com/main/lang-ja/docs/event-orchestration)を参照ください。

## Event Orchestrationとは
監視ツール等から送られるEventをPagerDutyで受け取り、その処理を行うための機能群になります。以下4つの機能で構成されています:
1. **Integrations**: Eventの受け取り口(Integration-KeyとEmailアドレス)を作成します。
1. **Global Orchestration Rules**: Eventに関するルールを定義し、自動処理します。
1. **Service Routes** (Routing Rules): Eventを各Serviceに紐づけます。
1. **Service Orchestration Rules**: Eventに関するルールを定義し、自動処理します。

1.Integrationsと3.Service Routesに関しては、[検知編の記事](https://qiita.com/ymotomu/items/1edf89eb77a03f8b64e3)を参照ください。
この記事では、2.Global Orchestration Rules と 4.Service Orchestration Rulesについて説明します。

## Global Orchestraion Rules と Service Orchestration Rules
![EO_GRules_SRules.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/1eb83efc-f198-0b1b-774b-bd36fb25f916.png)

**Global Orchestration Rules**は、複数のServiceで共通の処理を行う際に利用します。
Routing RulesでEventを各Serviceに振り分ける前に適用されるので、1つのルールで全てのEventを対象に処理を行うことができます。

**Service Orchestration Rules**は、各Serviceの固有の処理を定義します。
Service Orchestration Ruleは、Service Integrationで受信したEventにも適用されます。

なお、最後に評価されたルールが優先されるため、同種のActionがGlobal Orchestration RulesとService Orchestration Rulesの両方で定義されていた場合、後者のService Orchestrations Rulesで上書きされます。

## Event Rules
Global Orchestraion Rules と Service Orchestration Rulesは、複数のEvent Ruleで構成されています。下図の四角いブロックがEvent Ruleになります。
![EventRules_Graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/e702a2cc-143c-4901-1cb8-11a1280e012d.png)

各Event Ruleには、**Conditions** (Eventに関する条件) と **Actions** (ConditionsにマッチしたEventに対して行う処理) を設定します。

各ルールが評価される順序:
- Event Ruleの評価は**1**からスタートし、ルールにマッチした場合は右方向、マッチしなかった場合は下方向のルールの評価に移ります。
- あるEventが**1**のConditionsにマッチした場合、**1**のActionsを実行し、(右側にルールがないため)処理は終了します。
- あるEventが**1**のConditionsにマッチしない場合、下方向へ**2**の評価に進みます。
    - **2**にマッチした場合は**2**のActionsを実行後、右方向へ**2A**の評価に進みます。
        - **2A**にマッチしなかった場合、**2B**の評価に進みます。

### Conditions
Eventに関する条件を設定します。
![EventRule_Conditions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/7849871c-6c2b-2fa2-ec5d-81cd64590686.png)

利用可能なConditions:
1. *If events match certain conditions*: Eventに含まれるデータ(KeyとValue)に関する条件
2. *On a recurring weekly schedule*: 週次の定期的なスケジュール
3. *During a scheduled date range*: 特定の期間を日時で指定
4. *Depends on event frequency*: Eventの受信頻度 (例: 5分間に10 Event以上)

これらをAND[^1]/ORで組み合わせ、対象とするEventを柔軟に指定することが可能です。
[^1]: 2-4のConditionを選択した場合、GUIではAND条件が設定できません。しかし、[PCL](https://support.pagerduty.com/main/lang-ja/docs/event-orchestration#advanced-configuration-with-the-and-operator)を利用すれば、AND条件を設定することが可能です。

Integrationに事前にEventを送っておくと、送られたEventに含まれるデータを参照しながら条件を設定することができます。(Event内のデータをクリックすると、クリックした箇所のKeyとValueがセットされます。)

### Actions
ConditionsにマッチしたEventに対して、行う処理を設定します。

**Incident Data　- Basic Event**
インシデントに関するデータを変更できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/e8dc8257-0492-1762-9920-5d7d9a5b9c36.png)

- *Suppress incident...*: インシデントを起票せず、通知も行いません。
- *Pause notifications...*: 指定した秒数、通知を一時停止します。[Auto Pause](https://qiita.com/ymotomu/items/66aab8eb8d04bd59ac67)を上書きできます。
- *Set incident priority...*: インシデントのPriorityを設定・変更します。
- *Add incident note*: インシデントにNotes欄に手順書へのリンク等、任意のコメントを追加します。

**Incident Data - Event Fields**
Eventに含まれるデータを編集したり、追加することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/9c68fdf7-053a-728a-4db3-f9a349e6d059.png)

上記の例では、インシデントのタイトル(Summary)を変更しています。

変更を行うEvent Fieldを選択し、値を指定します。
利用できる値は、以下です:
- Eventに含まれるフィールド([CEF](https://qiita.com/drafts#cefcommon-event-format%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%A6%E6%9D%A1%E4%BB%B6%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B)) - 例: `event.class`, `event.custom_details.plain_body`
- Eventに含まれるフィールド(CEF変換前) - 例: `raw_event.client`,`raw_event.description`
- 次項のVariablesで作成した変数 - 例: `variables.MessageID`, `variables.Location`
- 任意の文字列 - 例: `[緊急]`, `Infraチーム`

**Incident Data - Custom Fields**
[Custom Fields](https://support.pagerduty.com/main/lang-ja/docs/custom-fields-on-incidents)に値を追加・変更します。
値の指定方法は、Variables, Event Fields, または静的テキストが利用できます。
![EO_setting_customfield_values.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/a4821f01-e8a3-0974-73b5-838c38f8d68c.png)

Custom Fieldsは、インシデント詳細画面内で共有Fieldsの下に表示されます。
![CustomFields_Incident_detail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/432e82cb-164d-0970-79bd-8bc7c1503852.png)

**Variables**
前述のEvent Fieldsで利用する変数を定義できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/3baaddc3-085d-8e16-bab6-c028549a5b52.png)
上記の例では、Emailで受信したEventの本文から、メッセージIDの値を正規表現で抽出し、MessageIDという変数を定義しています。

**Alert Data**
アラートに関するデータを変更できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/957e4efe-9d2e-ebb3-8326-47e729ca7f05.png)
- *Set alert severity to...*: Eventに含まれる[`payload.severity`](https://developer.pagerduty.com/docs/ZG9jOjExMDI5NTgx-send-an-alert-event)の値を上書きします。
値は`critical`, `error`, `warning` or `info`の4つで、前者2つはHigh-Urgency, 後者2つはLow-Urgencyの通知ルールが選択されます。[^2]
[^2]: [Dynamic Notification](https://qiita.com/ymotomu/items/3cb2d8898857cdcbab02#alert%E3%81%AEseverity%E3%81%AB%E5%90%88%E3%82%8F%E3%81%9B%E3%81%A6urgency%E3%82%92%E5%8B%95%E7%9A%84%E3%81%AB%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)が有効になっている場合。デフォルトでは、severityの値に関わらずHigh-Urgencyとして扱います。
- *Override the given `event_action` behavior*
    - *Always trigger an alert*: `event_action`の値を無視して、Eventを`trigger`として扱います。
    - *Always resolve an alert*: `event_action`の値を無視して、Eventを`resolve`として扱います。*

*: ユースケースとしては、Emailでトリガーされたアラートを、後続のEmailを受信時に自動復旧させる場合があります。
Emailは`event_action`の情報を持たないため、デフォルトでは全て`trigger`として扱われます。本文に"復旧"の文字列が含まれたメールを受信した際に、`resolve`として扱うルールを設定すると、"復旧"のメールを受信した際に、アラートの状態をResolveに変更することができます。

**Automation - Webhooks**
PagerDuty外の仕組みと連携し、自動化を行うことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/d3204f38-c976-684c-6fce-43e234a1c9d4.png)

- *Enable webhook to specified endpoint for these incidents*: チェックを入れると、Webhookの送信を有効化します。 
    - *Must be maually triggered through incident dropdown*: インシデント詳細画面のドロップダウンメニューにボタンを追加し、担当者がボタンを押すとWebhookを送信します。
    - *Automatically triggered on incident creation*: インシデント起票時にWebhookを自動送信します。
- *Name*: ボタン名(実行される処理の説明)
- *API Endpoint*: Webhookの送信先URL
- *Headers*: WebhookのHTTPヘッダーに含める情報を指定
- *JSON Body Fields*: WebhookのBodyに含める情報を指定

ユースケースとしては、インシデント起票時にWebhookをAWS EventBridgeに送り、LambdaやStep Functionsと連携してEC2インスタンスの再起動や、ステータスページ更新を自動化するといったものがあります。

実行結果などの情報をPagerDutyに戻したい場合は、[PagerDuty REST API](https://developer.pagerduty.com/docs/ZG9jOjQ2NDA2-introduction)を利用してPagerDutyに情報を渡す仕組みを送信先で構築する必要があります。

**Automation - Automation Actions**
PagerDutyが提供する自動化の仕組み(Automation ActionsやRunbook Automation)と連携し、Event-Drivenでジョブを実行することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/0cd7f141-29b8-db0f-72c3-60e8a93f1f69.png)

Automation Actionsで作成したジョブを選択できます。
自動診断や自動修復、復旧後の正常性確認等、インシデント対応時に必要な作業を自動化することで、ミスのない迅速な対応と担当者の負担軽減が可能です。

進捗や実行結果等の情報をPagerDutyに戻す仕組みが用意されているため、PagerDutyやSlack上で実行ログや結果を確認しながら、迅速に対応を継続できます。

## Event Rulesの設定例
### CEF(Common Event Format)を利用して条件を指定する
PagerDutyでは標準のEventフォーマット([共通イベントフォーマット PD-CEF](https://support.pagerduty.com/main/lang-ja/docs/pd-cef))が定義されています。
PagerDutyと連携可能な監視ツール等は、このフォーマットでEvent情報を送ります。ここではCEFの構造と、CEFを利用したEvent Rule Conditionの設定例を説明します。

以下は[Event APIv2](https://developer.pagerduty.com/docs/ZG9jOjExMDI5NTgw-events-api-v2-overview)で利用するCEFの例です:
```
{
  "payload": {
    "summary": "[Payment Process] ES Cluster Avg Max Load is > 2.5",
    "timestamp": "{{timestamp}}",
    "source": "aws:elasticache:us-east-1:852511987:cluster/api-stats-prod-003",
    "severity": "error",
    "component": "LOAD_AVERAGE",
    "group": "Domainname:prod-es-7-1-v4, monitor, terraform:true",
    "class": "deploy",
    "custom_details": {
        "body": "aws.es.os_1min_load over prod-es-7-1-v4 was > 2.5 on average",
        "Metric value": 2.51
    }
  },
  "routing_key": "(省略)",
  "dedup_key": "central-region-dc-01:852559987:005",
  "event_action": "trigger"
}
```
必須フィールド:
- `summary`: Eventのタイトル(アラートとインシデントのタイトルに引き継がれる)
- `severity`: Eventの深刻度を4段階で指定 (`critical`, `error`, `warning`, or `info`)
- `source`: 影響を受けるシステム(hostnameやFQDN)
- `routing_key`: [Integration](https://qiita.com/ymotomu/items/1edf89eb77a03f8b64e3)で発行したIntegration-Key(32文字)
- `event_action`: Eventのタイプ(`trigger`, `acknowledge`, or `resolve`)

その他:
- `dedup_key`: アラートの重複排除キー。同じdedup_keyを持つEventは、1つのアラートに紐付けられる。値の指定がなければ、Event受信時にPagerDutyが自動付与。
- `custom_details`: 標準フィールドにない付加情報はこの下に追加される。

**例1**: Eventのタイトル(`summary`)を参照して文字列 [Payment Process] の部分一致を指定
![EvenRule_Example_condition_summary.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/7a7aa40f-4c63-01f8-ceb2-a8b619d51f59.png)

**例2**: Custom Details内のMetric valueフィールドを参照して、正規表現で3.00以下の値を指定
![EvenRule_Example_condition_customdetails.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/8d3aedcf-0340-b316-584b-eee2e78f7bfb.png)

### Emailから正規表現で情報を抽出し、Custom Detailsに格納する
Emailでは件名や本文に複数のパラメータが含まれていることがあります。Global OrchestrationでIncident Data/Event Fieldsを利用し、各パラメータをCustom Detailsに書き出しておくと、Service Orchestrationでの条件指定が簡単になります。

[Emailで利用可能な主なFields](https://support.pagerduty.com/main/lang-ja/docs/event-orchestration#if-events-match-certain-conditions)は以下です:
- `event.custom_details.subject`: 件名
- `event.custom_details.plain_body`: 本文
- `event.custom_details.from`: 送信元メールアドレス

**例1**: メール本文から情報を抽出し、Custom Detailsに追加
Variablesで、メール本文から情報を抽出し、変数(`Server`,`Severity`)を定義
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/3cf59f60-0078-0f34-c470-ce3e69e27fe5.png)

Variablesで定義した変数を利用して、Incident Data/Event Fieldsで作成した変数をCustom Detailsに追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/4f4bc183-6796-b3c2-0eed-ab6cb5e8915c.png)

**PagerDutyに送信するEmailの例**:
```
Subject: High API auth errors: 2% - prod-apigw-d01
To: (省略)
From: (省略)
cc: 

High API auth errors

Timestamp: 2023-12-30T04:24:15.041Z

Event ID: ABF023995
Auth Error Rate: 27
Server: prod-apigw-d01
Priority: 1

Event: trigger Severity: warning Source: prod-apigw-d01 Category: API Gateway User: N/A
```

**Custom Detailsが追加されたアラートの例**:
![EvenRule_Example_Email_Transformation_alert.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/9edc9f30-1cef-783e-ba12-04ef9f69dec0.jpeg)
Custom Detailsに新たにSeverityとServerのFieldが追加されました。
Global Orchestrationでこのような処理をしておくと、以降のService RoutingやService Orchestrationでは、これらのField(`event.custom_details.Server`, `event.custom_details.Severity`)を利用することができます。

### Emailで受信したアラートをLow-Urgencyとして扱う
EmailではSeverityに相当するフィールドをがないため、デフォルトでは全てHigh-Urgencyとして扱われます。通知レベルをLow-Urgencyに落としたい場合は、[ServiceでDynamic Notificationを有効](https://qiita.com/ymotomu/items/3cb2d8898857cdcbab02#alert%E3%81%AEseverity%E3%81%AB%E5%90%88%E3%82%8F%E3%81%9B%E3%81%A6urgency%E3%82%92%E5%8B%95%E7%9A%84%E3%81%AB%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)にした上で、Event OrchestrationでSeverityを変更します。

**例**: Emailに対する条件
![EvenRule_Example_Email_Conditions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/a17bf45e-0d3e-5dfd-8db1-4dbc0c140b14.png)
- 上の条件では、1つ前の例で作成した event.custom_details.Severity を利用しています。
- 下の条件では、メール本文を参照し、正規表現で指定しています。

**例**: Severityを変更し、通知レベルを Low-Urgency に変更
Alert DataでSeverityを `info` または `warning` にすると、Low-Urgencyの通知ルールが利用されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/e4ac5125-63bb-b787-1d24-2e642d3dbd2d.png)


### 件名が同じEmailを異なるアラートとして扱う
Emailでは件名を`dedup_key`として利用します。そのため、件名が同じEventは同じアラートに紐づくものと判断され、1つのアラートにまとめられます。
件名が同じEventを異なるアラートに分けたい場合は、Incident Data/Event Fieldsで`dedup_key`を変更します。

**例**: dedup_key とアラートのタイトルを変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/366db010-a6cf-a7e2-fa80-86b2913bf15b.png)
- 上の例では、`dedup_key`と`summary`にVariablesで定義した変数:Serverの値を追加しています。
- これにより、メール件名が同一でもServerの値が異なれば、別々のアラートとして扱われます。
- また、各アラートのタイトルにもServerの値が表示されます。

**例**: 件名が同一でServerが異なるEventを送信した結果
![EvenRule_Example_dedupalerts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2777160/1aa39841-b3e0-a6a9-0956-2cc80856376a.png)

## FAQ
### Emailでイベントを送っていますが、Event Ruleが適用されません。
[Global Integration](https://qiita.com/ymotomu/items/1edf89eb77a03f8b64e3)を利用して、Email連携を行っているか確認ください。
Global Orchestration RulesやService Orchestration Rulesで制御するためには、Event OrchestrationのIntegrationsで発行したEmailアドレス宛にイベントを送る必要があります。

[Service Integration](https://qiita.com/ymotomu/items/29495cd968f9c23d1939)で送信されたEmailイベントは、[Email Filter機能](https://support.pagerduty.com/main/lang-ja/docs/email-management-filters-and-rules)で制御することができます。本機能については今後拡張予定がないため、前述のGlobal IntegrationとGlobal Orchestration/Service Orchestrationの利用を推奨します。

### 正規表現にマッチしない
こちらの記事を参照ください。
- [PagerDuty の Event Orchestration の正規表現でつまずいた](https://qiita.com/sebesu/items/f2b3283b9757898e6a0f)

## PagerDuty設定ガイド 目次
[検知編](https://qiita.com/ymotomu/items/f9e8de2dfa94394df54c) | **[トリアージ編](https://qiita.com/ymotomu/items/1a40022feabae53e85c9)** | [動員編](https://qiita.com/ymotomu/items/e6d13e5284a62e3a1100) | 解決編 | 学習編
1. [一次対応を自動化する](https://qiita.com/ymotomu/items/1a40022feabae53e85c9)
1. [Alert Groupingでアラートノイズを削減する](https://qiita.com/ymotomu/items/a6665e9ad75bc2a5c600)
1. [Auto Pauseで一過性アラートの通知を削減する](https://qiita.com/ymotomu/items/66aab8eb8d04bd59ac67)
1. [Event Orchestrationでアラートへの対処を自動化する] << イマココ
1. [診断や復旧作業を自動化する](https://qiita.com/ymotomu/items/f93fc956e0c4e4642516)

## 参考リソース
* [PagerDuty利用ガイド - Responder編](https://qiita.com/ymotomu/items/42f825accbfca287464a)
* [PagerDuty AIOps](https://support.pagerduty.com/main/lang-ja/docs/aiops)
    * [Event Orchestration](https://support.pagerduty.com/main/lang-ja/docs/event-orchestration)
* [Custom Fields](https://support.pagerduty.com/main/lang-ja/docs/custom-fields-on-incidents)
* [共通イベントフォーマット PD-CEF](https://support.pagerduty.com/main/lang-ja/docs/pd-cef)
* [システム障害を未然に防ぐ「インシデント管理・対応」とは](https://www.pagerduty.co.jp/blog/what-is-incident-response)
* [PagerDuty 導入事例](https://www.pagerduty.co.jp/customers/)
* [PagerDuty - 14日間 無料トライアル](https://www.pagerduty.co.jp/lp/free-trial/)