Dashboards & Visualizations

How to use two custom cell renderers in one table

davisja
Explorer

I'm trying to make a comprehensive table that looks like the attached picture (except with a less broken health score). The difficulty I'm having is that the health score field is determined by the values in the other columns. Therefore, I need it to render AFTER all the other cells in order for its value and highlighting rules to be correct. How might I accomplish this?

alt text

Here's my code so far:

var deps = [
  'jquery',
  'underscore',
  'splunkjs/mvc',
  'splunkjs/mvc/tableview',
  'splunkjs/mvc/simplexml/ready!'
];

require(deps, function($, _, mvc, TableView) {
  //Cell highlighting for app pool
  var cells = [
    'CPU Load (%)',     // 0
    'Free RAM (MB)',    // 1
    'Used Disk (%)',    // 2
    'Traffic In (KB)',  // 3
    'Traffic Out (KB)', // 4
    'ULS Exceptions',   // 5
    'Unique Users',     // 6
    'Page Impressions',  // 7
  ];

/////////////////////////////////////////////////////////////////////

  var MainCellRenderer = TableView.BaseCellRenderer.extend({

    //Determine when highlighting occurs
    canRender: function(cell) {
      return _(cells).contains(cell.field);
    },

    //Define how to highlight
    render: function($td, cell) {
      var value = cell.value;
      var field = cell.field;

      //Used to determine ranges for each field
      var normal; //[low, high, dev_down, dev_up]

      //Declare ranges
      switch(field) {
        case cells[0]: //CPU
          normal = [20, 80, 0.25, 0.25];
          break;
        case cells[1]: //RAM
          normal = [800, 4000, 0.25, 0.25];
          break;
        case cells[2]: //Disk
          normal = [30, 75, 0.25, 0.25];
          break;
        case cells[3]: //NetIn
          normal = [5, 1000000, 0.25, 0.25];
          break;
        case cells[4]: //NetOut
          normal = [5, 1000000, 0.25, 0.25];
          break;
        case cells[5]: //ULS
          normal = [500, 1500, 0.25, 0.25];
          break;
        case cells[6]: //Users
          normal = [500, 3000, 0.25, 0.25];
          break;
        case cells[7]: //Page Impressions
          normal = [200, 1000, 0.25, 0.25];
          break;
      }

      //Calculate acceptable deviation from norm
      var low = normal[0];
      var high = normal[1];
      var dev_down = low - (low * normal[2]);
      var dev_up = high + (high * normal[3]);

      //Add highlighting to appropriate cells
      if (value >= low && value <= high) {
        $td.addClass('healthy');
      }

      else if (value >= dev_down && value <= dev_up) {
        $td.addClass('warning');
      }

      else {
        $td.addClass('severe');
      }

      //Render cell text
      $td.text(value).addClass('numeric');
  }});

/////////////////////////////////////////////////////////////////////

  var HealthRenderer = TableView.BaseCellRenderer.extend({

    //Only render for the Health Score column
    canRender: function(cell) {
      return cell.field === 'Health Score';
    },

    //Define how to highlight
    render: function($td, cell) {
      //Calculate health score
      var severe_count = $('.severe').length;
      var warning_count = $('.warning').length;
      var health_score = 100 - ((25*severe_count) + (12.5*warning_count));

      //Add appropriate highlighting rules
      if (health_score > 75) {
        $td.addClass('healthy');
      }

      else if (health_score <= 75 && health_score > 50) {
        $td.addClass('warning');
      }

      else {
        $td.addClass('severe');
      }

      //Render text
      $td.text(health_score).addClass('numeric');
  }});

/////////////////////////////////////////////////////////////////////

  //Add both custom cell renderers to table and render it
  mvc.Components.get('health_table')
    .getVisualization(function(tableView) {
      tableView.table.addCellRenderer(new MainCellRenderer());
      tableView.table.addCellRenderer(new HealthRenderer());
      tableView.table.render();
  });
});

Currently, severe_count is showing up as 8 (even though it should be 2) and warning_count is 0 (even though it should be 2)

0 Karma
1 Solution

davisja
Explorer

Solved it. Here's my solution in case anybody ends up needing it:

alt text

And the code:

