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?
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)
Solved it. Here's my solution in case anybody ends up needing it:
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();
});
});
Solved it. Here's my solution in case anybody ends up needing it:
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();
});
});
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!
@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.