Datadog イベント管理でアラートを集約し正しく届ける

:::note
本記事は [Datadog Advent Calendar 2024](https://qiita.com/advent-calendar/2024/datadog) 19日目です。
:::

## はじめに
　Datadog のオブザバビリティ機能を利用してメトリクスやログを分析し、[モニター](https://docs.datadoghq.com/ja/monitors/)の[通知](https://docs.datadoghq.com/ja/monitors/notify/)機能を使ってインフラやアプリの監視を行っている方は多いと思います。しかしサービスの環境が複雑化したり大規模化していく中で、モニター設定が増えて設定作業が複雑化したり、その結果として大量アラートが発生し処理に苦労されていたりしないでしょうか。
　Datadog の[イベント管理](https://docs.datadoghq.com/ja/service_management/events/)機能は、複雑化してきたサービス環境の悩みをお持ちの方に、アラート／イベント処理を中心として運用監視を改善する手段を提供します。またサードパーティからのアラートを集約し、統合監視を実現することを可能にします。
　本稿では実際のユースケースに基づく設定例を交えながら、イベント管理がどのように課題を解決するかをご紹介できればと思います。 

:::note warn
本稿の内容は執筆時点(2024年12月)の情報をもとに記載しています。
:::

## モニタリングの課題
　Datadog には様々なモニターがあり、Datadog が収集するオブザバビリティデータ(メトリクス、トレース、ログなど)を分析して、条件にマッチするとアラート通知を行うことができます。アラートはモニター毎に設定されたメールやチャット(あるいは外部のインシデント管理ツール)等に通知できます。
　サービスが複雑化・大規模化していくと、モニターの設定上の悩みが増えていくと思います。例えば同じタイプのインフラやアプリでもアラートの通知先が異なったり、しきい値をはじめとする監視条件が異なったりします。また条件設定によって短時間に大量のアラートを発生させてしまうリスクもあります。
　このような悩みのうち、イベント管理で解決できそうなものをいくつか列挙してみました。皆さんの課題にマッチするものはあるでしょうか。

### 大量アラートが発生する
　しきい値などモニターのアラート通知条件をシビアに設定していると、センシティブに反応してしまい、大量のアラートを短時間に発生させてしまうことがあります。またシステム構成によっては一つのコンポーネントの障害が他のコンポーネントに波及し、インフラ、アプリ、ミドルウェア、クラウドサービス等から同じようなアラートが大量に発生することがあります。そのような環境では担当者はいつも大量アラートの処理に追われてしまいます。いわゆる**アラート疲れ**ですね。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/72741c89-2a0b-0319-1d53-d934280c0561.png)

　Datadog のイベント管理には特定の条件と時間によってアラート／イベントを相関処理する機能があるので、類似したアラートを集約することができ、大量アラートの通知を防ぐことができます。


### 同じアラートでも通知先が異なる
　技術的には同じ監視対象であっても、仮想インスタンス、コンテナ、プロセス、タスクといったインスタンス毎に利用部門や利用ユーザー、SLA、重要度が異なるかもしれません。モニターでそれらの条件を識別できない場合は、オブザバビリティ情報に含まれるデータを使って識別する必要があります。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/283a8af2-a33d-0b7f-6846-eb9fb4b8ee16.png)

 　イベント管理はそのようなキー情報に対して外部データを相関処理することができるので、モニターから発生するアラート／イベントに必要なコンテキスト情報を付加し、正しい通知先にルーティングさせることができます。

### モニターが際限なく増えていく
　サービスが複雑化していくと、同じ監視対象、例えば同じ仮想インスタンスのメトリクスであっても異なる条件で監視しなければならなかったり、Priority や通知先が異なるなどして、モニターの数が増大してきます。モニターが増えるとそれだけ管理する手間も増えていくことになります。
　イベント管理を使うと Priority や通知先が異なる条件の場合でもモニターの数を抑える効果が期待できます。

### 既存の監視ツールやクラウドからのアラートを集約したい
　オンプレミスからクラウド環境に移行するようなケースで Datadog を利用する場合、Datadog 発のアラートだけでなくオンプレミスやクラウドの監視ツールや通知機能からのアラートも一時的に集約したいことがあると思います。
　Datadog は [インテグレーション](https://docs.datadoghq.com/ja/integrations/) の一部としてこうしたアラート収集機能を提供しているので、統合監視ツールとして利用することが可能です。

## Datadog のイベント管理
　イベント管理は様々なソースからアラート／イベントを取り込み、運用業務やビジネスの要求に基づく処理を行う機能です。以下の図のように、多様なデータソースからのイベントを集約して情報を付加し、相関処理して、適切な宛先にルーティングすることができます。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/faff33a9-f476-28f0-4c65-4dde2f0333b8.png)

### イベント収集
　様々なデータソースからアラート／イベントを取り込みます。モニターが生成するアラートは自動的に収集されます。また Datadog が提供する[インテグレーション](https://docs.datadoghq.com/ja/integrations/ )を介して、あるいは[イベント API](https://docs.datadoghq.com/ja/api/latest/events/) を介してイベントを収集することができます。100以上の Datadog インテグレーションがイベント収集をサポートしています。

https://docs.datadoghq.com/service_management/events/ingest/

### イベントパイプライン
　入力されたイベントはイベントパイプラインで正規化された後、情報のエンリッチやタグ付け、属性の変更といった操作を行うことができます。これにより元のイベントには含まれていないコンテキストを追加し、イベントを分類しやすくします。

https://docs.datadoghq.com/service_management/events/pipelines_and_processors/

### イベントエクスプローラー
　パイプラインで処理されたイベントはイベントエクスプローラーに表示されます。イベントエクスプローラーではリスト表示で時系列に並べ替えたり、イベントを分析してグラフなどのビューで分析を行うことができます。またパイプラインで付加したコンテキスト属性を表示して視認性を高めることができます。

https://docs.datadoghq.com/ja/service_management/events/explorer/

### イベントコリレーション
　イベントコリレーションはイベントを関連性や時間など指定した条件で相関付けし、その結果を設定された通知先に送信します。大量アラートによる頻繁な通知を削減してアラート疲れを予防すると同時に、対応するチームに正しく通知することができるようになります。

https://docs.datadoghq.com/ja/service_management/events/correlation/

### ケース管理
　ケース管理はイベント管理の機能ではありませんが、イベントコリレーション機能と密接に連携します。相関処理されたイベントからの通知はケース管理の中で定義された [プロジェクト](https://docs.datadoghq.com/ja/service_management/case_management/projects) へ割り当てられ、プロジェクト毎に設定した手段で [Team](https://docs.datadoghq.com/ja/account_management/teams/) やユーザーに通知します。ケースから Datadog [インシデント管理](https://docs.datadoghq.com/ja/service_management/incident_management/)に起票することも可能です。

https://docs.datadoghq.com/ja/service_management/case_management/

## ユースケース例: 顧客ごとに SLA があるサービスに対して異なる通知先を設定する

　今回設定例として、MSP サービスを展開する事業者を想定してみました。IT サービスを提供しているお客様ごとに SLA が設定されており、その SLA にもとづいてアラートの通知先が異なるケースです。
　下の図のようなアラート／イベント処理の流れを想定します。アラートが発生する際、アラートに **Owner ID** という属性を付与していると仮定します。MSP サービスとして **Owner ID** 毎に **SLA** と**契約名**が定義されており、SLA に対応してどの**ステータス**と **Priority** で通知するかも決まっています。そして SLA 毎に対応する **Team** が決まっており、メールやチャットなどの手段を用いて通知します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/b9156921-59b0-9a2c-9c16-169d92952a30.png)

:::note info
登場する社名はすべて架空のものです。
:::

　Datadog 内部の処理の順序は以下のようにしました:
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/47afb353-d735-4800-46c6-402699e1e92c.png)

 1. **Owner ID** を含むオブザバビリティデータを収集し、それをモニターで監視します。今回は計装したアプリから[Custom Span Tag](https://docs.datadoghq.com/ja/tracing/trace_collection/custom_instrumentation/python/dd-api?tab=decorator#adding-tags) として **Owner ID** を送れるようにしています。また、イベント API を通じて **Owner ID** を含むイベントを送ることもできます
 2. イベント管理に送られたアラート／イベントは、パイプラインで **Owner ID** に対するエンリッチ処理が行われ、**SLA** 情報、**契約名**、**ステータス**などの情報が追加されます
 3. コリレーションルールで相関処理が行われ、単一のケースとして自動的に起票されます
 4. ケース管理があらかじめ決められたルールにもとづき担当する各チームへ通知します

## 設定

それでは今回行った実際の設定と動作を見ていきます。

### モニターから属性付きのアラートを送信する
　まずは [APM Monitor](https://docs.datadoghq.com/ja/monitors/types/apm/) の設定です。今回、監視対象の APM Trace に [span tag]((https://docs.datadoghq.com/ja/tracing/trace_collection/custom_instrumentation/python/dd-api?tab=decorator#adding-tags)) `@owner_id.name` として **Owner ID** 情報を付与しているので、Trace Monitor で `owner_id` 情報を取り出してアラートに付与する必要があります。
　Monitor 自体は、Error Trace をカウントしてしきい値を超えたらアラートを出すように設定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/570b265d-a0a1-124c-3832-2201c27c2b63.png)

　取り出した `owner_id` などの情報は[モニターの通知](https://docs.datadoghq.com/ja/monitors/notify/)メッセージ内に JSON で記載しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/54570f70-05bf-9298-b8f3-cc42eb513375.png)


### イベント API でイベントを挿入する

　[イベント API](https://docs.datadoghq.com/ja/api/latest/events/) でも同様に `owner_id` 付きのイベントを送ります。情報は tag でも付与できますが、Trace Monitor からのアラートと同じパイプラインで処理するために `text` の中で JSON で付与しています。
 
```shell
curl -X POST "https://api.datadoghq.com/api/v1/events" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "DD-API-KEY: ${DD_API_KEY}" \
-d @- << EOS
{
  "title": "fruits-appサービスで状態が変化しました",
  "text": "fruits-appサービスが停止しました {\"service\": \"fruits-app\", \"env\": \"dev\", \"resource_name\": \"none\",\"owner_id\": \"XVVA0001\"}",
  "alert_type": "error",
  "aggregation_key": "fruits-appサービスで状態が変化しました",
  "tags": [
    "service:fruits-app",
    "env:dev",
    "resource_name:none",
    "owner_id:xvva0001"
  ]
}
EOS
```

### イベントパイプラインで処理する

　集めたアラート／イベントを[イベントパイプライン](https://docs.datadoghq.com/ja/service_management/events/pipelines_and_processors/)で処理します。今回は以下のようなパイプラインを作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/29087c3d-a3c6-10c9-56e3-e326c3d27657.png)

 最初のパイプライン **SLA 情報をイベントに追加する** ではすべてのイベントを対象に JSON 情報の抽出とエンリッチを行っています。2番目のパイプライン **SLA にもとづきイベントのステータスを設定し直す** では `status:error` のイベントのみ処理します。
 
　では、パイプラインの中のプロセッサーの設定を見ていきます。
 
#### Grok Parser: アラート属性をイベントメッセージ内の JSON から取り出す

　[Grok Parser](https://docs.datadoghq.com/ja/service_management/events/pipelines_and_processors/grok_parser?tab=matchers) を使い、以下のシンプルなルールでメッセージ内の JSON からアラート詳細情報を取り出しています。取り出した情報は `contract` 属性の下に追加されます。`owner_id` は `contract.owner_id` として属性に取り込まれます。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/fbf12556-0542-ce69-ff88-b7d315dbc3da.png)

#### Lookup Processor: イベント情報にもとづき SLA と契約名を追加する

　[Lookup Processor](https://docs.datadoghq.com/ja/service_management/events/pipelines_and_processors/lookup_processor) を使用します。`contract.owner_id` をキーに[リファレンステーブル](https://docs.datadoghq.com/ja/integrations/guide/reference-tables/)を参照してイベントに **SLA** 情報 `sla` と**契約名** `contract_name` を取り出します。リファレンステーブルは事前に作成しておきます。取り出した属性は`contract_details`の下に追加されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/882d1131-1f98-14d9-3b82-246f267087ae.png)

#### Remapper: SLA タグを追加する。

　[Remapper](https://docs.datadoghq.com/ja/service_management/events/pipelines_and_processors/remapper) を利用して抽出した **SLA** 情報 `contract_details.sla` を `contract_sla` タグとして追加します。これは後にコリレーションルールで SLA 判定をする際に使用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/9802ba62-d2b0-e59b-4d37-6b16be17f239.png)

#### String Builder Processor: イベントタイトルに契約名を付加する

　取り出した契約名は `contract_details.contract_name` イベント属性として参照できますが、より分かりやすくするためにタイトルにも追加します。[String Builder Processor](https://docs.datadoghq.com/ja/service_management/events/pipelines_and_processors/string_builder_processor) を使用しました。 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/bef27400-5ab5-26a9-eeed-2ccfec2181f9.png)

#### Category Processor: SLA にもとづき Priority を再設定する

　ここから2番目のパイプラインの処理に移ります。まず [Category Processor](https://docs.datadoghq.com/ja/service_management/events/pipelines_and_processors/category_processor) を使って **SLA** にもとづき **Priority** 値を `contract_details.priority` に定義します。**SLA High = P2**、**SLA Medium = P3**、**SLA Low = P4** となるように設定しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/863f945d-e3b2-7d1a-a1cb-76a39cd15c74.png)

#### Remapper: Priority タグを設定する

 [Remapper](https://docs.datadoghq.com/ja/service_management/events/pipelines_and_processors/remapper) を使って前のステップで定義した **Priority** 値 `contract_details.priority` を　`priority` タグにコピーします。これは後に自動起票されるケースに対して反映されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/23296dc1-6cba-70a1-7fae-57bc783af50c.png)

#### Category Processor: SLAにもとづきイベントステータスを決定する

　 [Category Processor](https://docs.datadoghq.com/ja/service_management/events/pipelines_and_processors/category_processor) を使って、**SLA** にもとづき**イベントステータス**を `contract.event_status` 属性に定義します。**f = emergency**、**a = alert**、**w = warning** というマッピングになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/a7a9c92b-7cc5-820f-fbf8-18ba3aec575e.png)

#### Status Remapper: イベント属性からイベントステータスを再設定する

　[Status Remapper](https://docs.datadoghq.com/ja/service_management/events/pipelines_and_processors/status_remapper) を使って、定義した**イベントステータス**を反映させます。イベントエクスプローラー上に表示される各イベントの**ステータス**として表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/f976dedb-d075-559e-75b5-6e8a834bb38c.png)

　以上でパイプライン処理は終わりです。
 
### イベントエクスプローラーで SLA や契約名付きのイベントを表示する

　パイプライン処理を経たイベントはイベントエクスプローラーに表示されます。最初に作成した APM Monitor やイベント API スクリプトを使ってイベントを送信すると、イベントエクスプローラーで以下のように表示さました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/77c0aa37-1bfa-f3c0-6bca-46dce34f5982.png)

 今回はエンリッチしたイベント用にイベントエクスプローラーをカスタム定義しています。**ステータス**や**契約名**、**SLA** といった情報を表示し、並べ替えやフィルタが簡単にできるようにしています。同じタイプのイベントでも異なる**ステータス**が割り当てられていたり、タイトルに**契約名**が表示されていることを確認いただけるかと思います。
　以下はイベント属性の一部の抜粋です。パイプラインで処理した `contract` や `contract_details` の各属性が追加されていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/a3df52f6-4f37-aa31-7616-9aae3c093d4e.png)

### イベントの重複を排除しつつ通知先を制御する

　次にコリレーションルールの[パターン](https://docs.datadoghq.com/ja/service_management/events/correlation/patterns/)を使ってイベントの通知先の制御および同じイベントの相関処理を設定します。以下は High SLA パターンの例です。**Correlation events** で、タグ `contract_sla:high` にマッチするようフィルタを定義しています。**Advanced correlation logic** では、最初のイベントから1時間の間は同じ条件にひっかかるイベントが相関処理され、再度通知されないように定義しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/fa3aff1a-0a2b-6ed9-8c5b-1ea426c9a49b.png)

  同じイベントかどうかは **Group events** の設定で判定ます。今回は `env`, `owner_id`, `service` タグが同じ場合に同じイベントと判定されるようにしています。
　最後に通知先の判定ルールを **Select Destination** で設定します。プロジェクトとして指定している`high_sla_destination` はケース管理側で High SLA 用に設定したプロジェクトの一つです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/7d48dde0-11aa-5e3f-1954-a87604e5dd43.png)

### ケース管理を介してイベント通知を送り届ける

　最後に、相関処理されたイベントを受け取る[ケース管理](https://docs.datadoghq.com/ja/service_management/case_management/)の設定です。[プロジェクト](https://docs.datadoghq.com/ja/service_management/case_management/projects) `high_sla_destination` には [Team](https://docs.datadoghq.com/ja/account_management/teams/) `High SLA` をアサインしており、相関処理されたイベントを受け付けるとこの **Team** に対して通知を送ります。通知方法は **Team** で設定した手段に依存します。今回はEメールを選択しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/6a05a65b-b7a8-0082-79bd-e9444c81b8d0.png)

 実際にイベントを受け取るとケースが起票されます。今回の例では APM Monitor とイベント API の両方からイベントを受け取りますが、下の図のように1つのケースに相関処理されていることが分かります。このままケースを使って問題の解決まで管理することもできますし、右上のボタンからインシデントを起票することもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/63c32f37-eb34-d33e-44cc-19f72b1a7c9f.png)

 以下は相関処理されたパターンの一つを開いた画面です。発生と復旧の2つのアラートを繰り返し起こしたのですが、1つのパターンに集約されていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/2a72a04d-2b6e-a79f-acce-65bc56df26f6.png)

 ケースが自動起票された時点で、**Team** メンバーである私に以下のようなメールが届きました。この相関処理パターンにヒットするイベントがたくさんあっても、設定した時間内であれば1つのメールしか送信されることはありません。また、タイトルには**契約名**が、**Priority** にはパイプラインで変更した **P2** が表示されていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1018265/c3ba4353-d795-7613-6e45-da508278ac85.png)
 
## 最後に

　いかがでしたでしょうか。本稿では Datadog イベント管理のパイプラインとコリレーションルールを使って、アラート／イベントに欠けているコンテキストを追加し、繰り返しイベントを集約して、適切な宛先に通知できることをご紹介しました。冒頭で述べたようなアラート疲れや通知処理の難しさに課題がある場合は、有効な機能だと思います。
　Datadog にはイベント管理以外にも[インシデント管理](https://docs.datadoghq.com/ja/service_management/incident_management/)や[ワークフロー](https://docs.datadoghq.com/ja/service_management/workflows/)などアラート／イベントの管理や処理に活用できる機能がありますので、機会があれば記事にしてみたいと思います。