じゅのぶろ

社内SEが自宅でSOC/CSIRTするために色々頑張っていきたいブログ 画像が見れない場合はjavascriptを有効にするかデスクトップからご覧下さい。

Splunkでforeachコマンドを使ってみる

foreachコマンド

WILDCARDマッチなどを使い特定のフィールドに対してEval式の適用など特定の処理をしてくれる便利なコマンドです。

Syntaxはこちら

foreach <wc-field>... [fieldstr=<string>] [matchstr=<string>] [matchseg1=<string>] [matchseg2=<string>] [matchseg3=<string>] <subsearch>

docs.splunk.com

timechartのsum関数を実行したときに複数系列あると以下のようにフィールド名が sum(reply_size): www.google.com sum(reply_size): www.yahoo.co.jp sum(request_size): www.google.com sum(request_size): www.yahoo.co.jpとなってしまいます。
timechartの実行結果。系列名にsum()が追加されてしまう。

この結果のあるフィールドにだけ手を加えたいときに役立ちます。
以下の例はreply_sizeを含むフィールドの値だけを50で割っています。

reply_sizeを含むフィールドの値だけを50で割る

timechartの実行結果。系列名にreply_sizeを含むフィールドの値だけ50で割っています。

SPL

index="squid" domain=www.google.com OR domain=www.yahoo.co.jp
| timechart sum(reply_size) sum(request_size) by domain
| foreach *reply_size* [eval <<FIELD>> = '<<FIELD>>'/50]

以下の例はgoogleを含むフィールドの値だけを1000で割っています。

reply_sizeを含むフィールドの値だけを1000で割る

timechartの実行結果。系列名にgoogleを含むフィールドの値だけ1000で割っています。

SPL

index="squid" domain=www.google.com OR domain=www.yahoo.co.jp
| timechart sum(reply_size) sum(request_size) by domain
| foreach *google* [eval <<FIELD>> = '<<FIELD>>'/1000]

<<FIELD>><<MATCHSTR>>の違い

<<FIELD>>はforeachに渡したフィールド名、
<<MATCHSTR>>はforeachにフィールド名を渡す際、WILDCARDで指定した部分の部分一致となります。

以下の表が入力で与えられたとします。
3x10の表。カラム名test_1,test_2,test3、データ1~10

<<FIELD>>をeval式の左辺ではFIELD名として、右辺ではFIELD値として扱われます。
右辺で"<<FIELD>>"とした場合はFIELD名として扱われます。
一方、<<MATCHSTR>>をeval式の左辺でも右辺でも部分一致したFIELD名として扱われます。

FIELD, FIELD

※FIELD名が重複し、結果が分かりづらいため、new_<<FIELD>>としています。
FIELDとFIELDの組み合わせ

FIELD, "FIELD"

FIELDと

FIELD, MATCHSTR

※FIELD名が重複し、結果が分かりづらいため、new_<<FIELD>>としています。
FIELDとFIELDの組み合わせ

MATCHSTR, MATCHSTR

FIELDとFIELDの組み合わせ

MATCHSTR, FIELD

FIELDとFIELDの組み合わせ

<<MATCHSEG1>><<MATCHSEG3>>について

<<MATCHSTR>>と似たトークンに<<MATCHSEG1>><<MATCHSEG3>>が用意されている。
<<MATCHSEG1>>はWILDCARDを複数回使った場合に最初のWILDCARDに一致した値となる。
2,3についても同様に2個目,2個目のWILDCARDと一致した値となる。

以下の画像はMATCHSTRとMATCHSEGを使用した例。
WILDCARDを3回使用した結果、<<MATCHSTR>>は全てのWILDCARDのマッチ結果をあわせた値となり、 MATCHSEG1~3はそれぞれの場所のWILDCARDのマッチ結果の値となった。 MATCHSEG1~3の利用例。

SPL

| makeresults count=10
| streamstats count
| foreach count [eval test_1_aa=<<FIELD>>,test_2_bb=<<FIELD>>,test_3_cc=<<FIELD>>]
| fields - count _time
|  foreach *_*_* [eval new_<<FIELD>>="<<MATCHSTR>>"." "."<<MATCHSEG1>>"." "."<<MATCHSEG2>>"." "."<<MATCHSEG3>>"]

おわりに

本文では特定のフィールドに対して処理を行いましたが、 全てのフィールドに対してforeachを使うこともでき、| foreach *を使えばよいです。
このときは<<FIELD>><<MATCHSTR>>が同じ値になりますね。

難しいコマンドなので間違いや、こうした方が良い等あるかもしれません。
その際はコメントなどでご指摘いただければと思います。