Hello Again,
I am using Splunk 9.4.12 on Oracle Linux 9. I want to use dashboard studio. Is dashboard studio
preferred over simple xml? I want to use the name/value of a column to create a search for a table using a token. Depending on column name (ERRORS or WARNINGs) I want to see a table with the toke set to
$ERRORS$ or $WARNINGS$. Can this be done using Splunk Dashboard Studio, or do I have to use Simple XML?
Thaniks,
eholz1
Hi @eholz1,
I'll add one more example that works in Splunk Enterprise 9.4.12 and sets token values directly from a column chart. The token value you're looking for is probably row.<fieldname>.value, where <fieldname> corresponds to the over/row-split field in the chart command or the x-value in the xyseries command.
E.g.:
index=_internal source=*splunkd.log*
| chart limit=10 usenull=f useother=f count over log_level by componentindex=_internal source=*splunkd.log*
| stats count by log_level component
| xyseries log_level component count=>
row.log_level.value
You copy and paste the source below or use it as a reference to define the dashboard using Dashboard Studio. There's no source-only magic in the dashboard.
{
"title": "ds_drilldown",
"description": "",
"inputs": {
"input_global_trp": {
"options": {
"defaultValue": "-24h@h,now",
"token": "global_time"
},
"title": "Global Time Range",
"type": "input.timerange"
}
},
"defaults": {
"dataSources": {
"ds.search": {
"options": {
"queryParameters": {
"earliest": "$global_time.earliest$",
"latest": "$global_time.latest$"
}
}
}
}
},
"visualizations": {
"viz_TbwbICq3": {
"dataSources": {
"primary": "ds_zDetExHq"
},
"options": {},
"type": "splunk.table"
},
"viz_ZhY8abJJ": {
"options": {
"markdown": "**chart_name:** $chart_name$\n\n**chart_value:** $chart_value$\n\n**chart_row_log_level_value:** $chart_row_log_level_value$"
},
"type": "splunk.markdown"
},
"viz_eASiDDzL": {
"dataSources": {
"primary": "ds_AIqBMriG"
},
"eventHandlers": [
{
"options": {
"tokens": [
{
"key": "name",
"token": "chart_name"
},
{
"key": "value",
"token": "chart_value"
},
{
"key": "row.log_level.value",
"token": "chart_row_log_level_value"
}
]
},
"type": "drilldown.setToken"
}
],
"options": {},
"type": "splunk.column"
}
},
"dataSources": {
"ds_AIqBMriG": {
"name": "Search_1",
"options": {
"query": "index=_internal source=*splunkd.log*\n| chart limit=10 usenull=f useother=f count over log_level by component",
"queryParameters": {}
},
"type": "ds.search"
},
"ds_zDetExHq": {
"name": "Search_2",
"options": {
"query": "index=_internal source=*splunkd.log* log_level=$chart_row_log_level_value|s$\n| table _time log_level component _raw"
},
"type": "ds.search"
}
},
"layout": {
"globalInputs": [
"input_global_trp"
],
"layoutDefinitions": {
"layout_1": {
"options": {
"height": 960,
"width": 1440
},
"structure": [
{
"item": "viz_eASiDDzL",
"position": {
"h": 400,
"w": 1440,
"x": 0,
"y": 0
},
"type": "block"
},
{
"item": "viz_ZhY8abJJ",
"position": {
"h": 87,
"w": 1440,
"x": 0,
"y": 400
},
"type": "block"
},
{
"item": "viz_TbwbICq3",
"position": {
"h": 400,
"w": 1440,
"x": 0,
"y": 487
},
"type": "block"
}
],
"type": "grid"
}
},
"options": {},
"tabs": {
"items": [
{
"label": "New tab",
"layoutId": "layout_1"
}
]
}
}
}
I'm also a bit like everyone else: I prefer Simple XML; however, that's mostly because it's what I've used daily for ... too many years. Dashboard Studio iterates significantly with every release. Splunk Enterprise 10.4 and Splunk Cloud Platform 10.4.2604 added support for custom visualizations, for example.
The product manager for Dashboard Studio and other SplunkWeb features posts blog updates and (presumably) monitors Answers. I know they welcome friendly, constructive feedback. That said, Splunk Enterprise 9.4 is nearly three years old now and more than a little out of date with respect to Dashboard Studio.
There was a competition recently encouraging people to submit Dashboard designs, showcasing creativity and complex interactions, only it had to be in Dashboard Studio. I tried "porting" my favourite, most interactive dashboard from SimpleXML to Studio, but I was unable to find a way to replicate everything I had done with SimpleXML in Studio. Perhaps I didn't try hard enough; the prize was a .conf pass,, but since I am unable to make it this year, there wasn't so much of an incentive, and I have been busy with other stuff (puzzles in Slack, questions for BORE and SPLing Bee, etc.)! 😎
I love engineering/systems-oriented dashboards and applied puzzle solving, but when I try to do something "pretty" ... the Titanic flute fail meme comes to mind. My favorite dashboards tend to be simple things with 3-5 metrics (principal component analysis maybe?) that say this is your root cause.
That Titanic meme is great - never seen it before.
There is a Camden active in Slack DS who seems reasonably interested in hearing ideas and use cases. I recently sent him an app of blocking stuff we do in XML that does not yet port to DS, primarily around interactivity/tokens. The team have made massive strides with it in the last year or so, but it's still not for me...
I'm another advocate for XML over DS. It still has a greater ability to style display elements than DS using CSS. Token interaction is better in XML, especially if you plug in a tiny piece of JS into your app, which then allows token management through <button> elements in <html> panels.
Although DS does have conditional token handling so can model XML's depends= and rejects= constructs, it doesn't have this flexibility.
Sure you can add pretty pictures in DS that make it look appealing, but for any kind of interactive dashboard, XML is probably superior (for the time being).
Hi @eholz1
Is this what you are looking for?
Sample Dashboard Studio JSON below:
{
"title": "Splunk Answers - Select token",
"description": "",
"inputs": {
"input_global_trp": {
"options": {
"defaultValue": "-24h@h,now",
"token": "global_time"
},
"title": "Global Time Range",
"type": "input.timerange"
}
},
"defaults": {
"dataSources": {
"ds.o11y": {
"options": {
"queryParameters": {
"earliest": "$global_time.earliest$",
"latest": "$global_time.latest$"
}
}
},
"ds.search": {
"options": {
"queryParameters": {
"earliest": "$global_time.earliest$",
"latest": "$global_time.latest$"
}
}
},
"ds.spl2": {
"options": {
"queryParameters": {
"earliest": "$global_time.earliest$",
"latest": "$global_time.latest$"
}
}
}
},
"visualizations": {
"global": {
"showProgressBar": true
}
}
},
"visualizations": {
"viz_1AKJy9Nl": {
"options": {
"markdown": "Column = $myToken_colName$ \nField Val = $myToken_val$"
},
"type": "splunk.markdown"
},
"viz_3gsbpHDP": {
"options": {
"markdown": "# Search: \nindex=_internal $myToken_colName$=$myToken_val|s$ | stats count by source, sourcetype"
},
"type": "splunk.markdown"
},
"viz_JuRIvRRn": {
"dataSources": {
"primary": "ds_wp6MIDyw"
},
"eventHandlers": [
{
"options": {
"tokens": [
{
"key": "name",
"token": "myToken_colName"
},
{
"key": "value",
"token": "myToken_val"
}
]
},
"type": "drilldown.setToken"
}
],
"options": {
"count": 20,
"dataOverlayMode": "none",
"drilldown": "none",
"showInternalFields": false,
"showRowNumbers": false
},
"type": "splunk.table"
},
"viz_tylYiXSD": {
"dataSources": {
"primary": "ds_P0dq5nsp"
},
"options": {},
"type": "splunk.table"
}
},
"dataSources": {
"ds_P0dq5nsp": {
"name": "Search_1",
"options": {
"query": "index=_internal $myToken_colName$=$myToken_val|s$ | stats count by source, sourcetype"
},
"type": "ds.search"
},
"ds_wp6MIDyw": {
"name": "Table search",
"options": {
"query": "| tstats count where index=_internal by sourcetype, host prestats=t | stats count by host, sourcetype",
"queryParameters": {
"earliest": "-24h@h",
"latest": "now",
"sampleRatio": 1
}
},
"type": "ds.search"
}
},
"layout": {
"globalInputs": [
"input_global_trp"
],
"layoutDefinitions": {
"layout_1": {
"options": {
"display": "auto",
"height": 960,
"width": 1440
},
"structure": [
{
"item": "viz_JuRIvRRn",
"position": {
"h": 250,
"w": 1440,
"x": 0,
"y": 50
},
"type": "block"
},
{
"item": "viz_1AKJy9Nl",
"position": {
"h": 50,
"w": 340,
"x": 10,
"y": 10
},
"type": "block"
},
{
"item": "viz_3gsbpHDP",
"position": {
"h": 80,
"w": 850,
"x": 20,
"y": 320
},
"type": "block"
},
{
"item": "viz_tylYiXSD",
"position": {
"h": 180,
"w": 1410,
"x": 10,
"y": 410
},
"type": "block"
}
],
"type": "absolute"
}
},
"options": {},
"tabs": {
"items": [
{
"label": "New tab",
"layoutId": "layout_1"
}
]
}
},
"applicationProperties": {
"hideEdit": false,
"hideExport": false
}
}
🌟 Did this answer help you? If so, please consider:
Your feedback encourages the volunteers in this community to continue contributing.
Hello livelybid,
and other responders. Thank you for the feedback and examples. I think I almost favor
SimpleXML over Dashboard Studio, bu tthe jury is still out.
Thank you for the good example.
eholz1
Is dashboard studio preferred over simple xml?
It depends what you weight. Splunk's strategic direction is Dashboard Studio — that's where new visualization work and feature investment go, and it's what Splunk steers new users toward. Simple XML is still fully supported and not deprecated, so existing dashboards aren't going anywhere.
The practical catch for your use case: Simple XML still has a couple of drilldown capabilities Dashboard Studio doesn't replicate cleanly, and conditional drilldown is the big one. More on that below.
Yes, this works in Dashboard Studio. As of 9.4, the table visualization supports predefined drilldown tokens where you choose an event of either name, value, or row.<fieldname>.value — and "name" is the field name of the value/location clicked. So clicking a cell in your ERRORS column gives you name = "ERRORS", and the WARNINGS column gives name = "WARNINGS". That's the column-detection you're after. Splunk
You'd configure it under the Interactions section of the visualization's config panel, or directly in JSON:
"eventHandlers": [ { "type": "drilldown.setToken", "options": { "tokens": [ { "token": "clicked_col", "key": "name" }, { "token": "clicked_val", "key": "value" } ] } } ]
After a click, $clicked_col$ holds "ERRORS" or "WARNINGS" and $clicked_val$ holds the cell's value. Your detail table's search then consumes them, e.g.:
index=your_index | search severity="$clicked_col$"If the column label doesn't match the raw field value, you map it in SPL with an eval/case rather than needing two tokens.
Where you'll feel the difference is your phrasing about setting either `ERRORSERRORS ERRORS` or `WARNINGSWARNINGS WARNINGS` depending on the column. Simple XML does this natively with <condition match="..."> blocks that set one token and unset others. Dashboard Studio's drilldown.setToken has no equivalent conditional matcher - this is a long-standing gap that trips people up. You can't say "if column is ERRORS, set this token; else set that one" inside the event handler.
So you have two realistic paths:
The Dashboard Studio way — set a single token to the column name (as above) and do all the branching in SPL with eval ... case() or if(). This is clean and is how most people handle it in Studio. One token, logic lives in the search.
The Simple XML way — if you genuinely need separate $ERRORS$ and $WARNINGS$ tokens set/unset conditionally (e.g., to show/hide whole panels), Simple XML's <condition match="'click.name2'==\"ERRORS\""> pattern is more direct and less fiddly.
My suggestion: build it in Dashboard Studio with the single clicked_col token and branch in SPL. You keep Splunk's preferred platform and avoid the one feature it's missing. Only fall back to Simple XML if you specifically need conditional token unsetting for panel visibility that's awkward to drive from a single token.
Hello kml_uvce,
and other responders. Thank you for the feedback and examples.
Thank you for the good example.
eholz1
As @kml_uvce says, Dashboard Studio does not replicate Simple XML features cleanly. Here, "cleanly" is the key word. You did not specify the exact result you are trying to get by setting either $ERRORS$ or $WARNINGS$. But DS can achieve most effect you want to implement. (I ran into an unexpected bug while testing one use case; I will explain that later.)
The most common use case of setting conditional token names is for them to be used on the dashboard itself, mostly to hide or reveal an element as kml_uvce suggests. (Because you cannot use unset token in search, $ERRORS$ and $WARNINGS$ cannot appear in the same panel even in Simple XML.) So, I constructed this dashboard to demonstrate two methods to achieve such hide-and-seek interaction.
{
"title": "Drilldown from column chart",
"description": "https://community.splunk.com/t5/Dashboards-Visualizations/How-to-Create-a-drill-down-from-a-column-chart/m-p/761714/highlight/true#M59493",
"inputs": {},
"defaults": {
"dataSources": {
"ds.search": {
"options": {
"queryParameters": {
"earliest": "$global_time.earliest$",
"latest": "$global_time.latest$"
}
}
},
"ds.spl2": {
"options": {
"queryParameters": {
"earliest": "$global_time.earliest$",
"latest": "$global_time.latest$"
}
}
}
},
"visualizations": {
"global": {
"showProgressBar": true
}
}
},
"visualizations": {
"viz_FwYm3SJW": {
"containerOptions": {
"visibility": {
"showConditions": [
"condition_brJLKJTd"
]
}
},
"options": {
"markdown": "Only show if *ERROR* is clicked!\n\nDo some search with $ set stuff conditionally:result.error_clicked $ (value is $set stuff conditionally:result.error_clicked$)"
},
"type": "splunk.markdown"
},
"viz_b4Bxi3gB": {
"dataSources": {
"primary": "ds_Oaqhxumn"
},
"eventHandlers": [
{
"options": {
"tokens": [
{
"key": "name",
"token": "click_col"
},
{
"key": "value",
"token": "click_val"
},
{
"token": "info_clicked_tok",
"value": "$set stuff conditionally:result.info_clicked$"
}
]
},
"type": "drilldown.setToken"
}
],
"title": "this is your column chart",
"type": "splunk.table"
},
"viz_o3sdPo7w": {
"containerOptions": {
"visibility": {
"showConditions": [
"condition_5dQcfJWD"
]
}
},
"options": {
"markdown": "This panel only shows if clicked value is **greater than** 0\n\n> clicked name: $click_col$\n\n> clicked value: $click_val$"
},
"type": "splunk.markdown"
},
"viz_o6JLZxMy": {
"dataSources": {
"primary": "ds_U44DG9ro"
},
"title": "output from >set stuff conditionally<",
"type": "splunk.table"
},
"viz_xM7oEpU3": {
"options": {
"markdown": "values in \"set stuff conditionally\" search. Formula is\n`$<search name>.result.<field name>$`\n\n- $ set stuff conditionally:result.info_clicked $: $set stuff conditionally:result.info_clicked$\n- $ set stuff conditionally:result.warn_clicked $: $set stuff conditionally:result.warn_clicked$\n- $ set stuff conditionally:result.warning_clicked $: $set stuff conditionally:result.warning_clicked$\n- $ set stuff conditionally:result.error_clicked $: $set stuff conditionally:result.error_clicked$"
},
"type": "splunk.markdown"
},
"viz_y668z7ad": {
"containerOptions": {
"visibility": {
"showConditions": [
"condition_6zVp0DS6"
]
}
},
"options": {
"markdown": "Only show if **WARN** is clicked!\n\nDo some search with $ set stuff conditionally:result.warn_clicked $ (value is $set stuff conditionally:result.warn_clicked$)"
},
"type": "splunk.markdown"
},
"viz_zugP9Nmm": {
"containerOptions": {
"visibility": {
"showConditions": [
"condition_BiyxjNkX"
]
}
},
"options": {
"markdown": "This panel only shows after click\n\nYou last clicked\n\n> Field name (i.e., $ click_col $): $click_col$\n\n> Field value (i.e., $ click_val $): $click_val$"
},
"type": "splunk.markdown"
}
},
"dataSources": {
"ds_Oaqhxumn": {
"name": "column chart search",
"options": {
"query": "index=_internal log_level=*\n| chart count over sourcetype by log_level",
"queryParameters": {
"earliest": "-24h@h",
"latest": "now"
}
},
"type": "ds.search"
},
"ds_U44DG9ro": {
"name": "set stuff conditionally",
"options": {
"enableSmartSources": true,
"query": "| makeresults format=csv data=\"token_name\ndummy\"\n| eval error_clicked = if(\"$click_col$\" == \"ERROR\", $click_val$, \"iNvAlId\")\n| eval warn_clicked = if(\"$click_col$\" == \"WARN\", $click_val$, \"iNvAlId\")\n| eval warning_clicked = if(\"$click_col$\" == \"WARNING\", $click_val$, \"iNvAlId\")\n| eval info_clicked = if(\"$click_col$\" == \"INFO\", $click_val$, \"iNvAlId\")\n",
"queryParameters": {
"earliest": "-24h@h",
"latest": "now"
}
},
"type": "ds.search"
}
},
"layout": {
"globalInputs": [],
"layoutDefinitions": {
"layout_1": {
"options": {
"height": 960,
"width": 1440
},
"structure": [
{
"item": "viz_b4Bxi3gB",
"position": {
"h": 352,
"w": 1112,
"x": 0,
"y": 0
},
"type": "block"
},
{
"item": "viz_zugP9Nmm",
"position": {
"h": 176,
"w": 328,
"x": 1112,
"y": 0
},
"type": "block"
},
{
"item": "viz_o3sdPo7w",
"position": {
"h": 176,
"w": 328,
"x": 1112,
"y": 176
},
"type": "block"
},
{
"item": "viz_o6JLZxMy",
"position": {
"h": 162,
"w": 549,
"x": 0,
"y": 352
},
"type": "block"
},
{
"item": "viz_xM7oEpU3",
"position": {
"h": 162,
"w": 445,
"x": 549,
"y": 352
},
"type": "block"
},
{
"item": "viz_y668z7ad",
"position": {
"h": 162,
"w": 223,
"x": 994,
"y": 352
},
"type": "block"
},
{
"item": "viz_FwYm3SJW",
"position": {
"h": 162,
"w": 223,
"x": 1217,
"y": 352
},
"type": "block"
}
],
"type": "grid"
}
},
"options": {},
"tabs": {
"items": [
{
"label": "New tab",
"layoutId": "layout_1"
}
]
}
},
"expressions": {
"conditions": {
"condition_5dQcfJWD": {
"name": "clicked value greater than 0",
"value": "$click_val$ > 0"
},
"condition_6zVp0DS6": {
"name": "WARN clicked",
"value": "$set stuff conditionally:result.warn_clicked$ != \"iNvAlId\""
},
"condition_BiyxjNkX": {
"name": "a click is performed",
"value": "isSet($click_col$)"
},
"condition_brJLKJTd": {
"name": "ERROR clicked",
"value": "$set stuff conditionally:result.error_clicked$ != \"iNvAlId\""
}
}
}
}Upon launch, a "minimal" layout is shown, including one panel with warning about no search result.
When you click in column chart, layout will change depending on where you click, e.g.,
Play with the demo and see if your desired effects can be achieved. A few pointers.
In short, Dashboard Studio can be strong even in complex interactions, as long as you are willing to adapt to its own feature set. (I am keenly aware of the absence of some desirable features in Simple XML, but the set is smaller and smaller.)
This is how I see the situation: If you are already proficient in Simple XML, and there are some effects that are harder/impossible to achieve in DS, stay with Simple XML. Else it is worth venturing into DS even if sometimes that requires a different way to solve the problem. I have used Simple XML for many years and still have many dashboards there. But my goto for new dashboard today is Dashboard Studio.
From a personal point of view, SimpleXML is preferred over Studio.
Conditional handling is one aspect which Studio does not have which SimpleXML does. I find that token handling in general is still better in SimpleXML. There are also other handlers which are easier to do in SimpleXML, and there is better support for CSS and javascript in SimpleXML. Also, Studio is still being developed so you may find you need to upgrade to the latest version to get some features that you need, whereas they are already in SimpleXML.