Splunk Search

How to change color of row after column has a certain value?

bmendez0428
Explorer

I'm somewhat new to Splunk.

I have a dashboard displaying a table with data. I have code that fills in the columns with 4 different values.
For example, the NA values underneath the column(ex QA4, QA5, PVE) should cause the whole row to have a red outline in the corresponding boxes.
The green checkmark comes from a DB and the value that causes that is "low", yellow icon is "moderate", and the red circle is caused by a "severe" value from the table. How can I get the "NA" to change the whole row to a red outline?
With CSS/Javascript?

alt text

0 Karma
1 Solution

niketn
Legend

@bmendez0428 please use the following run anywhere example on similar lines as per your question. It gets the ERROR, INFO and WARN log levels for Splunk's _internal logs and converts the range of count of each over time to SLAs i.e. low, moderate and severe. Whenever any row has a column with NA, it adds a red border to the same.

PS: I have extended the DARK mode customer table rendering for this example. So if you are on more recent versions of Splunk i.e. 7.x+ , you can take advantage of the Dark Mode for as your dashboard theme.

alt text

Following is the run anywhere Simple XML Code:

<form script="table_row_highlighting_with_icons.js">
  <label>Table with icon and NA</label>
  <fieldset submitButton="false">
    <input type="time" token="field1" searchWhenChanged="true">
      <label></label>
      <default>
        <earliest>-24h@h</earliest>
        <latest>now</latest>
      </default>
    </input>
  </fieldset>
  <row>
    <panel>
      <html>
        <style>
          /* Custom Icons */
          #highlight td {
              text-align: center;
          }
          #highlight td.icon i {
              font-size: 25px;
              text-shadow: 1px 1px #aaa;
          }
          #highlight td.icon .severe {
              color: #DC4E41;
          }
          #highlight td.icon .moderate {
              color: #F8BE34;
          }
          #highlight td.icon .low {
              color: #006400;
          }
          #highlight tr.range-red td {
              border-top: 1px solid #DC4E41!important;
              border-bottom: 1px solid #DC4E41!important;
          }
          #highlight .table td {
              border-top: 1px solid #fff;
          }
          #highlight td.range-red {
              font-weight: bold;
          }
          .icon-inline i {
              font-size: 18px;
              margin-left: 5px;
          }
          .icon-inline i.icon-alert-circle {
              color: #ef392c;
          }
          .icon-inline i.icon-alert {
              color: #ff9c1a;
          }
          .icon-inline i.icon-check {
              color: #5fff5e;
          }
          /* Dark Theme */
          td.icon i.dark {
              text-shadow: none;
          }
          /* Row Coloring */
          #highlight tr.dark td {
              background-color: #5BA383 !important;
          }
          #highlight tr.range-red.dark td {
              border-top: 1px solid #AF575A!important;
              border-bottom: 1px solid #AF575A!important;
          }
          #highlight .table .dark td {
              border-top: 1px solid #000000;
              color: #F2F4F5;
          }
        </style>
      </html>
      <table id="highlight">
        <search id="myTableSearch">
          <query>index=_internal sourcetype=splunkd 
| eval Time=strftime(_time,"%Y-%m-%d %H").":00" 
| chart count by log_level Time span=1h limit=10 useother=f 
| foreach "*:00" 
    [| eval "<<FIELD>>"=case('<<FIELD>>'>=0 AND '<<FIELD>>'<100,"low",'<<FIELD>>'>=100 AND '<<FIELD>>'<5000,"moderate",'<<FIELD>>'>=5000 AND '<<FIELD>>'<10000,"severe",true(),"NA")] 
| foreach "*:00" 
    [| eval "<<FIELD>>"=replace('<<FIELD>>',"^0$","NA")]</query>
          <earliest>$field1.earliest$</earliest>
          <latest>$field1.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="refresh.display">progressbar</option>
        <option name="rowNumbers">false</option>
        <option name="totalsRow">false</option>
        <option name="wrap">true</option>
      </table>
    </panel>
  </row>
</form>

Following is the required JS table_row_highlighting_with_icons.js

