Dashboards & Visualizations

How can I get the Table cell colorization rendering for every cell except the ones I don't want?

leesahic
Engager

I am using the example from the Splunk Dashboard Examples for Table Cell Highlighting, I'm using Splunk 7.0.2. I am creating a chart where only one of the column names is known ahead of time, "testcase". I need to color cells for every cell except those in the testcase column. Per the example, it looks as though the canRender function returns true for any cell which requires rendering, i.e. for any cell which may need color added. I have tried coding the canRender function to return true if cell.field for any field other than the testcase field, but in all my attempts, the render function is still invoked for every cell, including the testcase field. Here are two examples of what I have tried:

        canRender: function(cell) {
            console.log("canRender:  cell.field=" + cell.field);
            // Enable this custom cell renderer for any field except the test case field
            var testpattern = new RegExp ('test', 'i');

            return _(!testpattern.test(cell.field));
        },

I have also tried:

        canRender: function(cell) {
            console.log("canRender:  cell.field=" + cell.field);
            // Enable this custom cell renderer for any field except the test case field

            return _(!(['testcase']).contains(cell.field));
        },

I have worked around this by putting code in the render function to add the cell.value as a string for the testcase field, but if I understand how this is supposed to work, then I should not have to do that.

0 Karma
1 Solution

niketn
Legend

@leesahic, Please try the following approach where I am filtering only the required fields using the following JavaScript and then pass on the filtered column list as array of string. In the example I have used _time as the filed not be included for custom cell rendering.

myResults.on("data", function(){
    allFields=myResults.data().fields;
    filteredFields=allFields.filter(filterFields);
    console.log("Filtered Fields:",filteredFields);
});
function filterFields(field) {
    return field !== "_time";
}

alt text

Following is the Simple XML Dashboard code:

<form script="table_cell_render_all_cells.js">
  <label>Custom Cell Render to all cells except _time</label>
  <fieldset submitButton="false">
    <input type="time" token="tokTime" searchWhenChanged="true">
      <label>Select Time</label>
      <default>
        <earliest>-24h@h</earliest>
        <latest>now</latest>
      </default>
    </input>
  </fieldset>
  <row>
    <panel depends="$alaysHideCSS$">
      <html>
        <style>
          #highlight td {
              background-color: #c1ffc3 !important;
          }
          */
          #highlight td.range-low {
              color: #C0D9D9;
          }
          #highlight td.range-elevated {
              background-color: #ffc57a !important;
              font-weight: bold;
          }
          #highlight td.range-severe {
              background-color: #d59392 !important;
              font-weight: bold;
          }          
        </style>
      </html>
    </panel>
    <panel>
      <table id="highlight">
        <search id="myTableSearch">
          <query>index=_internal sourcetype=splunkd
| timechart count by component useother=f usenull=f</query>
          <earliest>$tokTime.earliest$</earliest>
          <latest>$tokTime.latest$</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>
</form>

Following is the JavaScript code for table_cell_render_all_cells.js

require([
    "underscore",
    "jquery",
    "splunkjs/mvc",
    "splunkjs/mvc/searchmanager",
    "splunkjs/mvc/tableview",
    "splunkjs/mvc/simplexml/ready!"
], function(_, $, mvc, SearchManager, TableView) {

    var mySearch = splunkjs.mvc.Components.getInstance("myTableSearch");
    var myResults = mySearch.data("results", {count:0});
    var allFields,filteredFields;
    myResults.on("data", function(){
        allFields=myResults.data().fields;
        filteredFields=allFields.filter(filterFields);
        console.log("Filtered Fields:",filteredFields);
    });
    function filterFields(field) {
        return field !== "_time";
    }
    // Row Coloring Example with custom, client-side range interpretation
    var CustomRangeRenderer = TableView.BaseCellRenderer.extend({
        canRender: function(cell) {
            // Enable this custom cell renderer for all fields except _time
            return _(filteredFields).contains(cell.field);
        },
        render: function($td, cell) {
            // Add a class to the cell based on the returned value
            var value = parseInt(cell.value);

            // Apply interpretation based on count of errors per _time for each field
            if(cell.field !== "_time"){
                if (value >= 500) {
                    $td.addClass("range-cell").addClass("range-severe");
                }
                else if (value >= 200 && value < 500) {
                    $td.addClass("range-cell").addClass("range-elevated");
                }
                else if (value < 200) {
                    $td.addClass("range-cell").addClass("range-low");
                }
                // Update the cell content
                $td.text(value).addClass("numeric");
            }
        }
    });
    mvc.Components.get("highlight").getVisualization(function(tableView) {
        // Add custom cell renderer, the table will re-render automatically.
        tableView.addCellRenderer(new CustomRangeRenderer());
    }); 
});
____________________________________________
| makeresults | eval message= "Happy Splunking!!!"

View solution in original post

0 Karma

niketn
Legend

@leesahic, Please try the following approach where I am filtering only the required fields using the following JavaScript and then pass on the filtered column list as array of string. In the example I have used _time as the filed not be included for custom cell rendering.

myResults.on("data", function(){
    allFields=myResults.data().fields;
    filteredFields=allFields.filter(filterFields);
    console.log("Filtered Fields:",filteredFields);
});
function filterFields(field) {
    return field !== "_time";
}

alt text

Following is the Simple XML Dashboard code:

<form script="table_cell_render_all_cells.js">
  <label>Custom Cell Render to all cells except _time</label>
  <fieldset submitButton="false">
    <input type="time" token="tokTime" searchWhenChanged="true">
      <label>Select Time</label>
      <default>
        <earliest>-24h@h</earliest>
        <latest>now</latest>
      </default>
    </input>
  </fieldset>
  <row>
    <panel depends="$alaysHideCSS$">
      <html>
        <style>
          #highlight td {
              background-color: #c1ffc3 !important;
          }
          */
          #highlight td.range-low {
              color: #C0D9D9;
          }
          #highlight td.range-elevated {
              background-color: #ffc57a !important;
              font-weight: bold;
          }
          #highlight td.range-severe {
              background-color: #d59392 !important;
              font-weight: bold;
          }          
        </style>
      </html>
    </panel>
    <panel>
      <table id="highlight">
        <search id="myTableSearch">
          <query>index=_internal sourcetype=splunkd
| timechart count by component useother=f usenull=f</query>
          <earliest>$tokTime.earliest$</earliest>
          <latest>$tokTime.latest$</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>
</form>

Following is the JavaScript code for table_cell_render_all_cells.js

require([
    "underscore",
    "jquery",
    "splunkjs/mvc",
    "splunkjs/mvc/searchmanager",
    "splunkjs/mvc/tableview",
    "splunkjs/mvc/simplexml/ready!"
], function(_, $, mvc, SearchManager, TableView) {

    var mySearch = splunkjs.mvc.Components.getInstance("myTableSearch");
    var myResults = mySearch.data("results", {count:0});
    var allFields,filteredFields;
    myResults.on("data", function(){
        allFields=myResults.data().fields;
        filteredFields=allFields.filter(filterFields);
        console.log("Filtered Fields:",filteredFields);
    });
    function filterFields(field) {
        return field !== "_time";
    }
    // Row Coloring Example with custom, client-side range interpretation
    var CustomRangeRenderer = TableView.BaseCellRenderer.extend({
        canRender: function(cell) {
            // Enable this custom cell renderer for all fields except _time
            return _(filteredFields).contains(cell.field);
        },
        render: function($td, cell) {
            // Add a class to the cell based on the returned value
            var value = parseInt(cell.value);

            // Apply interpretation based on count of errors per _time for each field
            if(cell.field !== "_time"){
                if (value >= 500) {
                    $td.addClass("range-cell").addClass("range-severe");
                }
                else if (value >= 200 && value < 500) {
                    $td.addClass("range-cell").addClass("range-elevated");
                }
                else if (value < 200) {
                    $td.addClass("range-cell").addClass("range-low");
                }
                // Update the cell content
                $td.text(value).addClass("numeric");
            }
        }
    });
    mvc.Components.get("highlight").getVisualization(function(tableView) {
        // Add custom cell renderer, the table will re-render automatically.
        tableView.addCellRenderer(new CustomRangeRenderer());
    }); 
});
____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

lim2
Communicator

Hi @niketn Looked at simple_xml_examples  splunk-dashboard-examples_824.tgz from 3/9/2022 but did not find the dependent script for table_cell_render_all_cells.js Where could we download the 

required scripts in splunkjs ?

 Thanks.

Tags (1)
0 Karma

leesahic
Engager

Can you explain to me how this is different from what my code does:

  1. AFAIK canRender in both our solutions returns true for each individual cell that needs colorization, false for the cell to not colorize, so what exactly is the difference?
  2. render still has to have a condition to operate only on the cells other then '_time'
  3. Why is the _time field colored green?
0 Karma

niketn
Legend

