[Datadog]ログ監視における特定文言の監視抑止方法

## はじめに

こんにちは、なじむです。今回はDatadogの設定で、どうやるのが正解なんだろうと分からなかったので自分なりに考えた記事です。こんな方法で実装しているけど、周りはどう設定しているのか気になるので「こっちの方が良い方法！」等ありましたらコメントを頂けると非常に嬉しいです。
お題は「Datadogにおけるログ監視における特定文言の監視抑止方法」についてです。

## 一般的なログ監視抑止方法

ログ監視を実施していると、特定の文言を含むエラーは通知したくないという状況があります。Datadogで設定しようとすると以下のクエリになります。

```:QUERY
logs("filename:test.log ERROR -testA -testB").index("*").rollup("count").last("5m") > 1
```
※test.logに「ERRORを含む」かつ「testAは含まない」かつ「testBは含まない」という条件のログが出力されたらアラートを通知する
![20200525_151142.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/5eddbfab-b864-67dd-fd11-7741c23df9b6.jpeg)

1つ、2つであればこの設定でも特に問題ないかと思っていますが、条件が100個や複雑な条件になってくると面倒だなと感じています。それらを改善したいというのが次の方法です。

## Pipelineを用いたログ監視抑止方法

### Pipelineの構築

上述の設定を回避するために以下のようなパイプラインを作成します。
それぞれについて解説していきます。
![20200525_174132.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/1dacce89-81f1-423f-2e4a-172675da8395.jpeg)

#### Grok Parser

Grok Parserは検知したログをパースして、Datadogの属性にマッピングします。
今回は以下の様に作成しました。
![20200525_154933.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/bce8a82e-f6fa-6998-ed41-fb636fa1b0ba.jpeg)

```:Parsing_Rule
err_log %{_date} \[%{_severity}\] %{_message}
```

```:Helper_Rule
_date %{date("yyyy-MM-dd HH:mm:ss.SSS"):timestamp}
_severity %{notSpace:severity}
_message %{data:message}
```

#### Status Remapper

Grok ParserでパースしたSeverityを用いて、Datadog上のステータスに変換しています。
![20200525_155715.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/49952cd8-2c35-3035-3d7c-d809e786745f.jpeg)

#### Pipeline
Status Remapperでマッピングしたステータスを用いて、status:errorのログを対象にCategory Remapperの処理を実行していきます。

#### Category Remapper

今回の肝です。
status:errorのログに対して、特定の文言があった場合にmonitoring.suppressionという新しいカテゴリに値を入れていきます。
![20200525_174613.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/7a92f538-6a12-bea0-0ee3-861df6f212ea.jpeg)

今回は以下の様に設定しています。
Category Remapperでは上から順に見ていき、最初にマッチしたところでNAME(monitoring.suppressionの値)を設定していきます。

|NAME|MATCHING QUERY|
|:---|:---|
|true|testA|
|true|testB|
|false|*|

### 確認

パイプラインを設定した結果、どのような動作になるのか確認します。

#### ログ出力

①通常のエラーを出力します。これはtestA, testBにマッチしないため、monitaring.suppressionがfalseになっていることが確認できます。
![20200525_174753.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/5e0181ea-2d54-46ec-82f1-8f9793d8f174.jpeg)

②testAを含むエラーを出力します。これは最初のtestAにマッチするため、monitaring.suppressionがtrueになっていることが確認できます。
![20200525_174801.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/15cebddb-b4a8-e945-2014-9937ceb984d4.jpeg)

③testBを含むエラーを出力します。これは二番目のtestBにマッチするため、monitaring.suppressionがtrueになっていることが確認できます。
![20200525_174809.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/cce0dfb5-6629-ec17-de31-62bcac75346e.jpeg)


#### facetの設定

monitorの検索条件で設定できるよう、facetの設定を実施します。
先ほど出力したログのmonitoring.suppressionカテゴリをクリックして、「Create facet for @monitoring.suppression」をクリックします。
![20200525_175530.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/c03e70b9-96a8-76ed-6155-e8e6e23cb806.jpeg)

#### Monitorの設定

ようやく準備が全て完了したので、モニターを設定します。
今回は以下のクエリで設定します。上述の手順で実施したfacetをクエリの条件として設定し、falseのものだけ検知します。

```:QUERY
logs("filename:test.log @monitoring.suppression:false").index("*").rollup("count").last("5m") > 1
```

エラーをログに出力するとちゃんと検知できました！
![20200525_174842.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396510/ad31a765-cae9-42a1-eccd-f477ed1b8980.jpeg)


### 注意事項

Category Remapperは順番の並び替えができないため、条件を変更したい場合は一度削除して再度登録という手順が発生します。terraform等を用いて実装すれば特に気になる点ではありませんが、設定の際は注意が必要です。
※手動での設定変更は現実的ではありません。

## まとめ

今回はログ監視の特定文言の監視抑止を分かりやすく実施したいという観点で記載しました。
③status:errorのパイプラインをstatus:info, status:warnの場合でそれぞれ作成すれば、info/warnだけど検知したいメッセージを同一のmoinitorで検知することができます。
監視抑止の条件もpipelineを見ればパッと分かるので、見やすさという意味でも良くなるかなと思います。ただ、上述の通りterraformを使用しないと更新が大変なところが難点です。
この方法が良いのか全く自信がないので「こんな方法があるよ！」というのがありましたらコメント等頂けると嬉しいです！