Jenkins Log Parser Pluginを触ってみる話

この記事は[Akatsuki Advent Calendar](https://adventar.org/calendars/7459)の23日目の記事です。
前日は柴原さんの[Fast DDLを使った高速なmigrationを実施してみた話](https://hackerslab.aktsk.jp/2022/12/22/180432)でした。
メンテナンス時間の削減はユーザーからしても嬉しいものですので、本番環境で使用しても問題ないようにできれば・・・！と思います。

## はじめに
最近業務でJenkinsを触れる機会が多く、そこでLog Parser Pluginを導入する機会がありましたので備忘録として記事にしました。

## Log Parser Pluginとは？

コンソールログを解析して、対象となった行をいくつかのパターンで強調してくれるプラグインになります。
例えばUnityのビルドログ等の行が多いものからエラーログを探すのが容易になります。

**※ 使用するには別途ルールを記述したファイルが必要です**
以降ルールファイルと呼びます。
ルールファイルはパイプラインスクリプトの管理リポジトリ内に入れておくと手間がないかと。

### 結果例
エラー対象の行は赤、警告対象の行は黄色で表示されます。
左メニューは対象の行一覧、右メニューは実際のログです。
左メニューの行を選択することで、実際のログまで移動ができます。
![スクリーンショット 2022-12-23 13.42.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126834/d9a1dcd6-37fe-1e4d-51f5-604ee5913a6b.png)

### Pipelineのコード例

``` groovy
logParser(failBuildOnError: true, projectRulePath: "parsingRule.txt", useProjectRule: true)
```
**※ このコード以降で出力されたコンソールログは対象になりません**

引数について
- parsingRulesPath(string): 使用するルールファイルのファイルパス（コントローラー上のファイルを参照します）
- projectRulePath(string): ワークスペースから相対的なルールファイルへのパス
- useProjectRule(boolean): trueの場合は`projectRulePath`のファイルを使用します。`parsingRulesPath`のファイルよりも優先して使用します

オプション引数
- failBuildOnError(boolean): trueの場合はエラー対象の行を検知した時、実行したジョブの結果は失敗（failure）となります
- unstableOnWarning(boolean): trueの場合は警告対象の行を検知した時、実行したジョブの結果は不安定（unstable）となります

### ルールファイルの記述について
#### サンプルコード
```
# コメント文
ok /OK:/
error /Error:/
warning /Warning:/
info /information:/
start /BUILD/
```
**/で囲った部分**が検索対象となります。

#### 各フォーマットについて

- ok: ヒットした行は強調しない
- error: ヒットした行はエラーとして強調する
- warning: ヒットした行は警告として強調する
- info: ヒットした行は強調する
- start: ヒットした行はinfoに含めて、以降の行は同じグループのログにする

#### start構文について
##### 例
以下のルールを入れる
```
start /BUILD/
```

以下のログを出力
```
UNITY_BUILD
warning対象のログ
UNITY_ASSET_BUILD
warning対象のログ
```
##### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126834/2f9e41e1-b015-48ae-b83d-3ca5d07054f9.png)

このようにログをグループ分けできます。
どの処理で発生したものかより明確にできるのでおすすめです。

#### ルールを適用する優先度
ルールの優先度は先に書いたものほど高いです。
もしルールが被った場合は、優先度の高いものが適用されます。

##### 例
```
ok /ok:/
error /Error/
```
以上の設定の場合、下のログは**ok扱い**となります。
`ok: Error: could not find something`


#### 特殊な書式指定

```
error /(?i)^error /
```
`error`という単語の大文字小文字区別なし かつ 行の先頭から始まる場合ヒットする

```
warning /[Ww]arning/
```
wは大文字小文字区別なしで`arning`を含む場合ヒットする


## エージェントにあるルールファイルを使う場合の注意点
引数次第で動作しないので注意が必要です。ここで少しハマりました。

### NGコード
``` groovy
pipeline {
    agent {
        label "test1"
    }

    stages {
        stage("test") {
            steps {
                script {
                    echo """
OK: ok
INFO: info
                    """   
                    logParser(failBuildOnError: true, parsingRulesPath: "${env.WORKSPACE}/parsingRule.txt", useProjectRule: false)
                }
            }
        }
    }
}
```

引数の`parsingRulesPath`は**コントローラー上のファイルを参照する**ため、指定パスにルールファイルがなければエラーとなりますしエージェント上（今回はtest1）のファイルは使用できません。

### 解決策
#### projectRulePathでパスを指定する

もしエージェント上のファイルを使う場合は`projectRulePath`引数でワークスペースからの相対パスを指定します。
`useProjectRule`をtrueにするのも忘れず。

``` groovy
pipeline {
    agent {
        label "test1"
    }

    stages {
        stage("test") {
            steps {
                script {
                    echo """
OK: ok
INFO: info
                    """   
                    //projectRulePathとuseProjectRuleを使用する
                    logParser(failBuildOnError: true, projectRulePath: "parsingRule.txt", useProjectRule: true)
                }
            }
        }
    }
}
```

## おわりに

今回紹介したプラグインは膨大な量のログから欲しい情報を見るにはとても有効なプラグインです。
Jenkinsは中々とっつきづらい部分もありますが、この記事が少しでも参考になれば幸いです。

今回使用したプラグインのURL
- https://plugins.jenkins.io/log-parser/
- https://www.jenkins.io/doc/pipeline/steps/log-parser/