You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

283 lines
17 KiB

/*
* The PMPinnedDetailView is the controller for a pinned entities in the proactive monitoring visualization
* Most notably it will control the creation of the required searches and sub views for an entity
*/
define(['/static/app/DA-ITSI-CP-vmware-dashboards/libs/backbone.js',
"/static/app/DA-ITSI-CP-vmware-dashboards/swc-vmware-cp/index.js",
"pm/PMEventDispatcher",
"pm/PMPinnedDetailTableView",
"pm/PMChartView",
"pm/PMThresholdIndexCellRenderer",
"pm/PMLeafNameCellRenderer",
"text!pm/PMPinnedDetail.html",
'/static/app/DA-ITSI-CP-vmware-dashboards/libs/underscore.js'],
function ( Backbone, SWCVMware, dispatcher, PinnedDetailTableView, ChartView, PMThresholdIndexCellRenderer, PMLeafNameCellRenderer, PinnedDetailTemplate, _ ) {
const TokenUtils = SWCVMware.MVCTokenUtils;
const SearchManager = SWCVMware.SearchManager;
const mvc = SWCVMware.MVC;
const TableView = SWCVMware.TableView;
var template = _.template(PinnedDetailTemplate, null, {variable: "node"});
var PinnedDetail = Backbone.View.extend({
tagName: "div",
className: "proactive-monitoring-pinboard",
events: {
"click .pm-pinned-detail-title-bar": "toggleBody",
"click .pm-pinned-detail-icon-circle.pm-pinned-detail-action-remove": "removeNode",
"click .pm-pinned-detail-icon-circle.pm-pinned-detail-action-drill": "drillNode"
},
options: {
sidebar_width: 300,
min_total_height: 800
},
type_detail_search_map: {
"VirtualMachine": '`vmwareinv-index` sourcetype="vmware_inframon:inv:vm" earliest=1 ' +
'| spath moid output=moid ' +
'| search moid="$moid$" host="$host$" ' +
'|spath collectionVersion output=collectionVersion ' +
'| spath changeSet.name output=name ' +
'| spath changeSet.summary.runtime.powerState output=powerState ' +
'| spath changeSet.config.guestFullName output=guestFullName ' +
'| spath changeSet.guest.toolsStatus output=toolsStatus ' +
'| spath changeSet.config.hardware.numCPU output=numCPU ' +
'| spath changeSet.config.hardware.numCoresPerSocket output=numCoresPerSocket ' +
'| spath changeSet.config.hardware.memoryMB output=memorySizeMB ' +
'| spath changeSet.resourceConfig.cpuAllocation.reservation output=cpuReservation ' +
'| spath changeSet.resourceConfig.memoryAllocation.reservation output=memoryReservation ' +
'| spath changeSet.resourceConfig.memoryAllocation.shares.level output=memSharesLevel ' +
'| spath changeSet.resourceConfig.memoryAllocation.shares.shares output=memSharesShares ' +
'| spath changeSet.resourceConfig.cpuAllocation.shares.level output=cpuSharesLevel ' +
'| spath changeSet.resourceConfig.cpuAllocation.shares.shares output=cpuSharesShares ' +
'| spath changeSet.summary.runtime.host.moid output=HostSystem ' +
'| head (collectionVersion!=1) keeplast=t ' +
'| stats first(name) AS name, first(powerState) AS powerState, first(numCPU) AS numCPU, first(guestFullName) AS guestFullName, ' +
'first(toolsStatus) AS toolsStatus, first(numCoresPerSocket) AS numCoresPerSocket, first(memorySizeMB) AS memorySizeMB, ' +
'first(cpuReservation) AS cpuReservation, first(memoryReservation) AS memoryReservation, first(memSharesLevel) AS memSharesLevel, ' +
'first(memSharesShares) AS memSharesShares, first(cpuSharesLevel) AS cpuSharesLevel, first(cpuSharesShares) AS cpuSharesShares, ' +
'first(HostSystem) AS HostSystem first(_time) AS _time by moid, host ' +
'| fillnull value="Not Available" powerState numCoresPerSocket memorySizeMB cpuSharesShares memSharesShares memoryReservation cpuReservation numCPU ' +
'| eval cpuSharesLevel=if(isnull(cpuSharesLevel), "Not Available", cpuSharesLevel) ' +
'| eval memSharesLevel=if(isnull(memSharesLevel), "Not Available", memSharesLevel) ' +
'| eval guestFullName=if(isnull(guestFullName), "Not Available", guestFullName) ' +
'| eval toolsStatus=if(isnull(toolsStatus), "Not Available", toolsStatus) ' +
'| fields - moid,host,name,HostSystem,_time',
"HostSystem": '`vmwareinv-index` sourcetype="vmware_inframon:inv:hostsystem" earliest=1 ' +
'| spath moid output=moid ' +
'| spath changeSet.name output=name ' +
'| search moid="$moid$" host="$host$" ' +
'| spath collectionVersion output=collectionVersion ' +
'| spath changeSet.summary.overallStatus output=overallStatus ' +
'| spath changeSet.summary.quickStats.overallCpuUsage output=overallCpuUsage ' +
'| spath changeSet.summary.quickStats.overallMemoryUsage output=overallMemoryUsage ' +
'| spath changeSet.summary.hardware.cpuMhz output=cpuMhz ' +
'| spath changeSet.summary.hardware.memorySize output=memorySize ' +
'| spath changeSet.summary.hardware.numCpuCores output=CPUCores ' +
'| spath changeSet.summary.hardware.vendor output=manufacturer ' +
'| spath changeSet.summary.hardware.model output=model | spath changeSet.summary.hardware.numNics output=numNics ' +
'| spath changeSet.summary.hardware.cpuModel output=processorType | spath changeSet.summary.hardware.numCpuPkgs output=numCpuPkgs ' +
'| spath changeSet.summary.hardware.numCpuThreads output=logicalProcessor | spath changeSet.config.hyperThread.active output=active ' +
'| spath changeSet.summary.host.moid output=HostSystem | spath changeSet.parent.moid output=HostSystemParent ' +
'| spath changeSet.parent.type output=HostSystemParentType | head (collectionVersion!=1) keeplast=t ' +
'| stats first(overallStatus) As overallStatus first(manufacturer) As Manufacturer first(model) As Model first(numNics) As NumberofNICs ' +
'first(logicalProcessor) As LogicalProcessors first(processorType) As ProcessorType first(numCpuPkgs) As ProcessorSockets ' +
'first(overallMemoryUsage) AS MemUsg first(overallCpuUsage) AS CpuUsg first(cpuMhz) AS MhzPerCore first(memorySize) AS Mem first(CPUCores) as CPUCores' +
' first(name) As Host first(HostSystem) AS HostSystem first(HostSystemParent) As HostSystemParent first(HostSystemParentType) As HostSystemParentType first(active) as active by moid, host' +
'| eval MaxCpuMhz=MhzPerCore*CPUCores ' +
'| eval MaxMemMB=((Mem/1024)/1024) ' +
'| eval FreeMem=MaxMemMB-MemUsg ' +
'| eval FreeCpu=MaxCpuMhz-CpuUsg ' +
'| eval CoresperSocket=CPUCores/ProcessorSockets ' +
'| eval Hyperthreading=if(active="True", "Active", "Inactive") ' +
'| fillnull value="N/A" overallStatus, Manufacturer, Model, NumberofNICs,LogicalProcessors,ProcessorType, ProcessorSockets, MemUsg, CpuUsg, MhzPerCore, Mem, CPUCores, CoresperSocket, FreeCpu, FreeMem, Hyperthreading, MaxCpuMhz, MaxMemMB' +
'| fields - count,Host,HostSystemParent,HostSystem,HostSystemParentType,moid,host,Mem,active',
"ClusterComputeResource": '| stats count ' +
'| eval moid="$moid$" ' +
'| eval host="$host$" ' +
'| `HandleInfoMaxTimeNow` ' +
'| eval _time=info_max_time ' +
'| lookup TimeClusterServicesAvailability moid, host OUTPUT p_average_clusterServices_effectivecpu_megaHertz p_average_clusterServices_effectivemem_megaBytes ' +
'| lookup FullHierarchy moid, host OUTPUT name | rename p_average_clusterServices_effectivecpu_megaHertz as AvgEffCpu_MHz ' +
'| eval AvgEffMem=`format_bytes(p_average_clusterServices_effectivemem_megaBytes*1024*1024)` ' +
'| eval AvgEffCpu_MHz=if(isnull(AvgEffCpu_MHz),"Unavailable",AvgEffCpu_MHz) ' +
'| table AvgEffCpu_MHz AvgEffMem',
"RootFolder": '`vmwareinv-index` sourcetype=vmware_inframon:inv:hierarchy earliest=-8h latest=now host=$host$ "\\"type\\": \\"VirtualMachine\\"" OR "\\"type\\": \\"HostSystem\\"" OR "\\"type\\": \\"ClusterComputeResource\\"" ' +
'| dedup moid | stats count(eval(type="HostSystem")) AS Hosts count(eval(type="VirtualMachine")) as VirtualMachines count(eval(type="ClusterComputeResource")) as Clusters'
},
specific_performance_search: '| mstats span=1m avg(_value) as avgValue ' +
'where metric_name=vsphere.$metric_entity$.$perf_type$.$metric_type$ AND `vmwareperf-metrics-index` AND source="VMPerf:$perf_source$" ' +
'AND instance="aggregated" AND unit="$unit$" AND (moid="$moid$" AND host="$host$") by vmware_metric_aggregation ' +
'| eval avg_$metric_type$_$unit$ =if(vmware_metric_aggregation="$metric_aggregation$",avgValue,NULL) ' +
'| timechart minspan=1m avg(avg_$metric_type$_$unit$) AS metric',
parent_performance_search: '| mstats span=1m avg(_value) as avgValue ' +
'where metric_name=vsphere.$metric_entity$.$perf_type$.$metric_type$ AND `vmwareperf-metrics-index` AND source="VMPerf:$perf_source$" ' +
'AND unit="$unit$" AND (moid="$moid$" AND host="$host$") ' +
'OR (hypervisor="$moid$" AND host="$host$") OR (cluster="$moid$" AND host="$host$") instance="aggregated" by host moid vmware_metric_aggregation ' +
'| eval avg_$metric_type$_$unit$ =if(vmware_metric_aggregation="$metric_aggregation$",avgValue,NULL) ' +
'| stats avg(avg_$metric_type$_$unit$) AS avg_metric by host, moid |stats sparkline(avg(avg_metric), 5m) AS sparkline avg(avg_metric) AS avg_metric by host, moid ' +
'| $threshold_snippet$ ' +
'| eval _time=now() ' +
'| lookup FullHierarchy moid, host OUTPUT name ' +
'| table threshold_index, name, sparkline ' +
'| sort threshold_index ' +
'| rename threshold_index AS s ' +
'| head 50',
node: undefined,
pinboard_controller: undefined,
detail_manager: undefined,
initialize: function (options) {
this.node = options.node;
this.pinboard_controller = options.pinboard_controller;
this.pin_id = options.pin_id;
this.distribution_search_id = options.distribution_search_id;
Backbone.View.prototype.initialize.apply(this, arguments);
},
/*
* Render all the things!
*/
render: function () {
this.$el.html(template(this.node, {variable: "node"}));
//Freeze Tokens at current values for pinned searches
var submitted_tokens = mvc.Components.get('submitted');
var entitytype = submitted_tokens.get("entity_type");
var earliest = submitted_tokens.get("earliest");
var latest = submitted_tokens.get("latest");
//Set Metric in View
this.$(".pm-pinned-detail-metric-section").text(submitted_tokens.get("metric"));
//Detail Info Search and View
var detail_manager_id = this.node.id + "-detail-" + this.cid;
this.detail_manager = new SearchManager({
id: detail_manager_id,
earliest_time: earliest,
latest_time: latest,
preview: false,
cache: 600,
status_buckets: 0,
search: this._getDetailSearch(),
time_format: "%s.%Q"
}, {tokens: false});
this.detail_view = new PinnedDetailTableView({
el: this.$(".pm-pinned-detail-detail-section"),
managerid: detail_manager_id
});
//Chart Search and View
var chart_manager_id = this.node.id + "-chart-" + this.cid;
var search_snippet;
if (this.node.type.toLowerCase() === entitytype) {
//For leaf node show the distribution graph
search_snippet = this.specific_performance_search.replace(/\$moid\$/g, this.node.node_id).replace(/\$host\$/g, this.node.tree);
this.chart_search = new SearchManager({
id: chart_manager_id,
earliest_time: earliest,
latest_time: latest,
preview: false,
cache: 600,
status_buckets: 0,
search: TokenUtils.replaceTokens(search_snippet, mvc.Components, {tokenNamespace: "submitted"}),
time_format: "%s.%Q"
}, {tokens: false});
this.chart_view = new ChartView({
el: this.$(".pm-pinned-detail-chart-section"),
color_scheme: "light",
plot_width: 230,
distribution_managerid: this.distribution_search_id,
specific_managerid: chart_manager_id
});
this.chart_view.render();
}
else {
//For parent node show sparklines
search_snippet = this.parent_performance_search.replace(/\$moid\$/g, this.node.node_id).replace(/\$host\$/g, this.node.tree);
this.chart_search = new SearchManager({
id: chart_manager_id,
earliest_time: earliest,
latest_time: latest,
preview: true,
cache: 600,
status_buckets: 0,
search: TokenUtils.replaceTokens(search_snippet, mvc.Components, {tokenNamespace: "submitted"}),
time_format: "%s.%Q"
}, {tokens: false});
this.chart_view = new TableView({
id: this.node.id + "-table-" + this.cid,
managerid: chart_manager_id,
format: {
sparkline: [
{
type: "sparkline",
options: {
width: "100px",
lineColor: "#BCBCBC"
}
}
]
},
pageSize: 10,
pagerPosition: "bottom",
showPager: true,
el: this.$(".pm-pinned-detail-chart-section")
}).render();
this.chart_view.table.addCellRenderer(new PMThresholdIndexCellRenderer());
this.chart_view.table.addCellRenderer(new PMLeafNameCellRenderer());
this.chart_view.table.render();
}
},
_getDetailSearch: function () {
var base_search = this.type_detail_search_map[this.node.type];
return base_search.replace(/\$moid\$/g, this.node.node_id).replace(/\$host\$/g, this.node.tree);
},
//
// EVENT CALLBACKS
//
toggleBody: function () {
console.log("[PMPinnedDetail] toggle body called on node:" + this.node.name);
var that = this;
this.$(".pm-pinned-detail-body").slideToggle(function () {
var $this = $(this);
if ($this.css("display") === "none") {
that.$(".pm-pinned-detail-title-bar").css("border-bottom", "1px solid #CCCCCC");
}
else {
that.$(".pm-pinned-detail-title-bar").css("border-bottom", "none");
}
});
},
removeNode: function (e) {
//Stop toggle from triggering
e.stopPropagation();
console.log("[PMPinnedDetail] remove called on node:" + this.node.name);
//Clean up detail info
this.detail_manager.set("cancelOnUnload", false);
this.detail_manager.cancel();
this.detail_manager.off();
mvc.Components.revokeInstance(this.detail_manager.id);
this.detail_view.off();
this.detail_view.remove();
//Unregister with controller
this.pinboard_controller.removePin(this.pin_id);
//Remove this view
this.off();
this.remove();
},
drillNode: function (e) {
//Stop toggle from triggering
e.stopPropagation();
console.log("[PMPinnedDetail] drill called on node:" + this.node.name);
dispatcher.trigger("node:drill", this.node);
}
});
return PinnedDetail;
});