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!

Index This | I am a number, but when you add ‘G’ to me, I go away. What number am I?

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

What’s New in Splunk App for PCI Compliance 5.3.1?

The Splunk App for PCI Compliance allows customers to extend the power of their existing Splunk solution with ...

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 ...