Splunkサブサーチで検索期間を変化させる

##概要
サブサーチの結果を元に、時間を絞って検索したい時がままある。
サブサーチ結果を`return`で返す時、書き換えて`earliest`と`latest`を追記して検索させる。
（2019/12/26追記）あとは`format`を使用して`earliest`と`latest`を返してやる方法もある。
（2020/01/22追記）`format`を使用して文字列から`earliest`と`latest`をつくる方法もある。
（2020/05/06追記）`format`を使用したあと、`earliest`と`latest`をくっつける方法もある。
（2020/05/18追記）単純にサブサーチのイベントの時間の前後１０分間を検索を追記
(2021/01/17追記)サブサーチで値だけ戻してやるを追記

##構文
```Splunk:SPL
index=_internal
[search index=_internal name=management
| eval time_args="earliest=@m latest=-10s"
| return $time_args thread]
```

##解説
1. 検索自体は適当
2. _time_args_に時間指定を入力、今回は1分前から10秒前までにしてみた。
3. `return`で時間および検索フィールドを指定
4. `return`の結果は_search_フィールドに入っている
5. メインサーチに戻してあげる

######  searchの中身
| search |
|:--|
| earliest=@m latest=-10s thread="webui" |

##結果
![qiita.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130729/96d83884-9198-bbb2-e984-4825bba39f40.jpeg)



過去60分で検索したが、サブサーチの結果を受け、サーチ期間が狭まっている。
> Your timerange was substituted based on your search string

とジョブ結果にもでている。

##応用
今回は時間指定を固定値で実施したけど、

```Splunk:SPL
eval time_args="earliest=".<<検索時間フィールド>>." "."latest=".<<検索時間フィールド>>
```

と動的に作成してもいいと思う。[earliestとlatest](https://docs.splunk.com/Documentation/Splunk/7.3.0/SearchReference/SearchTimeModifiers)を参考に。
_-1m_とかepoch時間でも渡せるので、
_[06/Jun/2019:09:00:00 +0900]_
とかを`strptime`の_"%d/%b/%Y:%H:%M:%S"_でepoch時間に直して渡してあげてみるとか
`relative_time`で1分前の時間を作ってみるとか

:sweat: ログが入っていないので、具体例を作れない・・・

##formatを使用
[format@splunk>docs](https://docs.splunk.com/Documentation/Splunk/latest/SearchReference/format)
例文

```
format [mvsep="<mv separator>"] [maxresults=<int>] ["<row prefix>" "<column prefix>" "<column separator>" "<column end>" "<row separator>" "<row end>"]
```
###単純にサブサーチのイベントの時間の前後１０分間を検索

```sql:subsearch_time_to_main.spl
index=_internal sourcetype=splunkd_ui_access 
    [ search index=_audit "_internal" 
    | eval earliest=relative_time(_time,"-5min@min"), latest=relative_time(_time,"+5min@min") 
    | streamstats count 
    | where count=1 OR count=100
    | fields earliest latest 
    | format]
```
単純に時間だけ渡したい場合は、`fields`と`format`で十分


###過去の検索期間の上位２つを１０分前〜５分前の間で検索

```java:SPL
index=_internal    [search index=_internal name=management 
| top 2 thread showcount=f showperc=f
| mvcombine thread
| eval earliest=relative_time(now(),"-10m@m") ,latest=relative_time(now(),"-5m@m")
| format "(" "" "" "" "" ")"]
```
####解説
今回は

|row prefix| column prefix|column separator|column end|row separator|row end|(参考)mvsep|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|(|||||)|OR|

- _row separator_は

|thread|
|:-:|
| archivereader | 
| batchreader0 |
| callbackrunnerthread |

の各項を何で繋いでやるか。defaultだと`OR`なので
`thread="archivereader" OR thread="batchreader0" OR thread="callbackrunnerthread"`となっているはず。

- _column separator_は２つ以上のフィールドをメインサーチに渡す場合、各フィールドを何で繋いでやるかということ。`A NOT B`とか書くとき使う。

- _column_prefix_はフィールドの頭につける文字列。これまた`NOT`とかで使えると思う

`format`はmultivalueフィールドと通常のフィールドの接続子を別に設定できるので、メインサーチに戻してやるフィールドはマルチバリューにしてあげると今回のように接続子に悩まなくてよくなる。

##サブサーチで値だけ戻してやる

```java:値だけ戻す
index=_internal splunkd component=*| head 20
| eval earliest=_time, latest=_time+60
| table component earliest latest
| rename component as search
| format "(" "" "" "" ") OR (" ")"
```

一つのフィールドの値と検索期間を戻す時は、`table`でフィールドを限定して、`rename`
で_search_にしてあげて、`format`してあげるといい感じになる。

`rename`しないと、`field名=値`でメインサーチに戻る。

##formatの後に検索期間をくっつける
```java:時間後付け
index=_internal [ search index=_internal
| stats count by sourcetype
| dedup sourcetype
| fields - count
| format
| addinfo
| eval earliest=relative_time(info_min_time,"+5h"), latest=relative_time(info_max_time,"-4h")
| eval search=search." ( earliest=".earliest." latest=".latest.")"]
```
複数の列をメインサーチに戻してやる場合、`format`の後に検索期間をくっつける方が楽なことに気がついた。
_epoch time_を作ってあげれば問題がないと思う。
####ダッシュボードむけ

```java:SPL
  index=hoge  [| makeresults 
 | eval earliest="1/22/2020:08:00:00"
 | eval earliest=strptime(earliest,"%m/%d/%Y:%T")
 | eval latest=relative_time(earliest,"+10m")
 | format "(" "" "" "" "" ")"]
```
`earliest`のところに文字列を入れてあげると、そこから１０分間のログを検索するクエリー。
どの道`strptime`で変換してあげるので条件は適宜。
ダッシュボードだと`<condition>`とかで`eval`が使えるので、実際はクエリーにする必要はないかもしれないけど、クエリーにしておくと、パネルで修正ができるという利点がある。
`<panel depends="$hide$">`にしておけば、使用する際は見えないし。

#横断検索

```java:SPL
index=hoge [search index=hoge sourcetype=hogehoge BAD
| eval search="earliest=".relative_time(_time,"-5s")." latest=".relative_time(_time,"+5s")
| table search
| head 1]
```
例はないけど、検索期間ひろめでなんか悪いこと見つよう。
見つけたときはその付近のログを横断的にみましょうね〜というクエリ
複数のログが出そうなときは
`eventstats earliest(_time) as earliest latest(_time) as latest`とかでつくった時間をもとに検索するといいと思います。

#まとめ
サブサーチは結局_search_フィールドの値をメインサーチに戻してやっている。
`format`や`return`を使えば値は確認できるので、うまく行かないなってときはサブサーチ自体の値を確認すればなんとかできると思います。

検索期間の変化は応用ですね。`earliest=`や`latest=`の接続に`AND`や`OR`を使えないので。:smiley_cat: