diff --git a/src/netsage_sankey.js b/src/netsage_sankey.js index d15ab3d..ac7ed06 100644 --- a/src/netsage_sankey.js +++ b/src/netsage_sankey.js @@ -52,15 +52,15 @@ const panelDefaults = { text: 'Not implemented yet', value: 'kbn.getUnitFormats()' }, - { - text: 'test unit', - value: 'short' - } - ] + { + text: 'test unit', + value: 'short' + } + ] }], table_editor_unitFormats: '', table_data_type: '', - table_data: [], + // table_data: [], // other variables auto_format_labels: false, label_nodes: [], @@ -68,15 +68,20 @@ const panelDefaults = { table_editor_kbnUnitFormats: kbn.getUnitFormats(), }; +let table_data = []; +let docs_data = []; + export class NetSageSankey extends MetricsPanelCtrl { + + constructor($scope, $injector) { super($scope, $injector); _.defaults(this.panel, panelDefaults); this.sankeynetsage_holder_id = 'sankeynetsage_' + this.panel.id; - this.containerDivId = 'container_' + this.sankeynetsage_holder_id; + this.containerDivId = 'container_' + this.sankeynetsage_holder_id; this.events.on('data-received', this.onDataReceived.bind(this)); this.events.on('data-error', this.onDataError.bind(this)); this.events.on('data-snapshot-load', this.onDataReceived.bind(this)); @@ -87,7 +92,8 @@ export class NetSageSankey extends MetricsPanelCtrl { onDataReceived(dataList) { - this.panel.docs_data = []; + table_data = []; + docs_data = []; this.panel.docs_table_data = []; this.panel.label_nodes = []; this.panel.data_type = ""; @@ -104,6 +110,7 @@ export class NetSageSankey extends MetricsPanelCtrl { if (dataList.length > 0) { // set current data type this.panel.data_type = dataList[0].type; + console.log(this.panel.data_type); // check if data type is full record if (this.panel.data_type === "docs") { @@ -130,7 +137,7 @@ export class NetSageSankey extends MetricsPanelCtrl { for (var i = 0; i < dataList[0].columns.length - 1; i++) { self.panel.table_editor_option_nodes.push(dataList[0].columns[i].text); } - this.panel.table_data = dataList[0].rows.slice(0); + table_data = dataList[0].rows.slice(0); } @@ -138,12 +145,12 @@ export class NetSageSankey extends MetricsPanelCtrl { process_docs_data(dataList) { function matchingFlow(elk_datapoint, agData) { return (elk_datapoint.meta.src_ip === agData.meta.src_ip && - elk_datapoint.meta.src_asn === agData.meta.src_asn && - elk_datapoint.meta.src_port === agData.meta.src_port && - elk_datapoint.meta.protocol === agData.meta.protocol && - elk_datapoint.meta.dst_port === agData.meta.dst_port && - elk_datapoint.meta.dst_asn === agData.meta.dst_asn && - elk_datapoint.meta.dst_ip === agData.meta.dst_ip) + elk_datapoint.meta.src_asn === agData.meta.src_asn && + elk_datapoint.meta.src_port === agData.meta.src_port && + elk_datapoint.meta.protocol === agData.meta.protocol && + elk_datapoint.meta.dst_port === agData.meta.dst_port && + elk_datapoint.meta.dst_asn === agData.meta.dst_asn && + elk_datapoint.meta.dst_ip === agData.meta.dst_ip) } // process full records here @@ -154,7 +161,7 @@ export class NetSageSankey extends MetricsPanelCtrl { var elk_datapoint = data.datapoints[i]; var flowNotExists = true; - if (self.panel.docs_data.length > 0) { + if (docs_data.length > 0) { _.forEach(self.panel.docs_data, function (agData) { if (matchingFlow(elk_datapoint, agData)) { flowNotExists = false; @@ -162,33 +169,33 @@ export class NetSageSankey extends MetricsPanelCtrl { agData.sankey_totalFlows++; //aggregate data switch (self.panel.aggregation) { - case 'Average': - for (var k in agData.values) { - agData.values[k] += elk_datapoint.values[k]; - } - break; - case 'Total': - for (var k in agData.values) { - agData.values[k] += elk_datapoint.values[k]; - } - break; - case 'Max': - for (var k in agData.values) { - if (agData.values[k] != elk_datapoint.values[k]) - console.log(agData._id) - agData.values[k] = Math.max(agData.values[k], elk_datapoint.values[k]); - } - break; - case 'Min': - for (var k in agData.values) { - agData.values[k] = Math.min(agData.values[k], elk_datapoint.values[k]); - } - break; - default: - elk_datapoint.sankey_totalFlows++; - for (var k in agData.values) { - agData.values[k] += elk_datapoint.values[k]; - } + case 'Average': + for (var k in agData.values) { + agData.values[k] += elk_datapoint.values[k]; + } + break; + case 'Total': + for (var k in agData.values) { + agData.values[k] += elk_datapoint.values[k]; + } + break; + case 'Max': + for (var k in agData.values) { + if (agData.values[k] != elk_datapoint.values[k]) + console.log(agData._id) + agData.values[k] = Math.max(agData.values[k], elk_datapoint.values[k]); + } + break; + case 'Min': + for (var k in agData.values) { + agData.values[k] = Math.min(agData.values[k], elk_datapoint.values[k]); + } + break; + default: + elk_datapoint.sankey_totalFlows++; + for (var k in agData.values) { + agData.values[k] += elk_datapoint.values[k]; + } } } }); @@ -206,13 +213,13 @@ export class NetSageSankey extends MetricsPanelCtrl { if (self.panel.docs_data.length > 0) { _.forEach(self.panel.docs_data, function (agData) { switch (self.panel.aggregation) { - case 'Average': - for (var k in agData.values) { - agData.values[k] = agData.values[k] / agData.sankey_totalFlows; - } - break; - default: - break; + case 'Average': + for (var k in agData.values) { + agData.values[k] = agData.values[k] / agData.sankey_totalFlows; + } + break; + default: + break; } }); } @@ -328,11 +335,11 @@ export class NetSageSankey extends MetricsPanelCtrl { } - setup(){ + setup() { var ctrl = this; - if (! document.getElementById(ctrl.sankeynetsage_holder_id)){ + if (!document.getElementById(ctrl.sankeynetsage_holder_id)) { return; } @@ -341,27 +348,27 @@ export class NetSageSankey extends MetricsPanelCtrl { } var sankeyData = []; - + if (ctrl.panel.data_type === 'docs') { // update node labels // convert docs data to sankey data - if (ctrl.panel.docs_data.length > 0) { - _.forEach(ctrl.panel.docs_data, function (agData, index) { + if (docs_data.length > 0) { + _.forEach(docs_data, function (agData, index) { for (var i = 0; i < ctrl.panel.docs_editor_option_nodes.length - 1; i++) { //get links info let source = getValueFromString(agData, ctrl.panel.docs_editor_option_nodes[i]); let target = getValueFromString(agData, ctrl.panel.docs_editor_option_nodes[i + 1]); let value = getValueFromString(agData, ctrl.panel.docs_editor_link_width_input); - + // to avoid cyclic sankey, appending (src) and (dst) to names let source_option = ctrl.panel.docs_editor_option_nodes[i]; let target_option = ctrl.panel.docs_editor_option_nodes[i + 1]; source += ((source_option.includes("src") || source_option.includes("dst")) ? - (source_option.includes("src") ? " (src)" : " (dst)") : - ""); + (source_option.includes("src") ? " (src)" : " (dst)") : + ""); target += ((target_option.includes("src") || target_option.includes("dst")) ? - (target_option.includes("src") ? " (src)" : " (dst)") : - ""); + (target_option.includes("src") ? " (src)" : " (dst)") : + ""); // add to sankeyData array sankeyData.push({ @@ -382,8 +389,8 @@ export class NetSageSankey extends MetricsPanelCtrl { ctrl.panel.label_nodes = ctrl.panel.table_editor_option_nodes.slice(0); } // convert table data to sankey data - if (ctrl.panel.table_data.length > 0) { - _.forEach(ctrl.panel.table_data, function (tData, index) { + if (table_data.length > 0) { + _.forEach(table_data, function (tData, index) { for (var i = 0; i < tData.length - 2; i++) { // last index is value, so -2 to prevent using value as a node //get links info let source = tData[i]; @@ -394,11 +401,11 @@ export class NetSageSankey extends MetricsPanelCtrl { let source_option = ctrl.panel.table_editor_option_nodes[i]; let target_option = ctrl.panel.table_editor_option_nodes[i + 1]; source += ((source_option.includes("src") || source_option.includes("dst")) ? - (source_option.includes("src") ? " (src)" : " (dst)") : - ""); + (source_option.includes("src") ? " (src)" : " (dst)") : + ""); target += ((target_option.includes("src") || target_option.includes("dst")) ? - (target_option.includes("src") ? " (src)" : " (dst)") : - ""); + (target_option.includes("src") ? " (src)" : " (dst)") : + ""); // add to sankeyData array sankeyData.push({ @@ -415,11 +422,11 @@ export class NetSageSankey extends MetricsPanelCtrl { // get sankey graph from data var graph = ctrl.createSankeyGraphFromData(sankeyData); - + //render sankey ctrl.renderSankey(graph); } - + // converts data into sankey node/link form createSankeyGraphFromData(data) { //set up graph in same style as original example but empty @@ -427,7 +434,7 @@ export class NetSageSankey extends MetricsPanelCtrl { "nodes": [], "links": [] }; - + data.forEach(function (d) { graph.nodes.push({ "name": d.source @@ -442,20 +449,20 @@ export class NetSageSankey extends MetricsPanelCtrl { "label": d.label }); }); - + // return only the distinct / unique nodes graph.nodes = d3.keys(d3.nest() - .key(function (d) { - return d.name; - }) - .map(graph.nodes)); - + .key(function (d) { + return d.name; + }) + .map(graph.nodes)); + // loop through each link replacing the text with its index from node graph.links.forEach(function (d, i) { graph.links[i].source = graph.nodes.indexOf(graph.links[i].source); graph.links[i].target = graph.nodes.indexOf(graph.links[i].target); }); - + //now loop through each nodes to make nodes an array of objects // rather than an array of strings graph.nodes.forEach(function (d, i) { @@ -463,18 +470,23 @@ export class NetSageSankey extends MetricsPanelCtrl { "name": d }; }); - + return graph; } - + // make sankey chart renderSankey(graph) { + + if (graph.links.length == 0 || graph.nodes.length == 0){ + return; + } + var ctrl = this; d3.select('#' + ctrl.containerDivId).selectAll('g').remove(); - + var units = "Widgets"; - + var offw = 900; var offh = 450; if (document.getElementById(ctrl.sankeynetsage_holder_id)) { @@ -482,10 +494,10 @@ export class NetSageSankey extends MetricsPanelCtrl { offh = document.getElementById(ctrl.sankeynetsage_holder_id).offsetHeight; } - if (offh == 0){ - return setTimeout(function(){ctrl.renderSankey(graph);}, 250); + if (offh == 0) { + return setTimeout(function () { ctrl.renderSankey(graph); }, 250); } - + var margin = { top: 10, right: 10, @@ -500,7 +512,7 @@ export class NetSageSankey extends MetricsPanelCtrl { var format = function (d) { return ctrl.panel.data_type === 'docs' ? (ctrl.panel.docs_editor_to_Byte ? ctrl.formatBytes(d) : ctrl.formatBits(d)) : - d + ' ' + ctrl.panel.table_editor_link_width_label + ' (' + ctrl.panel.table_data_type + ')'; + d + ' ' + ctrl.panel.table_editor_link_width_label + ' (' + ctrl.panel.table_data_type + ')'; }; var color = d3.scale.category20(); @@ -575,12 +587,12 @@ export class NetSageSankey extends MetricsPanelCtrl { .attr("y", (margin.top + 5)) .attr("text-anchor", function (d) { switch (ctrl.panel.label_nodes.indexOf(d)) { - case 0: - return "start"; - case ctrl.panel.label_nodes.length - 1: - return "end"; - default: - return "middle"; + case 0: + return "start"; + case ctrl.panel.label_nodes.length - 1: + return "end"; + default: + return "middle"; } }) .text(function (d) { @@ -628,13 +640,13 @@ export class NetSageSankey extends MetricsPanelCtrl { return "translate(" + d.x + "," + d.y + ")"; }) .call(d3.behavior.drag() - .origin(function (d) { - return d; - }) - .on("dragstart", function () { - this.parentNode.appendChild(this); - }) - .on("drag", dragmove)) + .origin(function (d) { + return d; + }) + .on("dragstart", function () { + this.parentNode.appendChild(this); + }) + .on("drag", dragmove)) .on('mouseover', function (event) { let hl = []; _.forEach(event.sourceLinks, function (sl) { @@ -729,20 +741,20 @@ export class NetSageSankey extends MetricsPanelCtrl { // the function for moving the nodes function dragmove(d) { d3.select(this).attr("transform", - "translate(" + d.x + "," + ( - d.y = Math.max(0, Math.min(height - d.dy, d3.event.y)) - ) + ")"); + "translate(" + d.x + "," + ( + d.y = Math.max(0, Math.min(height - d.dy, d3.event.y)) + ) + ")"); sankey.relayout(); link.attr("d", path); } } - + link(scope, elem, attrs, ctrl) { var self = this; ctrl.events.on('render', self.setup.bind(self)); - ctrl.events.on('refresh', self.setup.bind(self)); + ctrl.events.on('refresh', self.setup.bind(self)); } }