My Dashboard is generating a table with 50+ columns. Based on the field name 'LogLevel', i need to change the font color for that particular row only. In case, LogLevel is 'ERROR' change the font color to red for that row.
I would like this to be done using simple XML. In case of java script, i need to place the js file in Splunk server which is a big process.
Please suggest
@rarangarajansplunk this row color, that too text not background, wont be possible without JS.
Your only alternative to color text for entire row (not background) depending on particular cell without JS would be to convert to html dashboard but that will have loads of downsides as you can not take advantage of SimpleXML and several features of Simple XML dashboards will stop working. HTML dashboard allows JS to be included in the dashboard code but entire dashboard converts to SplunkJS and you would need to code JS afterwards.
If you are ok to do ** Table Row color by a particular Cell value using pure SimpleXML- NO JS Required
** you can try the following example where you will have to write <format>
option for each of the 50 fields (can only be avoided by JS). Following is the approach:
| eval field1=field1."|".log_level
. I have used foreach command to do this for all fields including log_level. |
<html>
panel with <style>
tag, to hide the multivalued field created for cell color using split()
function on delimited log_level value.Following is the Simple XML code with run anywhere example based on Splunk's _internal index where log_level field has three values i.e. INFO, ERROR, WARN
<dashboard>
<label>Table with Simple XML color</label>
<row>
<panel>
<title>Only SimpleXML no JS required</title>
<html>
<style>
#tableRowColorWithoutJS table tbody td div.multivalue-subcell[data-mv-index="1"]{
display: none;
}
</style>
</html>
<table id="tableRowColorWithoutJS">
<title>Color Row by log_level: ERROR INFO and WARN</title>
<search>
<query>index=_internal sourcetype=splunkd
| stats count last(date_hour) as date_hour last(date_minute) as date_minute last(date_second) as date_second last(component) as component by log_level
| foreach * [| eval "<<FIELD>>"='<<FIELD>>'."|".log_level]
| foreach * [| eval "<<FIELD>>"=split('<<FIELD>>',"|")]</query>
<earliest>-24h@h</earliest>
<latest>now</latest>
<sampleRatio>1</sampleRatio>
</search>
<option name="count">20</option>
<option name="dataOverlayMode">none</option>
<option name="drilldown">none</option>
<option name="percentagesRow">false</option>
<option name="rowNumbers">false</option>
<option name="totalsRow">false</option>
<option name="wrap">true</option>
<format type="color" field="date_hour">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
<format type="color" field="date_minute">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
<format type="color" field="date_second">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
<format type="color" field="component">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
<format type="color" field="log_level">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
<format type="color" field="count">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
</table>
</panel>
</row>
</dashboard>
Please change as per your use case!
@rarangarajansplunk this row color, that too text not background, wont be possible without JS.
Your only alternative to color text for entire row (not background) depending on particular cell without JS would be to convert to html dashboard but that will have loads of downsides as you can not take advantage of SimpleXML and several features of Simple XML dashboards will stop working. HTML dashboard allows JS to be included in the dashboard code but entire dashboard converts to SplunkJS and you would need to code JS afterwards.
If you are ok to do ** Table Row color by a particular Cell value using pure SimpleXML- NO JS Required
** you can try the following example where you will have to write <format>
option for each of the 50 fields (can only be avoided by JS). Following is the approach:
| eval field1=field1."|".log_level
. I have used foreach command to do this for all fields including log_level. |
<html>
panel with <style>
tag, to hide the multivalued field created for cell color using split()
function on delimited log_level value.Following is the Simple XML code with run anywhere example based on Splunk's _internal index where log_level field has three values i.e. INFO, ERROR, WARN
<dashboard>
<label>Table with Simple XML color</label>
<row>
<panel>
<title>Only SimpleXML no JS required</title>
<html>
<style>
#tableRowColorWithoutJS table tbody td div.multivalue-subcell[data-mv-index="1"]{
display: none;
}
</style>
</html>
<table id="tableRowColorWithoutJS">
<title>Color Row by log_level: ERROR INFO and WARN</title>
<search>
<query>index=_internal sourcetype=splunkd
| stats count last(date_hour) as date_hour last(date_minute) as date_minute last(date_second) as date_second last(component) as component by log_level
| foreach * [| eval "<<FIELD>>"='<<FIELD>>'."|".log_level]
| foreach * [| eval "<<FIELD>>"=split('<<FIELD>>',"|")]</query>
<earliest>-24h@h</earliest>
<latest>now</latest>
<sampleRatio>1</sampleRatio>
</search>
<option name="count">20</option>
<option name="dataOverlayMode">none</option>
<option name="drilldown">none</option>
<option name="percentagesRow">false</option>
<option name="rowNumbers">false</option>
<option name="totalsRow">false</option>
<option name="wrap">true</option>
<format type="color" field="date_hour">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
<format type="color" field="date_minute">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
<format type="color" field="date_second">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
<format type="color" field="component">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
<format type="color" field="log_level">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
<format type="color" field="count">
<colorPalette type="expression">case (match(value,"ERROR"), "#DC4E41",match(value,"WARN"), "#F8BE34",match(value,"INFO"),"#53A051",true(),"#C3CBD4")</colorPalette>
</format>
</table>
</panel>
</row>
</dashboard>
Please change as per your use case!
How would I edit this to not match the value precisely but allow to change colors if the value is in the field? I have a table that has the _raw field with more than just ERROR, WARN & INFO so I need to create a expression where I look for any occurance rather than an exact match. I tried to play with conditional functions but no success so far.
You can use match() to scan all of _raw on every event. If you look for "WARN" then it will find "WARNING".
If I was doing this I would instead give my sourcetype/search a field called log_level (in case _raw is long).
<dashboard>
<label>test_conditional_color</label>
<row>
<panel>
<html>
<style>
#tableRowColorWithoutJS table tbody td div.multivalue-subcell[data-mv-index="1"]{
display: none;
}
</style>
</html>
<table id="tableRowColorWithoutJS">
<title>We can color columnA based on whichever Log Level we see in columnB </title>
<search>
<query>
index=_internal log_level!="INFO"
| fields index sourcetype host _raw
| streamstats count as id
| table id a_new_field* *
| eval hex_color = case(match(_raw,"ERROR"),"red", match(_raw,"INFO"),"green", true(),"amber")
| foreach * hex_color
[| eval "<<FIELD>>"='<<FIELD>>'."|".hex_color]
| foreach *
[| eval "<<FIELD>>"=split('<<FIELD>>',"|")]
| fields index sourcetype host _raw
</query>
<earliest>-1h</earliest>
<latest>now</latest>
</search>
<option name="drilldown">none</option>
<format type="color" field="host">
<colorPalette type="expression">case (match(value,"red"),"#DC4E41", match(value,"green"),"#53a051", true(),"#f4a747")</colorPalette>
</format>
</table>
</panel>
</row>
</dashboard>
I've managed to get it working using LIKE and its wildcard (%search%) e.g LIKE(%DEBUG%).
Clever solution. Thank-you.
Tiny bug on this line:
| foreach * [| eval "<<FIELD>>"='<<FIELD>>'."|".log_level]
Should be:
| foreach * log_level [| eval "<<FIELD>>"='<<FIELD>>'."|".log_level]
Or each field that is being processed after log_level field (alphanumerically) is being given log_level 2 times.
And if you notice a field value is being given a comma (',') instead of a pipe ('|') then rename it before foreach.
| rename latest_time as latest_time2
I tried your solution : it's ok except for the hide multivalue simple XML extension.
My dashboard displays the "log_level" values anyway (called "defcon")
I'm using Splunk 7.3.3. The dashboard has multiple panels
any idea about the reason ?
<panel depends="$panel_show100KO$">
<title>Liste 100% KO </title>
<html>
<style>
#tableRowColor100KO table tbody td div.multivalue-subcell[data-mv-index="1"] { display: none; }
</style>
</html>
<table id="tableRowColor100KO">
<search>
<progress>
<condition match="'job.resultCount' > 0">
<set token="panel_show100KO">true</set>
</condition>
<condition>
<unset token="panel_show100KO"></unset>
</condition>
</progress>
<query>index="XXXXXXXX" host="XXXXXXXX" (...) | eval NbKO=total-KOMetier-NbOK,defcon=case(NbKO < 10,"5",NbKO < 20,"4",NbKO < 30,"3",NbKO < 40,"2",true(),"1") | table defcon,categorie,numero_amc,libelle_amc,id_ws,end_point,total,NbKO | uniq | where total=NbKO | sort -total | foreach * [ eval <<FIELD>>='<<FIELD>>'."|".defcon] | foreach * [ eval <<FIELD>>=split('<<FIELD>>',"|") ]</query>
<earliest>-8h@m</earliest>
<latest>now</latest>
<sampleRatio>1</sampleRatio>
<refresh>60s</refresh>
<refreshType>delay</refreshType>
</search>
<option name="count">10</option>
<option name="dataOverlayMode">none</option>
<option name="drilldown">none</option>
<option name="percentagesRow">false</option>
<option name="refresh.display">progressbar</option>
<option name="rowNumbers">false</option>
<option name="totalsRow">false</option>
<option name="wrap">true</option>
<format type="color" field="defcon">
<colorPalette type="expression">case(match(value,"1"),"0x555",match(value,"2"),"0xdc4e41",match(value,"3"),"0xf1813f",match(value,"4"),"0xf8be34",match(value,"5"),"0x53a051",true(),white)</colorPalette>
</format>
<format type="color" field="categorie">
<colorPalette type="expression">case(match(value,"1"),"0x555",match(value,"2"),"0xdc4e41",match(value,"3"),"0xf1813f",match(value,"4"),"0xf8be34",match(value,"5"),"0x53a051",true(),white)</colorPalette>
</format>
<format type="color" field="numero_amc">
<colorPalette type="expression">case(match(value,"1"),"0x555",match(value,"2"),"0xdc4e41",match(value,"3"),"0xf1813f",match(value,"4"),"0xf8be34",match(value,"5"),"0x53a051",true(),white)</colorPalette>
</format>
<format type="color" field="libelle_amc">
<colorPalette type="expression">case(match(value,"1"),"0x555",match(value,"2"),"0xdc4e41",match(value,"3"),"0xf1813f",match(value,"4"),"0xf8be34",match(value,"5"),"0x53a051",true(),white)</colorPalette>
</format>
<format type="color" field="id_ws">
<colorPalette type="expression">case(true(),"#d234eb")</colorPalette>
</format>
<format type="color" field="end_point">
<colorPalette type="expression">case(true(),"#d234eb")</colorPalette>
</format>
<format type="color" field="total">
<colorPalette type="expression">case(true(),"#d234eb")</colorPalette>
</format>
<format type="color" field="NbKO">
<colorPalette type="expression">case(true(),"#d234eb")</colorPalette>
</format>
</table>
</panel>
Thank You very much for the code and explaining in details! I'll use this for time being.
I am open use java script as well in longer run. Could you suggest on the same?
@rarangarajansplunk you can try table row highlighting example from Splunk Dashboard Examples app : https://splunkbase.splunk.com/app/1603/
However from Splunk 6.6+ version you need setTimeout inside render() function. Refer to one of my older answers for the same.
https://answers.splunk.com/answers/614788/splunk-dashboard-examples-table-row-highlighting-b.html
Without JS + CSS, i've not achieved this before. Though here is an alternative that will work.
- Create a new column which sets the range by the log level. Once you've set the values you can set the range to colour code the row
See the below code:
<row>
<panel>
<title>Range colour</title>
<table>
<search>
<query>| makeresults
| eval _raw = "desc, range
ERROR, 4
WARN, 3
OK, 0"
| multikv forceheader=1
| table desc range</query>
<earliest>-24h@h</earliest>
<latest>now</latest>
<sampleRatio>1</sampleRatio>
</search>
<option name="count">50</option>
<option name="dataOverlayMode">none</option>
<option name="drilldown">none</option>
<option name="percentagesRow">false</option>
<option name="rowNumbers">false</option>
<option name="totalsRow">false</option>
<option name="wrap">true</option>
<format type="color" field="range">
<colorPalette type="list">[#53A051,#F8BE34,#EC9960,#DC4E41]</colorPalette>
<scale type="threshold">1,3,4</scale>
</format>
</table>
</panel>
</row>
Results:
Hope this alternative helps.
Hi, could this be done in a range?
e.g. diskpercentage 0 to 10 - Red, 10 to 20 - Amber or 20 to 100 - Green
<colorPalette type="expression">case(match(value,"1"),"#FF0000",match(value,"2"),"0xdc4e41",match(value,"3"),"0xf1813f",match(value,"4"),"0xf8be34",match(value,"5"),"0x53a051",true(),white)</colorPalette>
Sorry scratch that I missed the standard functionality.