var deps = [
  'jquery',
  'underscore',
  'splunkjs/mvc',
  'splunkjs/mvc/tableview',
  'splunkjs/mvc/simplexml/ready!'
];

require(deps, function($, _, mvc, TableView) {
  var cells = [
    'CPU Load (%)',     // 0
    'Free RAM (MB)',    // 1
    'Used Disk (%)',    // 2
    'Traffic In (KB)',  // 3
    'Traffic Out (KB)', // 4
    'ULS Exceptions',   // 5
    'Unique Users',     // 6
    'Page Impressions', // 7
    'Health Score',     // 8
  ];

/////////////////////////////////////////////////////////////////////

  //Cell Highlighting
  var CustomCellRenderer = TableView.BaseCellRenderer.extend({

    //Determine when highlighting occurs
    canRender: function(cell) {
      return _(cells).contains(cell.field);
    },

    //Define how to highlight
    render: function($td, cell) {
      var value = cell.value;
      var field = cell.field;

      //Used to determine ranges for each field
      var normal; //[low, high, dev_down, dev_up]

      //Declare ranges
      switch(field) {
        case cells[0]: //CPU
          normal = [20, 80, 0.25, 0.25];
          break;
        case cells[1]: //RAM
          normal = [800, 4000, 0.25, 0.25];
          break;
        case cells[2]: //Disk
          normal = [30, 75, 0.25, 0.25];
          break;
        case cells[3]: //NetIn
          normal = [5, 1000000, 0.25, 0.25];
          break;
        case cells[4]: //NetOut
          normal = [5, 1000000, 0.25, 0.25];
          break;
        case cells[5]: //ULS
          normal = [500, 1500, 0.25, 0.25];
          break;
        case cells[6]: //Users
          normal = [500, 3000, 0.25, 0.25];
          break;
        case cells[7]: //Page Impressions
          normal = [200, 1000, 0.25, 0.25];
          break;
        case cells[8]: //Health Score
          $td.addClass('health_cell'); //Makes it findable
          break;
      }

      //Exclude Health Score cell from initial rendering
      if (normal) {
        //Calculate acceptable deviation from norm
        var low = normal[0];
        var high = normal[1];
        var dev_down = low - (low * normal[2]);
        var dev_up = high + (high * normal[3]);

        //Add highlighting to appropriate cells
        if (value >= low && value <= high) {
          $td.addClass('healthy');
        }

        else if (value >= dev_down && value <= dev_up) {
          $td.addClass('warning');
        }

        else {
          $td.addClass('severe');
        }

        //Render cell text
        $td.text(value).addClass('numeric');
      }
    }
  });


  //Add custom cell renderer to table and render it
  mvc.Components.get('health_table')
    .getVisualization(function(tableView) {
      tableView.table.addCellRenderer(new CustomCellRenderer());

      //Render the health score cell after all the others
      tableView.on('rendered', function() {
        //Calculate health score
        var severe_count = $('.severe').length;
        var warning_count = $('.warning').length;
        var health_score = 100-((25*severe_count)+(12.5*warning_count));

        //Determine correct highlighting and add it to appropriate cell
        tableView.$el.find('.health_cell').each(function() {

          if (health_score > 75) {
            $(this).addClass('healthy');
          }

          else if (health_score <= 75 && health_score > 50) {
            $(this).addClass('warning');
          }

          else {
            $(this).addClass('severe');
          }

          //Render text
          $(this).text(health_score).addClass('numeric');
        });
      });

      //Render table
      tableView.table.render();
  });
});

View solution in original post

davisja
Explorer

Solved it. Here's my solution in case anybody ends up needing it:

alt text

And the code:

var deps = [
  'jquery',
  'underscore',
  'splunkjs/mvc',
  'splunkjs/mvc/tableview',
  'splunkjs/mvc/simplexml/ready!'
];

