【Splunk】１サーチで複数の時間範囲のサーチ結果を比較する

[Splunk](https://www.splunk.com/ja_jp)は様々なデータに対応した統合ログプラットフォームです。
SPLというサーチ言語を利用してログから自分の見たい情報を抽出、Commnadsを活要して集計処理やデータの加工など様々なことが可能です。

Splunkは以下の図のようにlinechartをはじめpiechartやareachartなど様々な視覚エフェクトが提供されており、サーチ結果に対する可視化にも優れています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552698/525ec31c-cf7f-c1eb-4278-a212d447733e.png)

本記事ではSplunkそのものや様々なCommandsの深堀はしないためSplunkをより詳しく知りたい方は[チートシート](splunk.com/pdfs/solution-guides/splunk-quick-reference-guide-jp.pdf)や公式ドキュメントを参照いただければと思います。[日本語マニュアル](https://docs.splunk.com/Documentation/Splunk/8.2.3/Translated/Japanesemanuals)も充実しています。

#やりたいこと

**１サーチで複数の時間範囲のサーチ結果を比較したい！**


例えば以下のSPLではhost名hogeの1分毎のデータ量を得ることができます。

```
index=main sourcetype=ms:iis:auto host=hoge | timechart span=1m
```

上記のSPLでサーチした場合取得できる結果はあくまでGUIから指定している時間範囲の結果のみです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552698/7fc91bcd-c54f-d29f-cfef-66f1d62ce98e.png)


複数の時間範囲、例えば①2021/12/01 AM09:00~AM09:15と②2021/12/02 AM09:00~AM09:15をサーチし視覚エフェクトを使ってビジュアル化して比較したいと思うシーンがありました。

- 素直に2回サーチ
- ダッシュボード機能を活用して2つの検索結果を横に並べて表示する

上記のような方法でも比較はできるのですが、グラフを重ねて（できるだけ綺麗に）表示する方法がないかと模索しておりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552698/fd498a3c-78f8-68fd-d879-ffee535b4dc7.png)


調べたら簡単にできたので実現方法について記載したいと思います。


#実現方法
[Splunkのブログ](https://www.splunk.com/en_us/blog/tips-and-tricks/compare-two-time-ranges-in-one-report.html)に記載されていた方法を参考に以下のようなサーチ文にすることで欲しいデータを取得することができました。

```
index=main sourcetype=ms:iis:auto host=hoge
| eval ReportKey="期間①"
| append [search index=main sourcetype=ms:iis:auto host=hoge earliest=1638403200 latest=1638404100
| eval ReportKey="期間②"
| eval _time=_time-86400]
| timechart span=1m count by ReportKey
```

##何をしているか
###ベースサーチ

```
index=main sourcetype=ms:iis:auto host=hoge
```

GUIで指定を行なった時間範囲内からマッチするイベントのみを抽出しています。

###eval

```
| eval ReportKey="期間①"
```

1行目の検索結果をパイプで繋いで[eval](https://docs.splunk.com/Documentation/Splunk/8.2.3/SearchReference/Eval)コマンドを利用しています。
evalコマンドは計算などに利用できるコマンドで、計算結果を元に新規のFieldとValueを作ることができます。
今回の場合はSearchTermで抽出したイベント全てにReportKeyというFieldを追加し、Valueとして`期間①`を入れています。

ここまでの処理結果を[table](https://docs.splunk.com/Documentation/Splunk/8.2.3/SearchReference/Table)コマンドで見てみます。

```
index=main sourcetype=ms:iis:auto host=hoge
| eval ReportKey="期間①"
| table _time ReportKey _raw 
```

tableコマンドは引数で指定したField名のみのテーブルを応答してくれるコマンドです。
今回引数としてfield: `_time`と作成したfield: `ReportKey`、さらにfield: `_raw`を指定しています。`_raw`はデータ取り込み時に内部的に作成されるfieldで一言で言えば各イベントをKeyValueの形に分解する前の生データが格納されています（パフォーマンス低下の恐れがあるため_rawは可能な限り避けた方が良いです）、_timeも内部的に作成されるfieldで_raw内にタイムスタンプがあればその値が入ります。

サーチ結果では以下のように抽出したイベントにfield: `ReportKey`が作成され、Valueに`期間①`が入っていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552698/5bba69de-68d3-39fd-87ac-e6ecc6716b76.png)

###appendとsub search

```
| append [search index=main sourcetype=ms:iis:auto host=hoge earliest=1638403200 latest=1638404100
| eval ReportKey="期間②"
| eval _time=_time-86400]
```

[append](https://docs.splunk.com/Documentation/Splunk/8.2.3/SearchReference/Append)コマンドを利用し行を追加して
追加する行に入るデータを[sub search](https://docs.splunk.com/Documentation/SplunkCloud/latest/SearchTutorial/Useasubsearch)で抽出します。`[search ]`で囲われた範囲がsub searchとなります。

####sub search内でやっていること

①sub search内のベースサーチ内で明示的にfield: `earliest`とfield: `latest`を指定してsub searchの抽出対象とする期間を指定しています（今回の例では2021/12/2 09:00~2021/12/2 09:15）。
②抽出結果にさらにevalでfield: `ReportKey`を作成し`期間②`という値を入れています。
③さらにevalコマンドを利用しsub search結果のfield: `_time`の全ての値を-86400（秒）した値に書き換えます。86400秒は1日（24時間）なのでこのサーチでは12/2のデータを1日前の12/1として扱う状態にしました。

###timechart

```
| timechart span=1m count by ReportKey
```
sub searchとevalを使って同じ時間軸のデータとすることができたので最後にtimechartコマンドで比較します。by句で集計する対象をReportKeyの値とすることで以下のような可視化ができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552698/4a8912a5-cb1c-d806-7138-1c7b6b38e25c.png)

## 最後に

異なる2つの時間範囲を1つのサーチで抽出し、視覚エフェクトを活用し分かりやすく比較する方法を記載しました。
今後もSplunkの小技等を見つけたら投稿していきたいと思います。