Splunk Dashboard tokenの細かい話(処理タイミング編)
前提の話
Splunkダッシュボードを使うときに、検索結果をクリックすると更に別の詳細分析用にジャンプする。
そういう使い方ができるDrill Downは大変便利です。
便利だからと引き渡す変数(トークン)をあれこれあれこれとしていくと、、結構壁にぶつかりました。
色々と試行錯誤して、結果大変泥臭いTipsが溜まったので、吐き出しておこうかと思います。
tokenの定義と利用
公式だと、以下くらいしか見つけられていないのですが、もうちょっと泥臭い話がしたいんですよね。。
tokenの登録
フォームへの入力
フォームに入力した値は、$form.XXX$ (XXXはInputのなかの”トークン"で指定)と、$XXX$に登録されます。
$form.XXX$と$XXX$の違いですが、ドキュメントが見つけられてないのですが、実際の動きを見た理解としては、$form.XXX$はブラウザに表示され、入力窓に記入されている値。
$XXX$は、Splunkが内部で入力窓に入れた値を取り出して、取り込んだもの。
この差が大きく出るのは、Drilldownで転送されてきた時。
Drilldownの際に、クエリストリングでtokenを受け付けて、その値ベースでリンク後のダッシュボードの検索をするのですが、Inputに値を入れたいときは$form.XXX$に対して値を指定する必要があります。
$XXX$に対して値を指定するクエリストリングを書いてしまうと、表示上入力欄が空っぽだけど、内部的には$XXX$が値を受け取っている、という変な状態が出来上がります。
(あ、formの上書きが走るが正しいかも、別記事書くときに調べときます)
サーチ後に自動で登録されるもの
最初のリンク先が詳しいのですが、$result.XXX$や$job.XXX$などです。
但し、これはある一連のサーチの処理の際のみに使える、ローカル変数のようのなものです。他の処理で使いたいのなら、setやevalで別名のtoken(グローバル変数のイメージ)に代入する必要があります。
サーチ後などに任意に登録するもの
サーチ処理などは、<done>というエレメントを持っており、サーチ終了後に実施する処理を定義できます。
その中で、setやevalエレメントを使って任意のtokenを登録することができます。
こんな感じですね。
<dashboard>
<label>dashboard01</label>
<row>
<panel>
<table>
<search>
<query>| from datamodel:"internal_audit_logs.Audit"
| table _time host, action, info, sorce, user</query>
<earliest>-24h@h</earliest>
<latest>now</latest>
<done>
<set token="AfterSearch">Search Done</set>
</done>
</search>
<option name="drilldown">none</option>
</table>
</panel>
</row>
</dashboard>
但し、コレはサーチが実施されるごとに何度も実施されます。
例えば、queryの中にtokenが入っている場合、tokenの値が変わるたびに毎回サーチが走ります。
「処理タイミング」の観点でこれが意外な結果をもたらしたりするので、注意を要します。。
環境変数
これも最初のリンクの説明のとおりで、$env.XXX$などのことです。
$env.user$とか、結構使いみちがあります。
クエリストリングからの読み込み
DrillDownで転送してくる場合など、転送前にURLの中にクエリストリングを仕込んでおく(https://<FQDN>/<Dashboard>?XXX=hogehoge)とした場合、Splunkは$XXX$に"hogehoge"を取り込んでくれます。
Init
ダッシュボードを読み込むときに、一番最初に実施される処理ブロックである<init>の中で、setやevalで登録します。
但し、後述しますが、この処理は「フォーム入力」や「クエリストリングからの読み込み」、更には環境変数の取り込みよりも前に実行されます。
これが、実はこの記事で一番言いたいことだったりします。
脱線 set/eval
Initの際やサーチ後に使うset/evalに関するtipsです。
すでに登録済みの他のtokenを代入したり、そのtokenベースで計算処理して代入する、ということがあります。
この際、tokenが未定義の場合は、値として"$XXX$"という「文字列」が入ります。
で、ここで定義するtokenを使う先の処理ではエラーを起こして処理が止まる/「検索入力待ち」という表示になる、ということで事故につながることはあまりないとは思うのですが、デバッグなどで表示させるときに"$XXX$"という文字列が出てきたら、未定義なんだな、、と判断できるので、留意を要します。
tokenの利用(出力)
コレは簡単で、queryの中でも、set/evalの中でも、エレメント内で使うときには$XXX$と記載すれば、勝手に代入されている値に変換して処理してくれます。
tokenの処理順序
実験(Init要素の処理タイミング)
以下のようなダッシュボードを用意して、実験してみます。
<form>
<label>linked01</label>
<init>
<set token="init_static">Static Value</set>
<set token="init_from_form">$form.text$</set>
<set token="init_from_env">$env:version$</set>
<set token="init_from_querystring">$querystring$</set>
</init>
<fieldset submitButton="false">
<input type="text" token="text">
<label>text</label>
<default>Text init</default>
</input>
</fieldset>
<row>
<panel>
<html>
<h1>$$init_static$$: $init_static$</h1>
<h1>$$init_from_form$$: $init_from_form$</h1>
<h1>$$init_from_env$$: $init_from_env$</h1>
<h1>$$init_from_querystring$$: $init_from_querystring$</h1>
<h1>$$form.text$$: $form.text$</h1>
<h1>$$text$$: $text$</h1>
<h1>$$env.version$$: $env:version$</h1>
<h1>$$querystring$$: $querystring$</h1>
</html>
</panel>
</row>
</form>
以下のようにブラウザを叩いてみます。
https://<ダッシュボードまでのパス>?querystring=QS
上の3行の、Initの中で値を取り込んだtokenズを見ていただきたいのですが、静的に与えた"Static Value"意外の、他のtokenの値を読み込む前提の部分はすべてtoken名(=未定義)になっていることがわかるかと思います。
Init要素の処理段階では、formやクエリストリングからの値の読み込みが内部的に終わってないんだと思います。
「とはいえtokenとしては受け取れてるんだから、別に問題ないんじゃないの?」と言われそうですが、ダッシュボードの「中」で、受け取ったtokenを下処理して使いたい、というケースは多々あります。
Initのように、「ダッシュボード内で最初に一回だけtokenの整理をしたい」という処理ができないと、受け取った値をそのまま処理で使うしかなくなるので、もし値にあれこれ手を加えたいなら、その処理をドリルダウン前のダッシュボードでやって、処理後の値をクエリストリングでうけわたさないといけなくなり、実装が非常に汚くなります。。。
Init以外の選択肢
乱暴ではあるのですけれど、Inputやクエリストリングのtoken受取が終わった後に、1回だけ処理する、という方法としては、「空打ちサーチ」くらいかな、と思っています。
<search>要素は、<dashboard>直下においてもいいですし、非表示にしたpanelのなかのテーブルに仕込む形でもいいですので、以下のように空打ち処理を実施させて、その後の<done>要素でやりたい処理をさせる、という方法です。
<form>
<label>linked01</label>
<init>
<set token="init_static">Static Value</set>
<set token="init_from_form">$form.text$</set>
<set token="init_from_env">$env:version$</set>
<set token="init_from_querystring">$querystring$</set>
</init>
<search>
<query>
| makeresults 1
</query>
<done>
<set token="init_static">Static Value</set>
<set token="init_from_form">$form.text$</set>
<set token="init_from_env">$env:version$</set>
<set token="init_from_querystring">$querystring$</set>
</done>
</search>
<fieldset submitButton="false">
<input type="text" token="text">
<label>text</label>
<default>Text init</default>
</input>
</fieldset>
<row>
<panel>
<html>
<h1>$$init_static$$: $init_static$</h1>
<h1>$$init_from_form$$: $init_from_form$</h1>
<h1>$$init_from_env$$: $init_from_env$</h1>
<h1>$$init_from_querystring$$: $init_from_querystring$</h1>
<h1>$$form.text$$: $form.text$</h1>
<h1>$$text$$: $text$</h1>
<h1>$$env.version$$: $env:version$</h1>
<h1>$$querystring$$: $querystring$</h1>
</html>
</panel>
</row>
</form>
一瞬チカっと先と同じ表示になった後、以下のように値がきちんとは言っているのが見えるはずです。
。。。。ん??envだけ取れてない!?
試しに隠しパネル式でやってみましたが、ダメでした。。
envはもうちょっと調べときます。。
(Drilldownで使うときは問題ないので、これもタイミングがあるのですね、きっと、、)
とりあえず
この記事はここまでで。
別途、時間処理のtipsと、上記の未定義トークンを使ったサーチ(outputlookupタイミングの制御)のtipsは近々書こうと思います。
Discussion