/* TODO: jink to replace theme_utils with that from core */
require.config({
  paths: {
    theme_utils: "../app/simple_xml_examples/theme_utils"
  }
});

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

    console.log("Inside Table Render JS");

    var isDarkTheme = themeUtils.getCurrentTheme && themeUtils.getCurrentTheme() === "dark";

    var mySearch = splunkjs.mvc.Components.getInstance("myTableSearch");
    var myResults = mySearch.data("results", {count:0});
    var allFields,filteredFields;

    // Translations from rangemap results to CSS class
    var ICONS = {
        severe: 'alert-circle',
        moderate: 'alert',
        low: 'check-circle'
    };

    myResults.on("data", function(){
        allFields=myResults.data().fields;
        filteredFields=allFields.filter(filterFields);
    });
    function filterFields(field) {
        return field !== "log_level";
    }

     // 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 log_level
             return _(filteredFields).contains(cell.field);
         },
         render: function($td, cell) {

             // Apply interpretation based on count of errors per _time for each field
             if(cell.field!=="log_level"){
                var icon = 'question';
                var isDarkTheme = themeUtils.getCurrentTheme && themeUtils.getCurrentTheme() === 'dark';
                // Fetch the icon for the value
                if(cell.value!=="NA"){
                    if (ICONS.hasOwnProperty(cell.value)) {
                        icon = ICONS[cell.value];
                    }
                    // Create the icon element and add it to the table cell
                    $td.addClass('icon').html(_.template('<i class="icon-<%-icon%> <%- range %> <%- isDarkTheme %>" title="<%- range %>"></i>', {
                        icon: icon,
                        range: cell.value,
                        isDarkTheme: isDarkTheme ? 'dark' : ''
                    }));
                }else{
                    // Update the cell content
                    $td.text("NA").addClass("string");
                    $td.addClass("range-cell").addClass("range-red");
                }
             }
         }
     });

    mvc.Components.get('highlight').getVisualization(function(tableView) {
        tableView.on('rendered', function() {
            // Add a delay to ensure Custom Render applies to row without getting overridden with built in reder.            
            setTimeout(function(){  
                // Apply class of the cells to the parent row in order to color the whole row
                tableView.$el.find('td.range-cell').each(function() {
                    $(this).parents('tr').addClass(this.className);
                });
            },100);
            if(isDarkTheme){
              tableView.$el.find('td.timestamp').each(function() {
                 $(this).parents('tr').addClass('dark');
              });
            }
        });
        // Add custom cell renderer, the table will re-render automatically.
        tableView.addCellRenderer(new CustomRangeRenderer());
    });
});

PS: CSS Style override has been directly added in the SImple XML dashboard as <html> panel. You can move the same to css file as per your use case.

Please try out and confirm.

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

View solution in original post

niketn
Legend

@bmendez0428 please use the following run anywhere example on similar lines as per your question. It gets the ERROR, INFO and WARN log levels for Splunk's _internal logs and converts the range of count of each over time to SLAs i.e. low, moderate and severe. Whenever any row has a column with NA, it adds a red border to the same.

PS: I have extended the DARK mode customer table rendering for this example. So if you are on more recent versions of Splunk i.e. 7.x+ , you can take advantage of the Dark Mode for as your dashboard theme.

alt text

Following is the run anywhere Simple XML Code:

<form script="table_row_highlighting_with_icons.js">
  <label>Table with icon and NA</label>
  <fieldset submitButton="false">
    <input type="time" token="field1" searchWhenChanged="true">
      <label></label>
      <default>
        <earliest>-24h@h</earliest>
        <latest>now</latest>
      </default>
    </input>
  </fieldset>
  <row>
    <panel>
      <html>
        <style>
          /* Custom Icons */
          #highlight td {
              text-align: center;
          }
          #highlight td.icon i {
              font-size: 25px;
              text-shadow: 1px 1px #aaa;
          }
          #highlight td.icon .severe {
              color: #DC4E41;
          }
          #highlight td.icon .moderate {
              color: #F8BE34;
          }
          #highlight td.icon .low {
              color: #006400;
          }
          #highlight tr.range-red td {
              border-top: 1px solid #DC4E41!important;
              border-bottom: 1px solid #DC4E41!important;
          }
          #highlight .table td {
              border-top: 1px solid #fff;
          }
          #highlight td.range-red {
              font-weight: bold;
          }
          .icon-inline i {
              font-size: 18px;
              margin-left: 5px;
          }
          .icon-inline i.icon-alert-circle {
              color: #ef392c;
          }
          .icon-inline i.icon-alert {
              color: #ff9c1a;
          }
          .icon-inline i.icon-check {
              color: #5fff5e;
          }
          /* Dark Theme */
          td.icon i.dark {
              text-shadow: none;
          }
          /* Row Coloring */
          #highlight tr.dark td {
              background-color: #5BA383 !important;
          }
          #highlight tr.range-red.dark td {
              border-top: 1px solid #AF575A!important;
              border-bottom: 1px solid #AF575A!important;
          }
          #highlight .table .dark td {
              border-top: 1px solid #000000;
              color: #F2F4F5;
          }
        </style>
      </html>
      <table id="highlight">
        <search id="myTableSearch">
          <query>index=_internal sourcetype=splunkd 
