Dashboards & Visualizations

How to change font color based on a condition for a particular row using simple xml?

rarangarajanspl
Explorer

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

0 Karma
1 Solution

niketnilay
Legend

@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:

  1. Suffix the cell value which needs to deicide coloring to each of the other fields which need to be colored along with a delimiter. For example | eval field1=field1."|".log_level. I have used foreach command to do this for all fields including log_level.
  2. Using split() eval function split the table cell values into two rows based on delimiter. In the example pipe symbol is the delimiter: |
  3. Use colorPalette with expression in the table format option for each of the 50 fields you have. I have only few fields in the example. Expression allows you to kind of perform eval on table cell values for color formatting.
  4. Use Simple XML CSS extension, that can also be applied using hidden <html> panel with <style> tag, to hide the multivalued field created for cell color using split() function on delimited log_level value.

alt text

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!

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"

View solution in original post

niketnilay
Legend

@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:

  1. Suffix the cell value which needs to deicide coloring to each of the other fields which need to be colored along with a delimiter. For example | eval field1=field1."|".log_level. I have used foreach command to do this for all fields including log_level.
  2. Using split() eval function split the table cell values into two rows based on delimiter. In the example pipe symbol is the delimiter: |
  3. Use colorPalette with expression in the table format option for each of the 50 fields you have. I have only few fields in the example. Expression allows you to kind of perform eval on table cell values for color formatting.
  4. Use Simple XML CSS extension, that can also be applied using hidden <html> panel with <style> tag, to hide the multivalued field created for cell color using split() function on delimited log_level value.

alt text

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!

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"

View solution in original post

Bleepie
Path Finder

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.

Tags (1)
0 Karma

shandr
Path Finder

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 "&lt;&lt;FIELD&gt;&gt;"='&lt;&lt;FIELD&gt;&gt;'."|".hex_color]
| foreach *
[| eval "&lt;&lt;FIELD&gt;&gt;"=split('&lt;&lt;FIELD&gt;&gt;',"|")]
| 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>


0 Karma

Bleepie
Path Finder

I've managed to get it working using LIKE and its wildcard (%search%) e.g LIKE(%DEBUG%).

0 Karma

shandr
Path Finder

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

 

0 Karma

stef_the_choups
New Member

@niketnilay 

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' &gt; 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 &lt; 10,"5",NbKO &lt; 20,"4",NbKO &lt; 30,"3",NbKO &lt; 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 &lt;&lt;FIELD&gt;&gt;='&lt;&lt;FIELD&gt;&gt;'."|".defcon] | foreach * [  eval &lt;&lt;FIELD&gt;&gt;=split('&lt;&lt;FIELD&gt;&gt;',"|") ]</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>
0 Karma

rarangarajanspl
Explorer

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?

niketnilay
Legend

@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

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

anmolpatel
Builder

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:
alt text

Hope this alternative helps.

svarendorff
Engager

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>

0 Karma

svarendorff
Engager

Sorry scratch that I missed the standard functionality.

 

svarendorff_0-1615945492516.png

 

 

0 Karma
.conf21 Now Fully Virtual!
Register for FREE Today!

We've made .conf21 totally virtual and totally FREE! Our completely online experience will run from 10/19 through 10/20 with some additional events, too!