Splunkのトレリス表示を検証する

#つくってみた
```java:piechart.spl
|makeresults count=3
| streamstats count as x
| eval y=mvrange(1,4)
| chart list(y) as y by x
| mvexpand y
| streamstats count(x) as z
```

|x	|y	|z
|:-:|:-:|:-:|
|1	|1	|1
|1	|2	|2
|1	|3	|3
|2	|1	|4
|2	|2	|5
|2	|3	|6
|3	|1	|7
|3	|2	|8
|3	|3	|9

![ans.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130729/7cfb669d-c747-b4cf-6144-958ab75f9086.png)
トレリス表示の不思議なところが、`chart`を使用しないで同じ表を作ってもダメなところ。
また基準の`x`は`chart`の前で整形しなければならない。
`eval`で`chart`のあとでいろいろやってしまうとトレリス表示ができなくなる。

#もっと細かく
```java:こまかくしてみました.spl
|makeresults count=3
| eval x=mvrange(1,4)
| eval y=mvrange(1,10)
| chart list(y) as y by x
| mvexpand y
| eval  z=1
```
`count=3` * `mvrang(1,4)=3` * `mvrange(1,10)=9`　の行ができる。

#こんな感じ
```java:toshikawa.spl
|makeresults 
| eval x=split("朝#昼#夜","#")
| eval y=split("眠い,朝ごはん,仕事,夜ご飯,Splunk,おやすみ",",")
| stats values(y) as y by x
| eval y=case(x="夜",mvindex(y,0,3),x="昼","仕事",x="朝",mvindex(y,4,-1))
| mvexpand y
| streamstats count as z
| eval z = case(z=1,20,z=2,60,z=3,10,z=4,10,z=5,100,z=6,20,z=7,80)
```
![ans.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130729/14519b79-470e-4674-20a8-b68205e03fcf.png)
#Line Chart
```sql:linechart.spl
index=_internal 
| timechart span=1m count by sourcetype
| addcoltotals labelfield=_time label=total
| transpose 0 header_field=_time
| where total >100
| transpose 0 column_name=_time header_field=column
| where _time!="total"
```
![qiita1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130729/71b48492-8210-4320-8e7a-ae7edc305e54.png)
これでもトレリス表示できた。
クエリーは合計が１００以下の場合表示したくないな〜と思って
`addcoltotals` ⇨　縦横変換 ⇨　`where` ⇨　縦横変換 してみた。

なお

```sql:eventstats_linechart.spl
index=_internal 
| eventstats count by sourcetype 
| where count > 100 
| timechart span=1m count by sourcetype
```
との比較は

|command|search time|
|:-:|:-:|
|transpose| 0.443 seconds
|eventstats|  0.912 seconds

`addcoltotals`の検索コストが全然かかっていないのに、`eventstats`の検索コストが高いのがこの結果に。
####トレリスの後に計算したい時
`transpose`を使用して一旦縦横変換して計算してから戻してやると_Trellis_表記で表示が可能みたいです。

#timechartで２つ以上のフィールドでトレリス
```sql:double_fields_trellis.spl
index=_internal sourcetype=splunkd
 | bin _time span=5min
 | stats count by _time component log_level
 | eval {log_level}=count
 | fields - log_level count
```

_time|	component|	ERROR|	INFO|	WARN|
|:-:|:-:|:-:|:-:|:-:|
|2020/05/13 14:00:00|	ExecProcessor|	| 	1|	 
|2020/05/13 14:00:00|	LMStackMgr|	| 	14	 
|2020/05/13 14:00:00|	Metrics	 |	|1232|	...

