Splunk CSV等を加工したあとインデックスに取り込む

https://community.splunk.com/t5/Getting-Data-In/Index-time-field-extraction-not-working-with-backslash-in-field/m-p/505360
で回答したもののまとめ。
#前提
```console:psv.log
XXmentid|XX_date|blnumber|node|mode_nm|mode_nm2
"020202"|"2020-05-06 00:00:00"|"\"SCT 33447 33276 33276\""|"FAPJ"|"SCT 33447 33276 33276"|"SCT 33447 33276 33276"
```
いわゆる PSV(Pipe Separated Values)形式のファイル
SplunkはPSVの取り込みも、もちろん可能

#問題発生
```configuration:props.conf
INDEXED_EXTRACTIONS = psv
```
で取り込もうとすると
`blnumber=\"SCT 33447 33276 33276\""|"FAPJ`
となってしまう。
`\(back slash)`が悪さをしていて、`|`を認識しない。:confused: 

`SEDCMD`で削除する手があるけど、`INDEXED_EXTRACTIONS`が先に動いてしまう。
そのため、効果がない。

[props.conf](https://docs.splunk.com/Documentation/Splunk/latest/Admin/Propsconf)の評価順は

1. LINE_BREAKER
2. INDEXED_EXTRACTION
3. SEDCMD
4. TRANSFORMS等フィールド抽出

の順番みたい。確か以前の記事にあったと思うので、あとで修正します。

#解決方法
```configuration:props.conf
[psv_test]
LINE_BREAKER = ([\r\n]+)
NO_BINARY_CHECK = true
SEDCMD-trim = s/\\"//g
SHOULD_LINEMERGE = false
category = Custom
description = psv
pulldown_type = true
PREAMBLE_REGEX = XX.*
disabled = false
DATETIME_CONFIG =
TRANSFORMS-psv = psv
```

```configuration:transforms.conf
[psv]
REGEX = (?<XXmentid>[^\|]+)\|(?<XX_date>[^\|]+)\|(?<blnumber>[^\|]+)\|(?<node>[^\|]+)\|(?<mode_nm>[^\|]+)\|(?<mode_nm2>[^\|]+)
FORMAT = XXmentid::$1 XX_date::$2 blnumber::$3 node::$4 mode_nm::$5 mode_nm2::$6
WRITE_META = true
```

#解説
##props.conf
1. `PREAMBLE_REGEX` でヘッダー行を削除。以前は`TRANSFORMS`で_nullqueue_送りにしてたけど、これで良かった。
2. `SEDCMD`は悪さする`\|`を削除

##transforms.conf
1. `DELIMS`と`FIELD`のコンボは**search time extraction**なので今回は使えなかった。
2. `REGEX`と`WRITE_META`で行けるかと思ったけど、ダメだった。`FORMAT`は必須
 -  `* At index-time, FORMAT defaults to <stanza-name>::$1` ということらしい
3. `FORMAT`の区切り文字は特になかった、逆に`,`をつけていたら、値になってしまった。

#確認

```sql:search.spl
sourcetype="psv_test" node::FAPJ
```
結果が返ってきたので、きちんとindexに取り込まれている。

#フィールドを作ったり削除したり

```bash:sample.csv
2020/03/03,13:40:23,Ohio,1,200,30
2020/03/03,13:40:23,Ohio,2,33000,40.4173,82.9071
```

https://community.splunk.com/t5/Getting-Data-In/CSV-field-header-label-based-on-a-value-in-column/m-p/513427#M87073

のサンプル。

```configuration:props.conf
[double_csv]
INDEXED_EXTRACTIONS = csv
FIELD_NAMES = DATE,TIME, LOCATION,EVENT,altitude,latitude,longitude
DATETIME_CONFIG =
SHOULD_LINEMERGE = false
LINE_BREAKER = ([\r\n]+)
NO_BINARY_CHECK = true
category = Custom
pulldown_type = true
TRANSFORMS-csv = double_csv, double_csv1
disabled = false
```

```configration:transforms.conf
[double_csv]
INGEST_EVAL = speed=if(EVENT=1,altitude,NULL), tilt=if(EVENT=1,latitude,NULL)
WRITE_META = true

[double_csv1]
INGEST_EVAL = longitude:=if(EVENT=1,null(),logitude), altitude:=if(EVENT=1,null(),altitude), latitud
e:=if(EVENT=1,null(),latitude)
WRITE_META = true
```

`INGEST_EVAL`の`:=`を思い出せなくて、とても苦労しました:sweat:
`eval`で上書きできるので、途中で別なフィールドを作ったり、元のデータを削除したりはこのようにできる。

なお、一つにまとめることは可能です。

#ヘッダーの付け替え

```bash:sample.csv
time,command,data1,data2,
2020/03/03,13:40:23,Ohio,1
2020/03/03,13:40:23,Ohio,2
```

このCSVのヘッダーを付け替える場合

```configuration:props.conf
INDEXED_EXTRACTIONS = csv
KV_MODE=none
SHOULD_LINEMERGE=false
category=Structured
description=Comma-separated value format
disabled=false
pulldown_type=true
FIELD_NAMES=time,program,event,data
PREAMBLE_REGEX=command
```

- `FIELD_NAMES`で新しいフィールド名をつける
- `PREAMBLE_REGEX`でヘッダー削除

が一番早かった。

#まとめ
`SEDCMD`が`INDEXED_EXTRACTIONS`の後にしか効かないので、ちょっとログが変だと、こんな感じでいろいろと`transforms.conf`側でやらなければいけない。

`INDEXED_EXTRACTIONS`が使えれば、`props.conf`の`FIELD_NAMES`で指定ができる。

ヘッダーからフィールドが自動的に取れれば楽だけど、仕方ないですね:sweat: