Dashboards & Visualizations

In a Splunk dashboard, how do you make the cell coloring range different for each row?

asimagu
Builder

hi guys,

I have been trying to color a table in a Splunk dashboard, but I need the color ranges to be different for each row:

Example:

  Context     Field 1        Field 2       Field 3
   A             8               -4          9
   B             8               -4          9
   C             8               -4          9

For row where column Context is A: color green when the value is > 5 , red if the value < -5
For row where column Context is B: color blue when the value is > 5, yellow if the value < -5
For row where column Context is C: color orange when the value is > 5, pink if the value < -5

So, I tested with Javascript something that for a normal HTML page works. However, for the Splunk results table, it does not work.

what am I missing??

In Splunk, I built my SimpleXML table, then converted to HTML and inserted my Javascript code.

For an HTML page, this sample I built works:

<head>
<title>Sample code </title>
<script>
    function start() {

        var body  = document.getElementsByTagName("body")[0];
        var table = body.getElementsByClassName("table")[0];
        var tbody = table.getElementsByTagName('tbody')[0];

        for (var j=0; j<3; j++){

            var rows = tbody.getElementsByTagName('tr')[j];
            var cells = rows.getElementsByTagName('td');

            for (var i=0, len=cells.length; i<len; i++){

                if (cells[0].innerHTML == "A"){

                    if (parseInt(cells[i].innerHTML,10) > 5){
                        cells[i].style.backgroundColor = 'green';
                    }
                    else if (parseInt(cells[i].innerHTML,10) < -5){
                        cells[i].style.backgroundColor = 'red';
                    }
                }
                if (cells[0].innerHTML == "B"){

                    if (parseInt(cells[i].innerHTML,10) > 5){
                        cells[i].style.backgroundColor = 'blue';
                    }
                    else if (parseInt(cells[i].innerHTML,10) < -5){
                        cells[i].style.backgroundColor = 'yellow';
                    }
                }
                if (cells[0].innerHTML == "C"){

                    if (parseInt(cells[i].innerHTML,10) > 5){
                        cells[i].style.backgroundColor = 'orange';
                    }
                    else if (parseInt(cells[i].innerHTML,10) < -5){
                        cells[i].style.backgroundColor = 'pink';
                    }
                }

            }
        }       

    }
</script>
</head>
<body onload="start()">
</br></br></br></br></br>
<table id="tableID" class="table" border="2" style="padding: 0.2em 0.5em" align="center">
    <thead>
        <tr>
            <th>Context</th>
            <th>Field 1</th>
            <th>Field 2</th>
            <th>Field 3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td style="font-size: 50pt">A</td>
            <td style="font-size: 50pt">8</td>
            <td style="font-size: 50pt">-4</td>
            <td style="font-size: 50pt">-9</td>
        </tr>
        <tr>
            <td style="font-size: 50pt">B</td>
            <td style="font-size: 50pt">8</td>
            <td style="font-size: 50pt">-4</td>
            <td style="font-size: 50pt">-9</td>
        </tr>
        <tr>
            <td style="font-size: 50pt">C</td>
            <td style="font-size: 50pt">8</td>
            <td style="font-size: 50pt">-4</td>
            <td style="font-size: 50pt">-9</td>
        </tr>
    </tbody>
</table>
</body>
</html>
0 Karma
1 Solution

niketn
Legend

@asimagu based on the answer by our Trust Fez bearer @kamlesh_vaghela please find below an answer specific to your query.

Step 1) Prefix all Field values with the Context value with pipe and delimeter character (or any other delimeter of your choice except hyphen which is same as minus sign as per your data.). First table displays the same result (it does not apply range color by context as it is only for example of data for customer table cell rendering.)

Step 2) Give your table a specific id in Simple XML i.e. id="tableWithColorBasedOnContext", in the run anywhere search attached. PS: The first table in the example does not have table id so range color by context does not apply.

Step 3) Add Customer table Cell renderer and pull three required Field cells i.e. Field1, Field2 and Field3 in the above example. Apply custom JS section to split Context and Value for each field using delimeter (i.e. pipe | in the example).

Step 4) Add custom CSS Style class based on the context and range i.e. range-green, range-red etc.

Step 5) Create CSS Style section to apply CSS Style override for table with specific background color class. For example:

      #tableWithColorBasedOnContext .range-green{
        background:green;
      }

alt text

Please try out the following Run anywhere example and confirm:

1) Run anywhere Simple XML Dashboard Code

<dashboard script="table_row_color_by_context_and_range.js">
  <label>Table Color by Context</label>
  <row>
    <panel>
      <title>Table without Color Based on Context</title>
      <table>
        <search>
          <query>| makeresults 
| eval data="A,8,-6,0;B,6,-2,-9;C,0,7,-8" 
| makemv data delim=";" 
| mvexpand data 
| makemv data delim="," 
| eval Context=mvindex(data,0),Field1=mvindex(data,1),Field2=mvindex(data,2),Field3=mvindex(data,3) 
| table Context Field*
| foreach Field1, Field2, Field3 [| eval <<FIELD>>=Context."|".<<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>
      </table>
    </panel>
  </row>
  <row>
    <panel>
      <title>Table with Color Based on Context</title>
      <table id="tableWithColorBasedOnContext">
        <search>
          <query>| makeresults 
| eval data="A,8,-6,0;B,6,-2,-9;C,0,7,-8"
| makemv data delim=";" 
| mvexpand data 
| makemv data delim="," 
| eval Context=mvindex(data,0),Field1=mvindex(data,1),Field2=mvindex(data,2),Field3=mvindex(data,3) 
| table Context Field*
| foreach Field1, Field2, Field3 [| eval <<FIELD>>=Context."|".<<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>
      </table>
      <html depends="$alwaysHideStyleCSS$">
        <style>
          #tableWithColorBasedOnContext .range-green{
            background:green;
          }
          #tableWithColorBasedOnContext .range-red{
            background:red;
          }
          #tableWithColorBasedOnContext .range-blue{
            background:lightblue;
          }
          #tableWithColorBasedOnContext .range-yellow{
            background:yellow;
          }
          #tableWithColorBasedOnContext .range-orange{
            background:orange;
          }
          #tableWithColorBasedOnContext .range-pink{
            background:pink;
          }
        </style>
      </html>
    </panel>
  </row>  
</dashboard>

2) JavaScript file table_row_color_by_context_and_range.js

To be put under your Splunk app's appserver/static folder. (PS: You may need bump, refresh, restart of your Splunk instance depending on the need. Also, you may be required to clean your Internet Browser's history for Static file changes to reflect properly.)

require([
    'underscore',
    'jquery',
    'splunkjs/mvc',
    'splunkjs/mvc/tableview',
    'splunkjs/mvc/simplexml/ready!'
], function (_, $, mvc, TableView) {
    console.log("Script Started");
    var CustomRangeRenderer = TableView.BaseCellRenderer.extend({
        canRender: function (cell) {
            console.log("Starting Custom Renderer");
            return _(['Field1', 'Field2', 'Field3']).contains(cell.field);
        },
        render: function ($td, cell) {
            var context = cell.value.split("|")[0];
            var value = parseInt(cell.value.split("|")[1]);


            if (context == "A") {
                if (value > 5) {
                    $td.addClass('range-green');
                } else if (value < -5) {
                    $td.addClass('range-red');
                }
            }

            if (context == "B") {
                if (value > 5) {
                    $td.addClass('range-blue');
                } else if (value < -5) {
                    $td.addClass('range-yellow');
                }
            }

            if (context == "C") {
                if (value > 5) {
                    $td.addClass('range-orange');
                } else if (value < -5) {
                    $td.addClass('range-pink');
                }
            }
            $td.text(value).addClass('numeric');
        }
    });

    mvc.Components.get('tableWithColorBasedOnContext').getVisualization(function (tableView) {
        tableView.addCellRenderer(new CustomRangeRenderer());
    });
});
____________________________________________
| makeresults | eval message= "Happy Splunking!!!"

View solution in original post

niketn
Legend

@asimagu based on the answer by our Trust Fez bearer @kamlesh_vaghela please find below an answer specific to your query.

Step 1) Prefix all Field values with the Context value with pipe and delimeter character (or any other delimeter of your choice except hyphen which is same as minus sign as per your data.). First table displays the same result (it does not apply range color by context as it is only for example of data for customer table cell rendering.)

Step 2) Give your table a specific id in Simple XML i.e. id="tableWithColorBasedOnContext", in the run anywhere search attached. PS: The first table in the example does not have table id so range color by context does not apply.

Step 3) Add Customer table Cell renderer and pull three required Field cells i.e. Field1, Field2 and Field3 in the above example. Apply custom JS section to split Context and Value for each field using delimeter (i.e. pipe | in the example).

Step 4) Add custom CSS Style class based on the context and range i.e. range-green, range-red etc.

Step 5) Create CSS Style section to apply CSS Style override for table with specific background color class. For example:

      #tableWithColorBasedOnContext .range-green{
        background:green;
      }

alt text

Please try out the following Run anywhere example and confirm:

1) Run anywhere Simple XML Dashboard Code

<dashboard script="table_row_color_by_context_and_range.js">
  <label>Table Color by Context</label>
  <row>
    <panel>
      <title>Table without Color Based on Context</title>
      <table>
        <search>
          <query>| makeresults 