require(deps, function($, _, mvc, TableView) {
  var cells = [
    'CPU Load (%)',     // 0
    'Free RAM (MB)',    // 1
    'Used Disk (%)',    // 2
    'Traffic In (KB)',  // 3
    'Traffic Out (KB)', // 4
    'ULS Exceptions',   // 5
    'Unique Users',     // 6
    'Page Impressions', // 7
    'Health Score',     // 8
  ];

/////////////////////////////////////////////////////////////////////

  //Cell Highlighting
  var CustomCellRenderer = TableView.BaseCellRenderer.extend({

    //Determine when highlighting occurs
    canRender: function(cell) {
      return _(cells).contains(cell.field);
    },

    //Define how to highlight
    render: function($td, cell) {
      var value = cell.value;
      var field = cell.field;

      //Used to determine ranges for each field
      var normal; //[low, high, dev_down, dev_up]

      //Declare ranges
      switch(field) {
        case cells[0]: //CPU
          normal = [20, 80, 0.25, 0.25];
          break;
        case cells[1]: //RAM
          normal = [800, 4000, 0.25, 0.25];
          break;
        case cells[2]: //Disk
          normal = [30, 75, 0.25, 0.25];
          break;
        case cells[3]: //NetIn
          normal = [5, 1000000, 0.25, 0.25];
          break;
        case cells[4]: //NetOut
          normal = [5, 1000000, 0.25, 0.25];
          break;
        case cells[5]: //ULS
          normal = [500, 1500, 0.25, 0.25];
          break;
        case cells[6]: //Users
          normal = [500, 3000, 0.25, 0.25];
          break;
        case cells[7]: //Page Impressions
          normal = [200, 1000, 0.25, 0.25];
          break;
        case cells[8]: //Health Score
          $td.addClass('health_cell'); //Makes it findable
          break;
      }

      //Exclude Health Score cell from initial rendering
      if (normal) {
        //Calculate acceptable deviation from norm
        var low = normal[0];
        var high = normal[1];
        var dev_down = low - (low * normal[2]);
        var dev_up = high + (high * normal[3]);

        //Add highlighting to appropriate cells
        if (value >= low && value <= high) {
          $td.addClass('healthy');
        }

        else if (value >= dev_down && value <= dev_up) {
          $td.addClass('warning');
        }

        else {
          $td.addClass('severe');
        }

        //Render cell text
        $td.text(value).addClass('numeric');
      }
    }
  });


  //Add custom cell renderer to table and render it
  mvc.Components.get('health_table')
    .getVisualization(function(tableView) {
      tableView.table.addCellRenderer(new CustomCellRenderer());

      //Render the health score cell after all the others
      tableView.on('rendered', function() {
        //Calculate health score
        var severe_count = $('.severe').length;
        var warning_count = $('.warning').length;
        var health_score = 100-((25*severe_count)+(12.5*warning_count));

        //Determine correct highlighting and add it to appropriate cell
        tableView.$el.find('.health_cell').each(function() {

          if (health_score > 75) {
            $(this).addClass('healthy');
          }

          else if (health_score <= 75 && health_score > 50) {
            $(this).addClass('warning');
          }

          else {
            $(this).addClass('severe');
          }

          //Render text
          $(this).text(health_score).addClass('numeric');
        });
      });

      //Render table
      tableView.table.render();
  });
});

ktwingstrom
Path Finder

Hey @davisja, I know this post is from FOREVER ago but I'm attempting to create a custom renderer in JS to simply render some HTML code in a table, rather than color the cells, and I think your example could really help me out. I'm just struggling to figure out how to implement it. Would you be willing to have a conversation offline about how you were able to accomplish this? My email is ktwingstrom[AT]gmail.com. I didn't see a way to PM you through answers.splunk.com so that's why I'm just leaving my email. Thanks!

0 Karma

niketn
Legend

@ktwingstrom, if your issue is different from the one posted here, you should post a new question with details of your requirement, mock screenshot of the output, masked sample data and what you have done so far, so that community members can assist.

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma
Get Updates on the Splunk Community!

More Ways To Control Your Costs With Archived Metrics | Register for Tech Talk

Tuesday, May 14, 2024  |  11AM PT / 2PM ET Register to Attend Join us for this Tech Talk and learn how to ...

.conf24 | Personalize your .conf experience with Learning Paths!

Personalize your .conf24 Experience Learning paths allow you to level up your skill sets and dive deeper ...

Threat Hunting Unlocked: How to Uplevel Your Threat Hunting With the PEAK Framework ...

WATCH NOWAs AI starts tackling low level alerts, it's more critical than ever to uplevel your threat hunting ...