Splunk: timechartコマンドの間隔を日曜始まりまたは月曜始まりの1週間にする最も簡単な方法

しばしば必要となるのでメモ。

###### 実施環境： Splunk Free 8.2.2

###### やりたいこと

 timechart コマンドは、 span で集計間隔を様々に指定でき、1週間毎のデータを集計したい場合は span=1w を指定します。

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
```

![スクリーンショット 2021-11-21 20.54.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/c92a89cf-bcde-de05-979b-12eea518feca.png "元データ")

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| timechart span=1w count
```

![スクリーンショット 2021-11-21 20.55.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/32e19241-7fbc-1f56-0fef-8ca3d163b024.png "timechart")

ただ、ここで困ったことが1つ。
上記の例を見るとわかりますが、 span=1w で指定した場合の1週間の起点は、検索対象の中で最も古い日付、上記の例であれば2021/11/11(木)となります。
データを分析するには、これでは少々使いにくいです。
できれば、日曜始まりや月曜始まりで固定したいところですが、どのようにすればよいでしょうか。

###### 検索すると方法は出てくるが

「splunk timechart Sunday」等で検索すると、真っ先に出てくるのは eval コマンドの strftime 関数を使用する方法です。
 strftime 関数で時刻の形式に「%w」を指定すると、日曜日なら0、土曜日なら1、...月曜日なら6という数値が取得できます。

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| eval WEEK_CNT = tonumber(strftime(_time, "%w"))
```

![スクリーンショット 2021-11-21 20.56.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/4474a9c5-22a7-9d68-4f04-283e75dd42d3.png "strftime")

この数値を relative_time 関数を使用して元の日付から引くことで、日付を日曜始まりに揃えることができます。

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| eval WEEK_CNT = tonumber(strftime(_time, "%w"))
| eval _time = relative_time(_time, "-" + tostring(WEEK_CNT) + "d")
```

![スクリーンショット 2021-11-21 20.57.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/7f5c4cb5-0335-f243-5243-fb0e248fe19d.png "relative_time")

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| eval WEEK_CNT = tonumber(strftime(_time, "%w"))
| eval _time = relative_time(_time, "-" + tostring(WEEK_CNT) + "d")
| timechart span=1w count
```

![スクリーンショット 2021-11-21 20.58.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/257060bb-b218-f705-76e1-98ac9b26d062.png "日曜始まり1")

月曜始まりにするには、 strftime で取得した数値に6を足して7で割った余りを取得すればよいです。

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| eval WEEK_CNT = (tonumber(strftime(_time, "%w")) + 6) % 7
```

![スクリーンショット 2021-11-21 21.01.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/595d892d-5aaa-ab1b-f4c2-f2f24cdaf983.png "strftime_plus")

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| eval WEEK_CNT = (tonumber(strftime(_time, "%w")) + 6) % 7
| eval _time = relative_time(_time, "-" + tostring(WEEK_CNT) + "d")
```

![スクリーンショット 2021-11-21 21.01.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/af0bd1df-1c82-1dcf-7ccf-da0ebaf4eaaa.png "relative_time_plus")

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| eval WEEK_CNT = (tonumber(strftime(_time, "%w")) + 6) % 7
| eval _time = relative_time(_time, "-" + tostring(WEEK_CNT) + "d")
| timechart span=1w count
```

![スクリーンショット 2021-11-21 21.01.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/2ccf8406-2ad8-c5ad-8800-eb0868b4c8c6.png "月曜始まり1")

###### もう少し調べてみる

上記の方法で日曜始まりと月曜始まりは実現できましたが、やはり少々煩雑です。
もっと単純にできないのでしょうか。
もう少し調査してみると、以下のように「@w」という指定をすれば strftime 関数は不要となることがわかります。

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| eval _time = relative_time(_time, "@w")
```

![スクリーンショット 2021-11-21 21.02.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/18e60ef4-584e-9948-eee7-68084ba29a72.png "@w")

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| eval _time = relative_time(_time, "@w")
| timechart span=1w count
```

![スクリーンショット 2021-11-21 21.02.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/895943aa-d311-efd2-2f9d-2ef9b9e9e851.png "日曜始まり2")

月曜始まりにする場合は、「@w」の後ろに「1」を付けます。

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| eval _time = relative_time(_time, "@w1")
```

![スクリーンショット 2021-11-21 21.02.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/79250fd2-e49f-b968-4976-090dc7789179.png "@w1")

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| eval _time = relative_time(_time, "@w1")
| timechart span=1w count
```

![スクリーンショット 2021-11-21 21.03.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/848d6659-443e-78ba-9970-cfee3f38baf2.png "月曜始まり2")

非常にすっきりしましたが、実はもっとシンプルに記述できます。

###### 最も簡単な方法

上記で使用している「@w」という記載方法は、 timechart コマンドの span オプションでも使用できます。
結局、他にコマンドを使用せずとも、 timechart コマンドの範囲内で日曜始まり、月曜始まりは実現できるのです。

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| timechart span=1w@w count
```

![スクリーンショット 2021-11-21 21.03.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/ada7e6ed-7287-ae03-d649-96deab332501.png "日曜始まり3")

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval _time = _time - CNT * 60 * 60 * 24
| timechart span=1w@w1 count
```

![スクリーンショット 2021-11-21 21.04.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/6fcdbb3b-b54d-31cc-7b4a-cb848a76b252.png "月曜始まり3")

これが一番簡単だと思います。

###### ちなみに

上記の「@w」は、 relative_time 関数や timechart コマンドだけでなく、その他の場面でも使用できます。
例えば、以下では検索時のタイムピッカーで使用しています。

![スクリーンショット 2021-11-21 21.05.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/15858112-080d-e27a-e2ee-f7aebe23131d.png "タイムピッカー")

意外と使う機会があるので、覚えておくと便利です。