| eval data="A,8,-6,0;B,6,-2,-9;C,0,7,-8" 
| makemv data delim=";" 
| mvexpand data 
| makemv data delim="," 
| eval Context=mvindex(data,0),Field1=mvindex(data,1),Field2=mvindex(data,2),Field3=mvindex(data,3) 
| table Context Field*
| foreach Field1, Field2, Field3 [| eval <<FIELD>>=Context."|".<<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>
      </table>
    </panel>
  </row>
  <row>
    <panel>
      <title>Table with Color Based on Context</title>
      <table id="tableWithColorBasedOnContext">
        <search>
          <query>| makeresults 
| eval data="A,8,-6,0;B,6,-2,-9;C,0,7,-8"
| makemv data delim=";" 
| mvexpand data 
| makemv data delim="," 
| eval Context=mvindex(data,0),Field1=mvindex(data,1),Field2=mvindex(data,2),Field3=mvindex(data,3) 
| table Context Field*
| foreach Field1, Field2, Field3 [| eval <<FIELD>>=Context."|".<<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>
      </table>
      <html depends="$alwaysHideStyleCSS$">
        <style>
          #tableWithColorBasedOnContext .range-green{
            background:green;
          }
          #tableWithColorBasedOnContext .range-red{
            background:red;
          }
          #tableWithColorBasedOnContext .range-blue{
            background:lightblue;
          }
          #tableWithColorBasedOnContext .range-yellow{
            background:yellow;
          }
          #tableWithColorBasedOnContext .range-orange{
            background:orange;
          }
          #tableWithColorBasedOnContext .range-pink{
            background:pink;
          }
        </style>
      </html>
    </panel>
  </row>  
</dashboard>

2) JavaScript file table_row_color_by_context_and_range.js

To be put under your Splunk app's appserver/static folder. (PS: You may need bump, refresh, restart of your Splunk instance depending on the need. Also, you may be required to clean your Internet Browser's history for Static file changes to reflect properly.)

require([
    'underscore',
    'jquery',
    'splunkjs/mvc',
    'splunkjs/mvc/tableview',
    'splunkjs/mvc/simplexml/ready!'
], function (_, $, mvc, TableView) {
    console.log("Script Started");
    var CustomRangeRenderer = TableView.BaseCellRenderer.extend({
        canRender: function (cell) {
            console.log("Starting Custom Renderer");
            return _(['Field1', 'Field2', 'Field3']).contains(cell.field);
        },
        render: function ($td, cell) {
            var context = cell.value.split("|")[0];
            var value = parseInt(cell.value.split("|")[1]);


            if (context == "A") {
                if (value > 5) {
                    $td.addClass('range-green');
                } else if (value < -5) {
                    $td.addClass('range-red');
                }
            }

            if (context == "B") {
                if (value > 5) {
                    $td.addClass('range-blue');
                } else if (value < -5) {
                    $td.addClass('range-yellow');
                }
            }

            if (context == "C") {
                if (value > 5) {
                    $td.addClass('range-orange');
                } else if (value < -5) {
                    $td.addClass('range-pink');
                }
            }
            $td.text(value).addClass('numeric');
        }
    });

    mvc.Components.get('tableWithColorBasedOnContext').getVisualization(function (tableView) {
        tableView.addCellRenderer(new CustomRangeRenderer());
    });
});
____________________________________________
| makeresults | eval message= "Happy Splunking!!!"

asimagu
Builder

it works like a charm! thanks so much @niketnilay

0 Karma

asimagu
Builder

@niketnilay is there any way of getting all the fields without hardcoding the names in the javascript?? something like return _(['*']).contains(cell.field); for line 12 in the script

0 Karma

niketn
Legend

@asimagu refer to one of my older answers: https://answers.splunk.com/answers/618930/how-can-i-get-the-table-cell-colorization-renderin-1.html

It uses SearchManager from SplunkJS stack to get the list of fields returned and filters out unwanted fields (in the example it was _time but in your case it will be Context).

Alternatively, you can use an independent search in your dashboard to get all the field names and assign the list of comma separated field names as token which you can access in Splunk JS using Token Manger.

Please try out and confirm if you need assistance with any of the approach.

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

asimagu
Builder

thanks a lot @niketnilay !! I got it working!

pramit46
Contributor

@asimagu,

There is a simpler way you can do it. I suggest you form your table first using a normal search text box (not in the dashboard). Then use the individual cell formatting option to color the column cells based on its value. In the screenshot, I used ranges to decide the color.

Then, if you are satisfied with the colors of all your cells, simply save it as a 'dashboard panel'.

Of course there are other ways to achieve this using CSS and javascript, but if this gets our job done, then I would say let's avoid those many lines of code.

Let me know if this helps.

alt text

0 Karma

asimagu
Builder

@pramit46 each row should have a different condition for the colours. the default splunk does not provide this

0 Karma
Get Updates on the Splunk Community!

Extending Observability Content to Splunk Cloud

Register to join us !   In this Extending Observability Content to Splunk Cloud Tech Talk, you'll see how to ...

What's new in Splunk Cloud Platform 9.1.2312?

Hi Splunky people! We are excited to share the newest updates in Splunk Cloud Platform 9.1.2312! Analysts can ...

What’s New in Splunk Security Essentials 3.8.0?

Splunk Security Essentials (SSE) is an app that can amplify the power of your existing Splunk Cloud Platform, ...