| eval Time=strftime(_time,"%Y-%m-%d %H").":00" 
| chart count by log_level Time span=1h limit=10 useother=f 
| foreach "*:00" 
    [| eval "<<FIELD>>"=case('<<FIELD>>'>=0 AND '<<FIELD>>'<100,"low",'<<FIELD>>'>=100 AND '<<FIELD>>'<5000,"moderate",'<<FIELD>>'>=5000 AND '<<FIELD>>'<10000,"severe",true(),"NA")] 
| foreach "*:00" 
    [| eval "<<FIELD>>"=replace('<<FIELD>>',"^0$","NA")]</query>
          <earliest>$field1.earliest$</earliest>
          <latest>$field1.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="refresh.display">progressbar</option>
        <option name="rowNumbers">false</option>
        <option name="totalsRow">false</option>
        <option name="wrap">true</option>
      </table>
    </panel>
  </row>
</form>

Following is the required JS table_row_highlighting_with_icons.js

/* TODO: jink to replace theme_utils with that from core */
require.config({
  paths: {
    theme_utils: "../app/simple_xml_examples/theme_utils"
  }
});

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

    console.log("Inside Table Render JS");

    var isDarkTheme = themeUtils.getCurrentTheme && themeUtils.getCurrentTheme() === "dark";

    var mySearch = splunkjs.mvc.Components.getInstance("myTableSearch");
    var myResults = mySearch.data("results", {count:0});
    var allFields,filteredFields;

    // Translations from rangemap results to CSS class
    var ICONS = {
        severe: 'alert-circle',
        moderate: 'alert',
        low: 'check-circle'
    };

    myResults.on("data", function(){
        allFields=myResults.data().fields;
        filteredFields=allFields.filter(filterFields);
    });
    function filterFields(field) {
        return field !== "log_level";
    }

     // 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 log_level
             return _(filteredFields).contains(cell.field);
         },
         render: function($td, cell) {

             // Apply interpretation based on count of errors per _time for each field
             if(cell.field!=="log_level"){
                var icon = 'question';
                var isDarkTheme = themeUtils.getCurrentTheme && themeUtils.getCurrentTheme() === 'dark';
                // Fetch the icon for the value
                if(cell.value!=="NA"){
                    if (ICONS.hasOwnProperty(cell.value)) {
                        icon = ICONS[cell.value];
                    }
                    // Create the icon element and add it to the table cell
                    $td.addClass('icon').html(_.template('<i class="icon-<%-icon%> <%- range %> <%- isDarkTheme %>" title="<%- range %>"></i>', {
                        icon: icon,
                        range: cell.value,
                        isDarkTheme: isDarkTheme ? 'dark' : ''
                    }));
                }else{
                    // Update the cell content
                    $td.text("NA").addClass("string");
                    $td.addClass("range-cell").addClass("range-red");
                }
             }
         }
     });

    mvc.Components.get('highlight').getVisualization(function(tableView) {
        tableView.on('rendered', function() {
            // Add a delay to ensure Custom Render applies to row without getting overridden with built in reder.            
            setTimeout(function(){  
                // Apply class of the cells to the parent row in order to color the whole row
                tableView.$el.find('td.range-cell').each(function() {
                    $(this).parents('tr').addClass(this.className);
                });
            },100);
            if(isDarkTheme){
              tableView.$el.find('td.timestamp').each(function() {
                 $(this).parents('tr').addClass('dark');
              });
            }
        });
        // Add custom cell renderer, the table will re-render automatically.
        tableView.addCellRenderer(new CustomRangeRenderer());
    });
});

PS: CSS Style override has been directly added in the SImple XML dashboard as <html> panel. You can move the same to css file as per your use case.

Please try out and confirm.

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

vnravikumar
Champion
0 Karma
Get Updates on the Splunk Community!

Enterprise Security Content Update (ESCU) | New Releases

In December, the Splunk Threat Research Team had 1 release of new security content via the Enterprise Security ...

Why am I not seeing the finding in Splunk Enterprise Security Analyst Queue?

(This is the first of a series of 2 blogs). Splunk Enterprise Security is a fantastic tool that offers robust ...

Index This | What are the 12 Days of Splunk-mas?

December 2024 Edition Hayyy Splunk Education Enthusiasts and the Eternally Curious!  We’re back with another ...