[心の師匠](https://answers.splunk.com/answers/823451/timechart-count-by-ip-by-fw-name-over-time-with-tr.html)のクエリー

`stats`で集計しておいて、複数表示したいフィールド(この場合は`log_lebel`)の値をフィールド名とした集計値を作ってあげることで、トレリス表示が可能となる。

すごいや:smile:

```sql:same_result.spl
index=_internal sourcetype=splunkd
| timechart count(eval(log_level="INFO")) as INFO  count(eval(log_level="WARN")) as WARN count(eval(log_level="ERROR")) as ERROR by component
```
_trellis_表示すると一緒の表示になるクエリー

ただし、統計情報の結果は

| time | ERROR: BucketMover | ERROR: CsvDataProvider | ERROR: DatabaseDirectoryManager | ERROR: ExecProcessor | ERROR: LMStackMgr | ERROR: Metrics | ERROR: OTHER | ERROR: PeriodicHealthReporter | ERROR: PipelineComponent | ERROR: SearchAssistant | ERROR: spatial:PointInPolygonIndex | INFO: BucketMover | INFO: CsvDataProvider | INFO: DatabaseDirectoryManager | INFO: ExecProcessor | INFO: LMStackMgr | INFO: Metrics | INFO: OTHER | INFO: PeriodicHealthReporter | INFO: PipelineComponent | INFO: SearchAssistant | INFO: spatial:PointInPolygonIndex | WARN: BucketMover | WARN: CsvDataProvider | WARN: DatabaseDirectoryManager | WARN: ExecProcessor | WARN: LMStackMgr | WARN: Metrics | WARN: OTHER | WARN: PeriodicHealthReporter | WARN: PipelineComponent | WARN: SearchAssistant | WARN: spatial:PointInPolygonIndex |
|:--|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| 2020/05/30 07:00:00 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 67 | 6386 | 0 | 672 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
| 2020/05/30 07:30:00 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 6 | 0 | 8 | 1 | 53 | 4999 | 0 | 532 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
となっていて、だいぶ違う。

https://docs.splunk.com/Documentation/Splunk/latest/SearchReference/Timechart
には

```configuration:sep
Syntax: sep=<string>
Description: Used to construct output field names when multiple data series are used in conjunctions with a split-by field. This is equivalent to setting format to $AGG$<sep>$VAL$.
```
と書かれているので、自動的に`VAL(値)`と判断して表示してくれているみたい。
その２の`xyseries`も同じ原理だと思う。 :sweat:集計と値、逆じゃないかな・・・

##その２
```sql:timechart_trellis_2.spl
index=_internal sourcetype=splunkd_*
| timechart count by sourcetype
| untable _time sourcetype count
| streamstats global=f avg(count) as trend window=5 by sourcetype
| xyseries _time sourcetype count trend
```

![trellis.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130729/38523965-0d04-990f-0a05-58af19e30568.png)


| _time | count: splunkd_access | count: splunkd_ui_access | trend: splunkd_access | trend: splunkd_ui_access |
|:--|--:|--:|--:|--:|
| 2020/05/30 06:00:00 | 19 | 0 |   |   |
| 2020/05/30 06:30:00 | 0 | 0 |   |   |
| 2020/05/30 07:00:00 | 21 | 0 | 8.0 | 4.2 |
| 2020/05/30 07:30:00 | 1 | 0 | 4.4 | 4.4 |
| 2020/05/30 08:00:00 | 62 | 232 | 16.8 | 59.0 |
| 2020/05/30 08:30:00 | 7 | 822 | 60.4 | 224.6 |
| 2020/05/30 09:00:00 | 94 | 1279 | 243.4 | 486.8 |
| 2020/05/30 09:30:00 | 0 | 581 | 440.4 | 555.2 |

この結果は少しびっくりしていて、 `xyseries`で作ったフィールド名は `count: splunkd_access`なんだけど、_trellis_表示だと、綺麗にわかれて表示してくれる。

今回は~~`trendline`~~ (*複数フィールドだと上手く動いていないので`streamstats`に変更*) を使ったけど、`eventstats`も使えるからなにかと使えると思う。

```sql:forced_trendline.spl
index=_internal sourcetype=splunkd_*
| timechart count by sourcetype
| trendline sma5(splunkd_access) as "trend: splunkd_access" sma5(splunkd_ui_access) as "trend: splunkd_ui_access"
| untable _time sourcetype count
| eval trend=if(match(sourcetype,"trend"),count,NULL), count = nullif(count,trend)
| eval sourcetype=trim(sourcetype,"trend: ")
| selfjoin _time sourcetype
| stats values(*) as * by _time sourcetype
```
`trendline`は`*`が使えなかったので、こんな感じになった。:sweat:めんどくさい

##応用

| _time | sourcetype | count | trend |
|:--|:--|--:|--:|
| 2020/05/31 06:30:00 | splunkd_ui_access | 239 | 102.6 |
| 2020/05/31 06:30:00 | splunkd_access | 1 | 54.8 |
| 2020/05/31 06:00:00 | splunkd_ui_access | 214 | 54.6 |
| 2020/05/31 06:00:00 | splunkd_access | 59 | 11.8 |
| 2020/05/31 05:30:00 | splunkd_ui_access | 0 | 0.0 |
| 2020/05/31 05:30:00 | splunkd_access | 0 | 0.0 |
| 2020/05/31 05:00:00 | splunkd_ui_access | 0 | 0.0 |
| 2020/05/31 05:00:00 | splunkd_access | 0 | 0.2 |

 `xyseries`の前の結果がこれなので、

1: _trellis_表示を使いたいフィールドを`stats`の`by`で集計
2: `untable`して、`eventstats`とか`trendline`とかで別な集計を実施
3: フィールドの構成は

|col1|col2|col3|col4|...|
|:-:|:-:|:-:|:-:|:-:|
|_time|trellis表示したいフィールド|集計１|集計2|...|
4: `xyseries`で取りまとめる。
   構文は`xyseries col1 col2 col3 col4 ...`
5: _col2_で_trellis_表示をすると綺麗に表示される。


#まとめ
トレリス表示のときは

|x|y|z|
|:-:|:-:|:-:|
|トレリスの基準|表示項目|割合|
になります。
`x`と`y`を`stats`や`chart`で作成すれば、`z`は適当でいいので、
今回みたく数字で作っておいて`replace()`とかで調整して、`list()`や`values()`で表示させてやると思った通りのトレリス表示になりそうです。

:sweat:　実例でやれてないです。

-----
R2.3.8 Line Chartを追記
R2.5.14 timechartで２つ以上のフィールドでトレリスを追記
R2.5.31 timechartで２つ以上のフィールドでトレリスその２を追記