@leesahic, myResults.on("data", function() has been used to get all field names and then filter _time. Check out Console Logs. Then canRender gets all fields except _time.

_time is green because default Background Color has been overridden as green through CSS override.

       #highlight td {
           background-color: #c1ffc3 !important;
       }

You can remove this as all remaining rows except time will fall into either one of the three categories i.e. low, elevated or severe. Hence, background color will always be applied for remaining fields.
Sorry for the delay in my response. Please try out and confirm!

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

niketn
Legend

@leesahic please confirm whether the solution worked for you or not.

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

niketn
Legend

@leesahic, what are the fields other than test case? Do you know how many fields you will have if not their names? Do you intend to color specific cells for each field or do you need to color each row based on cell value?

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

leesahic
Engager

I need to color all fields except the testcase field. I do not know their names or how many there will be for any specific query.

0 Karma

niketn
Legend

@leesahic, can you add some sample for these fields other than testcase? Also what is the query generating these fields? If you don't know how many there can be is there still any max value like 10, 100, 1000, 10000 or more?

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

leesahic
Engager

There would typically be more than 10 and less than 100 columns. Other than testcase, the columns are labelled by kitname, so for example, the columns returned would be testcase, KitA, KitB, KitC, ... where kitname is dynamic. This query is counting the number of test failures by testcase for each kitname. The colorization I have implemented colors any kit failure count > 0 as red, otherwise green.

Query is as follows:
index="owr-build" sourcetype="owr:precheck" test-case{@name}="$testcase_token$"
| rename test-case{@result} as result
| rename test-case{@name} as testcase
| eval testcase=lower(testcase)
| eval resultval=case(result="Failure", 1, 1=1, 0)
| join id [search index=owr-build sourcetype=owr:build buildduration=* status!=incomplete platformfamily="$platformfamily_token$" platformconfig="$platformconfig_token$" ]
| replace "" with "Unknown" in platformfamily
| extract_test_case_ingredient_and_test(test-case{@name})
| dedup kitname testcase resultval
| chart count(resultval) over testcase by kitname limit=0

0 Karma

niketn
Legend

@leesahic, if it was limited countable fields I would have recommended the following approach using Simple XML chart configuration with Dynamic fields with tokens.

https://answers.splunk.com/answers/615411/how-to-format-table-range-per-week-automatically.html

But definitely your case is complicated. Let me see if I can find some time to figure out something for your issue.

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

leesahic
Engager

Perhaps there is something that I don't understand. I see from debug output that canRender is called for every column field, which is expected. Per the example from Splunk Dashboard Examples for Table Cell Highlighting, it returns true if the field should be rendered, otherwise false.

My code returns true for any field that is not the testcase field.

However, I had to add code in the render function to update the testcase field value; without this the cell ends up blank. Here is the complete working code:
require([
'underscore',
'jquery',
'splunkjs/mvc',
'splunkjs/mvc/tableview',
'splunkjs/mvc/simplexml/ready!'
], function(_, $, mvc, TableView) {

     // Row Coloring Example with custom, client-side range interpretation

    var CustomRangeRenderer = TableView.BaseCellRenderer.extend({
        canRender: function(cell) {
            console.log("canRender:  cell.field=" + cell.field);
            // Enable this custom cell renderer for any field except the test case field
            var testpattern = new RegExp ('test', 'i');

            return _(!testpattern.test(cell.field));
        },
        render: function($td, cell) {
            // Add a class to the cell based on the returned value
            var testpattern = new RegExp ('test', 'i');
            if (testpattern.test(cell.field))
            {
                // Update the cell content
                $td.text(cell.value).addClass('string');
            }
            else {
                var value = parseInt(cell.value);
                if (value >= 1) {
                    $td.addClass('range-cell').addClass('range-fail');
                }
                else {
                    $td.addClass('range-cell').addClass('range-pass');
                }

                // Update the cell content
                $td.text(' ').addClass('string');
            }
        }
    });

    mvc.Components.get('highlight').getVisualization(function(tableView) {
        // Add custom cell renderer, the table will re-render automatically.
        tableView.addCellRenderer(new CustomRangeRenderer());
    });

});
0 Karma
Get Updates on the Splunk Community!

Thanks for the Memories! Splunk University, .conf24, and Community Connections

Thank you to everyone in the Splunk Community who joined us for .conf24 – starting with Splunk University and ...

.conf24 | Day 0

Hello Splunk Community! My name is Chris, and I'm based in Canberra, Australia's capital, and I travelled for ...

Enhance Security Visibility with Splunk Enterprise Security 7.1 through Threat ...

 (view in My Videos)Struggling with alert fatigue, lack of context, and prioritization around security ...