【New Relic】 ログを操り、アラート通知を柔軟に制御しよう！ ～Workflowの秘密兵器を活用～

<details><summary>目次</summary>

1. [はじめに](#1-はじめに)
2. [目的/実現したいこと](#2-目的実現したいこと)
3. [前提条件](#3-前提条件)
   - [3.1 実装の流れ](#31-実装の流れ)
   - [3.2 サンプルログの確認](#32-サンプルログの確認)
   - [3.3 通知条件](#33-通知条件)
4. [手順](#4-手順)
   - [4.1 ログの正規表現設定](#41-ログの正規表現設定)
       - [4.1.1 正規表現の設定方法1](#411-正規表現の設定方法1)
       - [4.1.2 正規表現の設定方法2](#412-正規表現の設定方法2)
   - [4.2 監視設定](#42-監視設定)
       - [4.2.1 アラートコンディションの作成](#421-アラートコンディションの作成)
       - [4.2.2 アラートポリシーの作成](#422-アラートポリシーの作成)
   - [4.3 通知設定と確認](#43-通知設定と確認)
       - [4.3.1 ワークフローの作成](#431-ワークフローの作成)
       - [4.3.2 通知確認](#432-通知確認)
5. [おわりに](#5-おわりに)

<!--
6. [参考ページ](#6-参考ページ)
-->
</details>

# 1. はじめに
この記事は、以下アドベントカレンダーの15日目です。

[New Relic Advent Calendar 2024](https://qiita.com/advent-calendar/2024/newrelic)

## 2. 目的/実現したいこと
New Relic アラート通知の振り分け方法について
- 複数の正規表現を用いて、ログを整形し、指定の属性をトリガー条件に通知先を振り分けたい
- いろんな要素が複合しており、今後も活用できるよう要点毎にまとめておきたかった

## 3. 前提条件
### 3.1 実装の流れ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/83e1b688-565a-8726-aa79-bef6ce8b51b2.png)


<details><summary>詳細</summary>

#### 3.1.1 ログをNew Relicへ転送し属性付与し整形するまで
- 指定のファイルパスから出力されたログに任意の属性[attributes]を設定する
- 設定ファイルを対象のホストに配置もしくは、Parsingの設定をNew RelicのUI上で設定する

#### 3.1.2 属性付与されたログを元に、アラートコンディションを作成しアラートが検知できるまで
- アラートコンディションとポリシーを作成し、アラートが発砲されるようトリガー条件を設定する

#### 3.1.3 検知したアラートを指定の通知先に送信し、メールの本文に必要な情報が記載されていることを確認できるまで
- ワークフローを作成し、属性によって通知したい送信先を振り分ける設定をする

</details>

### 3.2 サンプルログの確認
 - 今回はJP1のサンプルログから、「JobType」と「MessageID」の属性を付与して振り分け先を検討していく
```:JP1サンプルログ
0002 20XX/12/09 19:01:25.123 jpqagt 00001AFC 000144C KAVU3614-I AJSROOT1:/JOBNETNAME/AAUNITNAME:@A111,80000001,ManagerHostName,un="JP1UserName",sc="C:\ExeFilePath\ExeFileName.exe",prm="Arg1 Arg2",pid=100
```

| Attribute Name | Value |
|:-|:-|
| ProcessID  | 00001AFC  |
| ThreadID  | 000144C  |
| MessageID  | KAVU3614-I  |
| JobName  | AJSROOT1:/JOBNETNAME/AAUNITNAME  |
| JobType  | AA  |
| unit  | UNIT ※AAorBBの時以外　|
| name  | NAME ※AAorBBの時のみ  |

:::note warn
`こちらはサンプルログであり、通常、フォーマットの出力が異なるはずなので、ログや環境ごとに適宜正規表現は変更してください`
:::

---------------------------------------

### 3.3 通知条件
通知条件は以下を想定
多くの部署やチームが所属するシステムで、各担当者ごとに通知先を振り分けすることを実現したい
|パターン#| 通知条件 |
|:-|:- |
|パターン①| 「JobType」がAAかBBのパターン|
|パターン②| 「JobType」がAAかBB以外のパターン|
|パターン③| 特定の「MessageID」で検知するパターン|

## 4. 手順
### 4.1 ログの正規表現設定
### 4.1.1 正規表現の設定方法1

- New Relic Infra Agentインストール済みのLinuxサーバ環境上で、/etc/newrelic-infra/logging.d/配下に以下3つのファイルを作成

|#| ファイル名 ※任意のファイル名 | 内容 |
|:-|:-|:-|
|1| ExternalForwarding.yml | 外部参照先のファイルのパスを指定するファイル[本来通常のlogging.ymlの役割を担う][^2]|
|2| fluentbit.conf | 設定ファイル|
|3| parsers.conf | 正規表現用ファイル|


```ExternalForwarding.yml
logs:
  - name: external-fluentbit-config-and-parsers-file
    fluentbit:
    # config_fileとparsers_fileは任意のファイルパスを指定
      config_file: /etc/newrelic-infra/logging.d/fluentbit.conf
      parsers_file: /etc/newrelic-infra/logging.d/parsers.conf
``` 

```fluent:parsers.conf
# 正規表現したいパターン数に応じて、[PARSER]セクションを追加可能
[PARSER]
    Name        JOBTYPE1
    Format      regex
    Regex       (?<ProcessID>[0-9A-F]+)\s(?<ThreadID>[0-9A-F]+)\s(?<MessageID>\w{4}\d{4}-\w)\s(?<JobName>[A-Z0-9].+/(?<JobType>(AA|BB))[A-Z0-9]{4}+(?<name>[A-Z]{4}))

[PARSER]
    Name        JOBTYPE2
    Format      regex
    Regex       (?<ProcessID>[0-9A-F]+)\s(?<ThreadID>[0-9A-F]+)\s(?<MessageID>\w{4}\d{4}-\w)\s(?<JobName>[A-Z0-9].+/(?<JobType>(?!AA|BB)[A-Z]{2})(?<unit>[A-Z]{4})[A-Z0-9]{4})

[PARSER]
    Name        JOBTYPE3
    Format      regex
    Regex       (?<MessageID>\w{4}\d{4}-\w)
``` 

```fluent:fluentbit.conf
[INPUT]
    Name                tail
# New Relicに転送したい任意のファイルパスを指定
    Path                /var/log/logFile.log
    Path_Key            filePath
    Key                 message
    Parser_Firstline    JOB_ERROR_PARSER

[FILTER]
    Name             parser
    Match            *
    Key_Name         message
# parsers.confの「Name」と一致するするように任意のNameを記載
    Parser           JOBTYPE1
    Parser           JOBTYPE2
    Parser           JOBTYPE3
    Reserve_Data     On
    Preserve_Key     On
``` 

 - `ファイル更新時には、必ず「newrelic-infra」のサービスを再起動すること`

---------------------------------------

### 4.1.2 正規表現の設定方法2

 - New RelicのGUI上のParsingの画面で操作して設定

設定完了後のイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/0ede93b6-2a15-4275-f52a-d78d3ef2ec54.png)

[JOBTYPE1]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/38c9005a-549d-6d4e-4094-ce0586afebde.png)

---------------------------------------
[JOBTYPE2]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/15a9a74c-64a8-9924-b369-6f58c787bb39.png)

---------------------------------------
[JOBTYPE3]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/d28a1d10-a129-d522-192c-fd71b586e234.png)

---------------------------------------

#### 正規表現の属性付与結果確認
New Relic上で想定通りのログが転送されたことを確認！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/dd129475-e4f6-d026-412e-e23b4efff1eb.png)

#### どちらの方法が良いか？
 - `セキュリティ対策の観点から、多くの組織では特定のサーバーへのアクセスに制限を設けており、このような環境下では、個々のサーバーに直接ログインすることが困難な場合があります
 そのため、New RelicのUI上で一元管理する方が、サーバー管理の煩雑さを軽減し、同時にセキュリティレベルを維持・向上させ、IT運用の効率化とリスク管理の強化の両立を目指すことができそうです。`

### 4.2 監視設定
### 4.2.1 アラートコンディションの作成
**アラートコンディション名 : JP1_MessageID_AlertCondition　※例**
```SQL:Query
SELECT count(*) FROM Log 
WHERE filePath = '/var/log/logFile.log' AND `hostname` = 'xxxxx' //任意のhostnameを指定
AND MessageID IN ( 'KAVS0248-I','KAVS0265-E','KAVS0269-W','KAVS0275-I','KAVU4310-I','KAVU3614-I') //任意のMessageIDを指定
FACET MessageID, JobType , messageId
```
 - `通知先のメールで「Tags」に表示される情報は、このNRQLのFACETで設定した内容が反映される。また、念のため「messageId」も追加することで、ログを一意のものとします。`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/3c64c3e8-1c1b-c348-3225-3e7c9f7bdb27.png)

---------------------------------------

**自動クローズ設定**
下記2パターンは、一定期間が過ぎると自動でincidentがクローズする設定です。
基本的にデフォルトで3日間incidentが発行されたままの状態になってしまうので、下記の2パターンのどちらかを設定して回避します。

①閾値設定
| 設定項目 | 値 |
|:-|:-|
|Consider the signal lost after   | 5 minitues  ※例|
| On signal loss:  |  Close all current open incidents |

②Add details
| 設定項目 | 値 |
|:-|:-|
|Close open incidents after   | 5 minitues ※例 |
---------------------------------------
### 4.2.2 アラートポリシーの作成
**アラートポリシー名 : JP1_MessageID_Policy　※例**
「Issue creation preference」の設定で、「One issue per condition and signal」を選択
⇒　**issue と incident が 1:1 の関係**になり、**「messageId」毎**に通知が行われる

---------------------------------------

:::note info 
#### FACET messageについて[^3]
> - イベントタイプ "Log" をクエリし、FACET 属性のリストに "message" 属性を含む NRQL アラート条件を作成する機能を無効にする予定です。
>  - 「FROM Log... FACET message」構文を含み、かつ、「Sum of Query Results」しきい値タイプを使用するNRQLアラート条件を無効にする予定です。

メールなど通知を確認した際に、messageの全文が表示されていないと、New RelicのUIを確認する必要が生じ、messageの内容把握までに時間を要する。
そこで、初動対応のスピード向上のため、「FACET message」を用いて、メールの本文にmessageの内容を表示することを考えたが、現在投稿日の時点では無効となっている。
:::

なので**代替案を用いて設定**していく[^参考]
## 4.3 通知設定と確認
### 4.3.1 ワークフローの作成
**作成するワークフローの数** = **振り分けたい通知先の数**としています

|#| ワークフロー名 ※例 | 通知条件 |通知先(例)※任意のアドレスを指定|
|:-|:-|:-|:-|
|1| AABB_JP1JobTypeTriage_Workflow | 「JobType」がAAかBBのパターン|aaa@beex-inc.com|
|2| Non-AABB_JP1JobTypeTriage_Workflow | 「JobType」がAAかBB以外のパターン|bbb@beex-inc.com|
|3| JP1MessageTriage_Workflow | 特定の「MessageID」のみで検知するパターン|ccc@beex-inc.com|
---------------------------------------
### 「Filter data」で設定
#### 「Advanced」で下記の通り、各ワークフロー毎に設定
```:AABB_JP1JobTypeTriage_Workflow
「labels.pollicyIds」 = 任意のポリシーID 'AND'
「accumulations.tag.JobType」 contains [AA] OR [BB]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/6e919b86-0e8e-f02f-dacf-313bb9dd1101.png)

```:Non-AABB_JP1JobTypeTriage_Workflow
「labels.pollicyIds」 = 任意のポリシーID 'AND'
「accumulations.tag.JobType」 does not exactly match [AA] 'AND'
「accumulations.tag.JobType」 does not exactly match [BB] 'AND'
「accumulations.tag.JobType」 does not exactly match [none]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/d21b76bd-cbdb-b58d-335b-97f9f276acf6.png)

```:JP1MessageTriage_Workflow
「labels.pollicyIds」 = 任意のポリシーID 'AND'
「accumulations.tag.MessageID」 [KAVU4310-I] OR [KAVU3610-I]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/7851c550-0f2e-736a-6227-a44a14b40821.png)

 - `ワークフローの「Advanced」で設定する「tag」の情報を設定するには、一度「FACET」で指定した内容がNew Relic上に転送され、データとして認識している必要があります`

#### 「Additional settings」で「Enrich data」有効化
```:Enrich data :  Name your query
Log lines that match a pattern
``` 
```:Enrich data : Build your query in NRQL 
SELECT message FROM Log WHERE messageId = {{accumulations.tag.messageId}}
``` 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/f9d8548d-ad7f-c4aa-9a4b-125ef359eece.png)

 - `「messageId」を変数に格納することで、一意のメッセージを特定し、messageのデータを取得する`
 - `「Enrich data」はPro以上のプランでないと設定できない`
---------------------------------------

### 「Notify」で設定

```:Custom Details (optional)
    messageId: 
    {{#if accumulations.tag.messageId}}
      {{accumulations.tag.messageId}}
    {{else}}
      "N/A"
    {{/if}}

    Log Message:
    {{#if [Log lines that match a pattern].result}}
      {{[Log lines that match a pattern].result}}
    {{else}}
      "No log message found"
    {{/if}}
``` 
 - `「Enrich data」のNRQLで取得した「message」をメールの本文に記載されるように設定`
 - `「.result」で出力結果をコンパクトに`

### 4.3.2 通知確認
通知先パターンごとにメールを受信できました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/693dddf7-45af-7e46-6f39-de6324618d6b.png)

また、メール本文の「Custom details」に想定の「message」が表示されていることを確認できました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3941149/3ba89a8b-6fb8-bd98-acc9-4acc3d27a464.png)

 
:::note info 
**ワークフローのmessageテキスト展開**
messageの内容をメール本文で表示させるためには、New Relicの内部的にワークフローのmessageテキスト展開を有効化する必要があります。
サポートより問い合わせ行い、有効化を実施してください。
:::
# 5. おわりに
 - 今回はJP1のログを元に正規表現を使ってログ整形しましたが、正規表現が扱えるようになると、監視条件や通知先選定等、その他のログに対してもできることの幅が広がると実感した
 - 正規表現は本文中にも記載したが、「Parsing」で設定する方が圧倒的に管理も検証・実装も楽
 - 私が理解している範囲ではありますが、今回記事自体初めて投稿させていただきました
 - 所感では情報収集から実装まで意外と情報が少なく苦戦したので、本投稿がどこかで役に立つことを願っております

[^参考]:[New Relic Workflowのエンリッチメントでログを取得する](https://zenn.dev/iret/articles/7d83f42b0ff042)

[^2]:[New Relic Infrastructureのログ転送でFluent Bitの機能をフル活用する](https://newrelic.com/jp/blog/how-to-relic/fluent-bit-tutorial-with-infra-agent)

[^3]:[FROM Log …FACET message」を使用したNRQL条件はブロックされ、無効になります](https://newrelic.com/jp/blog/how-to-relic/critical-notice-nrql-conditions-using-from-log-facet-message-will-be-blocked-and-disabled)


<!--
# 6. 参考ページ
[New Relic Infrastructureのログ転送でFluent Bitの機能をフル活用する](https://newrelic.com/jp/blog/how-to-relic/fluent-bit-tutorial-with-infra-agent)

https://newrelic.com/jp/blog/best-practices/notification-with-log-message
https://x-tech5.co.jp/2023/11/07/1113/
https://zenn.dev/iret/articles/7d83f42b0ff042

[New Relic Infrastructureのログ転送でFluent Bitの機能をフル活用する](https://newrelic.com/jp/blog/how-to-relic/fluent-bit-tutorial-with-infra-agent)

[Parsers Configuration File](https://docs.fluentbit.io/manual/pipeline/parsers/configuring-parser)

-->