Hi all,
.
Main description
I set a 1st token as a hostname of a system - $host_tok$
Then I need the dashboard to take this 1st token and determine a 2nd token using a [search] command. The 2nd token is the OS of the hostname (linux or windows) - $os_tok$
When the 2nd token is defined, it then then sets final Title/Search tokens - $load_query_title$, $load_query$.
These final Title/Search tokens will run the dashboard and generate the visualizations.
.
Main problem
I want to have zero user interaction besides changing the hostname.
The best I've achieved so far is a radio button that automatically updates to 'linux' or 'windows' if I change the hostname back-and-forth. But I have to click on the radio button in order to "set" the 2nd token.
.
Details
I have a dashboard that views system performance statistics for both linux and windows machines. The source data is from custom SAR Python and Perfmon PowerShell scripts (not source data from a Splunk App).
Significant Requirement:
I will be linking to this dashboard from other monitoring tools by using:
servername/en-US/app/poc/sysperfstats?form.host_tok=webserver01
So if we have an alert from Nagios for a host, in the Nagios email we can auto-generate a URL that will link to this dashboard and display advanced trending data for the alerting host.
.
Setting the OS:
Since I will only be sending the Hostname as a URL argument, Splunk has to determine if the host a Windows machine or a Linux machine. The basic functionality of this is straightforward, I can do something like this:
index=sysperfstats host=$host_tok$ | eval os=if(sourcetype=="powershell","windows","linux")
.
Changing Panels Dynamically:
Windows and Linux have maybe 50% identical-enough metrics (%swap, %cpuidle, availableram) and 50% unique key health metrics (Linux: load average 1 5 and 15 minute, Windows: "\System\Processor Queue Length")
I can create the same total number of dashboard panels for both linux and windows. 12 panels for linux and 12 panels for windows. But in 1 of those panels, linux would display "System: Load Average" and windows would display "System: Processor Queue Length".
So, I've got that figured out, using some 'set tokens' to dynamically set the panel's Title and Search query.
<input type="radio" token="os_tok" searchWhenChanged="true">
<label>Click to switch linux and windows panels</label>
<search>
<query>index=sysperfstats host=$host_tok$ | eval os=if(sourcetype=="powershell","windows","linux") | head 1 | table os | rename os AS os_tok</query>
</search>
<change>
<condition value="windows">
<set token="load_query_title">Processor Queue Length</set>
<set token="load_query">timechart avg(proc_queue) AS proc_queue</set>
</condition>
</change>
... ... ...
<chart>
<title>System: $load_query_title$</title>
<search>
<query>index=sysperfstats host=$host_tok$ | $load_query$</query>
.
Summary
It works fine if I only had 'linux' systems. I can make the radio button Default to 'linux' and everything works as expected.
But if I send a URL with a windows machine:
servername/en-US/app/poc/sysperfstats?form.host_tok=windowsrv01
The radio button value updates to 'windows', but the dashboard doesn't run until I click on the radio button to activate the "searchWhenChanged" handler.
I know it's not a huge issue to ask users to click on a radio button, but it seems I'm just missing something really simple. And I've spent a few hours looking at other forum posts and examples, so I'm hoping someone has the missing puzzle piece.
From another Splunk Answers question, @somesoni2 (https://answers.splunk.com/users/100305/somesoni2.html ) pointed out selectFirstChoice which solves this issue.
Now when I hit the URL with simply the initial hostname in the URL, the os_tok radio input value gets selected and the token gets 'set' with no user interaction.
https://answers.splunk.com/answers/452261/display-users-timezone-in-timechart-graph.html
From somesoni2:
There is a property of the radio form input using which you can select the first radio button values . It's called selectFirstChoice. See this for more information.
From another Splunk Answers question, @somesoni2 (https://answers.splunk.com/users/100305/somesoni2.html ) pointed out selectFirstChoice which solves this issue.
Now when I hit the URL with simply the initial hostname in the URL, the os_tok radio input value gets selected and the token gets 'set' with no user interaction.
https://answers.splunk.com/answers/452261/display-users-timezone-in-timechart-graph.html
From somesoni2:
There is a property of the radio form input using which you can select the first radio button values . It's called selectFirstChoice. See this for more information.
The only thing I can think of, is case-sensitive match. Other that, I just created this RA dashboard, and it works, Calling this URL has the right values selected http://.../test_dash?earliest=0&latest=&form.host_tok_d=Unix&form.host_tok_r=Windows
<form>
<label>Test Dashboard</label>
<fieldset submitButton="false" autoRun="true">
<input type="radio" token="host_tok_r" searchWhenChanged="true">
<label>Hosts - Radio</label>
<choice value="Windows">Windows</choice>
<choice value="Unix">Unix</choice>
</input>
<input type="dropdown" token="host_tok_d">
<label>Hosts - Dropdown</label>
<choice value="Windows">Windows</choice>
<choice value="Unix">Unix</choice>
</input>
</fieldset>
<row>
<panel>
<event>
<title>Radio: $host_tok_r$, Dropdown: $host_tok_d$</title>
<search>
<query>index=_internal | head 1</query>
<earliest>-15m</earliest>
<latest>now</latest>
</search>
</event>
</panel>
</row>
</form>
I haven't found a method yet to resolve this automatically (besides the idea of making some Javascript code to handle the automatic setting of tokens).
For now, "Linux" is the default selection for the dashboard and users are required to click on a radio button to change all of the dashboard to Windows.
<input type="radio" token="os_tok" searchWhenChanged="true">
<label>Click to switch linux <-> windows</label>
<search>
<query>index = sar host=$host_tok$ | eval os=if(sourcetype=="exec","linux","windows") | head 1 | table os | rename os AS os_tok</query>
</search>
<change>
<condition value="linux">
<set token="load_query_text">Load Average</set>
<set token="load_query">timechart $timebucket$ avg(ldavg_1) AS ldavg_1 avg(ldavg_5) AS ldavg_5 avg(ldavg_15) AS ldavg_15 | eval ldavg_1=round(ldavg_1,2) | eval ldavg_5=round(ldavg_5,2) | eval ldavg_15=round(ldavg_15,2) | rename ldavg_1 as ldavg-1 | rename ldavg_5 as ldavg-5 | rename ldavg_15 as ldavg-15</set>
<set token="cpu_query_text">User, System, Idle, IOwait</set>
<set token="cpu_query">timechart $timebucket$ avg(pct_user) AS pct_user avg(pct_system) AS pct_system avg(pct_iowait) AS pct_iowait avg(pct_idle) AS pct_idle | eval pct_user=round(pct_user,2) | eval pct_system=round(pct_system,2) | eval pct_iowait=round(pct_iowait,2) | eval pct_idle=round(pct_idle,2) | rename pct_user as %user | rename pct_system as %system | rename pct_iowait as %iowait | rename pct_idle as %idle</set>
<set token="disk_1_query_text">Avg Request Size</set>
<set token="disk_1_query">| timechart $timebucket$ avg(avgrq_sz) AS avgrq_sz by DEV | foreach * [eval <<FIELD>>=round('<<FIELD>>',0)]</set>
<set token="disk_2_query_text">Avg Queue Size</set>
<set token="disk_2_query">| timechart $timebucket$ avg(avgqu_sz) by DEV | foreach * [eval <<FIELD>>=round('<<FIELD>>',3)]</set>
<set token="disk_3_query_text">Percent Utilization</set>
<set token="disk_3_query">| timechart $timebucket$ avg(pct_util) AS %util by DEV | foreach * [eval <<FIELD>>=round('<<FIELD>>',2)]</set>
<set token="disk_4_query_text">Reads and Writes</set>
<set token="disk_4_query">| timechart $timebucket$ avg(rd_sec_s) as rd_sec/s avg(wr_sec_s) as wr_sec/s by DEV | foreach * [eval <<FIELD>>=round('<<FIELD>>',1)]</set>
<set token="memory_2_query_text">Available</set>
<set token="memory_2_query">eval mbmemavail = (kbmemused-kbbuffers-kbcached)/1024 | timechart $timebucket$ avg(mbmemavail) AS mbmemavail | eval mbmemavail=round(mbmemavail,0)</set>
<set token="memory_3_query_text">Swapping Rate</set>
<set token="memory_3_query">timechart $timebucket$ avg(pswpin_s) AS pswpin_s avg(pswpout_s) AS pswpout_s | eval pswpin_s=round(pswpin_s,2) | eval pswpout_s=round(pswpout_s,2) | rename pswpin_s as pswpin/s | rename pswpout_s as pswpout/s</set>
<set token="memory_4_query_text">Paging</set>
<set token="memory_4_query">timechart $timebucket$ avg(pgpgin_s) AS pgpgin_s avg(pgpgout_s) AS pgpgout_s | eval pgpgin_s=round(pgpgin_s,2) | eval pgpgout_s=round(pgpgout_s,2) | rename pgpgin_s as pgpgin/s | rename pgpgout_s as pgpgout/s</set>
<set token="network_1_query_text">Bandwidth</set>
<set token="network_1_query">IFACE=eth* OR IFACE=bond* OR IFACE=ens* | eval rxMbit_s=rxkB_s/1024*8 | eval txMbit_s=txkB_s/1024*8 | timechart span=5m avg(rxMbit_s) as rxMbit/s avg(txMbit_s) as txMbit/s by IFACE | foreach * [eval <<FIELD>>=round('<<FIELD>>',2)]</set>
<set token="network_2_query_text">Errors and Collisions</set>
<set token="network_2_query">IFACE=eth* OR IFACE=bond* OR IFACE=ens* | timechart $timebucket$ avg(rxerr_s) as rxerr/s avg(txerr_s) as txerr/s avg(coll_s) as coll/s by IFACE | foreach * [eval <<FIELD>>=round('<<FIELD>>',0)]</set>
<set token="network_3_query_text">Connections</set>
<set token="network_3_query">| timechart $timebucket$ avg(totsck) as totsck avg(tcpsck) as tcpsck avg(udpsck) as udpsck | eval totsck=round(totsck,0) | eval tcpsck=round(tcpsck,0) | eval udpsck=round(udpsck,0)</set>
</condition>
<condition value="windows">
<set token="load_query_text">Proc Queue</set>
<set token="load_query">timechart $timebucket$ avg(proc_queue) AS proc_queue</set>
<set token="cpu_query_text">User, System, Idle, Interrupt</set>
<set token="cpu_query">timechart $timebucket$ avg(pct_user) AS pct_user avg(pct_system) AS pct_system avg(pct_interrupt) AS pct_interrupt avg(pct_idle) AS pct_idle | eval pct_user=round(pct_user,2) | eval pct_system=round(pct_system,2) | eval pct_interrupt=round(pct_interrupt,2) | eval pct_idle=round(pct_idle,2) | rename pct_user as %user | rename pct_system as %system | rename pct_interrupt as %interrupt | rename pct_idle as %idle</set>
<set token="disk_1_query_text">Avg Latency</set>
<set token="disk_1_query">Disk!="_total" | timechart $timebucket$ avg(rd_latency) AS rd_latency avg(wr_latency) AS wr_latency by Disk | foreach * [eval <<FIELD>>=round('<<FIELD>>',0)]</set>
<set token="disk_2_query_text">Avg Queue Length</set>
<set token="disk_2_query">Disk!="_total" | timechart $timebucket$ avg(disk_queue) by Disk | foreach * [eval <<FIELD>>=round('<<FIELD>>',1)]</set>
<set token="disk_3_query_text">Percent Utilization</set>
<set token="disk_3_query">Disk!="_total" | eval pct_util=101-idle_time | timechart $timebucket$ avg(pct_util) AS %util by Disk | foreach * [eval <<FIELD>>=round('<<FIELD>>',2)]</set>
<set token="disk_4_query_text">Reads and Writes</set>
<set token="disk_4_query">Disk!="_total" | timechart $timebucket$ avg(rd_sec_s) as rd_sec/s avg(wr_sec_s) as wr_sec/s by Disk | foreach * [eval <<FIELD>>=round('<<FIELD>>',1)]</set>
<set token="memory_2_query_text">Available</set>
<set token="memory_2_query">timechart $timebucket$ avg(mbmemavail) AS mbmemavail | eval mbmemavail=round(mbmemavail,0)</set>
<set token="memory_3_query_text">Page Faults</set>
<set token="memory_3_query">timechart $timebucket$ avg(fault_s) AS fault_s avg(pgpgin_s) AS pgpgin_s avg(pgread_s) as pgread_s | eval fault_s=round(fault_s/1000,2) | eval pgpgin_s=round(pgpgin_s,2) | eval pgread_s=round(pgread_s,2) | rename fault_s as "Page Faults (1000/s)" | rename pgpgin_s as "Pages Input/s" | rename pgread_s as "Page Reads/s"</set>
<set token="memory_4_query_text">Paging</set>
<set token="memory_4_query">timechart $timebucket$ avg(poolpaged_mbytes) AS poolpaged_mbytes avg(poolnonpaged_mbytes) AS poolnonpaged_mbytes | eval poolpaged_mbytes=round(poolpaged_mbytes,2) | eval poolnonpaged_mbytes=round(poolnonpaged_mbytes,2)</set>
<set token="network_1_query_text">Bandwidth</set>
<set token="network_1_query">| rex field=Interface "(?<IFACE>.*)_ethernet_adapter" | eval rxMbit_s=rxkB_s/1024*8 | eval txMbit_s=txkB_s/1024*8 | timechart span=5m avg(rxMbit_s) as rxMbit/s avg(txMbit_s) as txMbit/s by IFACE | foreach * [eval <<FIELD>>=round('<<FIELD>>',2)]</set>
<set token="network_2_query_text">Errors, Discards, and Collisions</set>
<set token="network_2_query">| rex field=Interface "(?<IFACE>.*)_ethernet_adapter" | timechart $timebucket$ avg(rxerr) as rxerr avg(txerr) as txerr avg(rxdiscard) as rxdiscard avg(txdiscard) as txdiscard avg(coll) as coll by IFACE | foreach * [eval <<FIELD>>=round('<<FIELD>>',2)]</set>
<set token="network_3_query_text">Connections</set>
<set token="network_3_query">| timechart $timebucket$ avg(totsck) as totsck avg(tcpsck) as tcpsck avg(udpsck) as udpsck | eval totsck=round(totsck,0) | eval tcpsck=round(tcpsck,0) | eval udpsck=round(udpsck,0)</set>
</condition>
</change>
<fieldForLabel>os_tok</fieldForLabel>
<fieldForValue>os_tok</fieldForValue>
<default>linux</default>
</input>
Thanks! I need to be able to call the hostname in the URL, though:
servername/en-US/app/poc/sysperfstats?form.host_tok=webserver01
I just tried this and mongod is selected in the radio list AND the list is populated dynamically
http://localhost:8000/en-US/app/answers/test_answers/edit?earliest=0&latest=&form.host_tok_r=mongod
<input type="radio" token="host_tok_r" searchWhenChanged="true">
<label>Hosts - Radio</label>
<search>
<query>index=_internal | stats count by sourcetype</query>
</search>
<fieldForLabel>sourcetype</fieldForLabel>
<fieldForValue>sourcetype</fieldForValue>
</input>
Thanks, yes that's functionality which is already working properly. The 1st token (called in the URL) must generate a 2nd token (not provided in the URL) which then automatically sets additional tokens.
The difficult part is having the 2nd token (again, not called in the URL) automatically setting the additional tokens.