mirror of
https://github.com/ntop/ntopng.git
synced 2026-04-30 16:09:32 +00:00
397 lines
12 KiB
JavaScript
397 lines
12 KiB
JavaScript
// Wrapper function
|
|
function do_sequence_sunburst(circle_name,sequence_name,refresh,update_url,url_params,title,units) {
|
|
var graph = new SequenceSunburst(circle_name,sequence_name,refresh,update_url,url_params,title,units);
|
|
graph.setInterval(window.setInterval(function(){graph.update();}, refresh));
|
|
// Return new class instance, with
|
|
return [graph];
|
|
}
|
|
|
|
|
|
function SequenceSunburst(circle_name,sequence_name,refresh,update_url,url_params,title,units) {
|
|
|
|
// Add object properties like this
|
|
this.circle_name = circle_name;
|
|
this.sequence_name = sequence_name;
|
|
this.update_url = update_url;
|
|
this.url_params = url_params;
|
|
this.units = units;
|
|
this.refresh = refresh;
|
|
this.sunburstInterval;
|
|
|
|
var oldPieData = [];
|
|
var filteredPieData = [];
|
|
|
|
var rsp = create_sequence_sunburst(circle_name,sequence_name,title,units);
|
|
var color = rsp[0];
|
|
var partition = rsp[1];
|
|
var totalSize = rsp[2];
|
|
var arc = rsp[3];
|
|
var arc_group = rsp[4];
|
|
var trail = rsp[5];
|
|
var whiteCircle = rsp[6];
|
|
var totalLabel = rsp[7];
|
|
var totalValue = rsp[8];
|
|
var totalUnits = rsp[9];
|
|
var radius = rsp[10];
|
|
var width = rsp[11];
|
|
var height = rsp[12];
|
|
var b = rsp[13];
|
|
|
|
var last_process = "";
|
|
var last_byte = 0;
|
|
var substring_limit = 8;
|
|
|
|
|
|
// to run each time data is generated
|
|
this.update = function () {
|
|
$.ajax({
|
|
type: 'GET',
|
|
url: this.update_url,
|
|
data: this.url_params,
|
|
success: function(content) {
|
|
update_sequence_sunburst(jQuery.parseJSON(content));
|
|
},
|
|
error: function(content) {
|
|
console.log("error");
|
|
}
|
|
});
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// STREAKER CONNECTION ////////////////////////////////////
|
|
///////////////////////////////////////////////////////////
|
|
|
|
// Needed to draw the pie immediately
|
|
this.update();
|
|
|
|
// var updateInterval = window.setInterval(update, refresh);
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// UPDATE FUNCTIONS ////////////////////////////////////
|
|
///////////////////////////////////////////////////////////
|
|
this.flashUpdate = function (start,end) {
|
|
arc_group.selectAll("path").style("opacity", start)
|
|
.transition().duration(200).style("opacity", end);
|
|
}
|
|
|
|
|
|
function update_sequence_sunburst(data) {
|
|
streakerDataAdded = data;
|
|
// console.log(data);
|
|
oldPieData = filteredPieData;
|
|
pieData = partition.nodes(streakerDataAdded);
|
|
|
|
filteredPieData = pieData.filter(function(d) {
|
|
return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
|
|
});
|
|
|
|
if((filteredPieData.length > 0) && (oldPieData.length > 0)) {
|
|
//REMOVE PLACEHOLDER CIRCLE
|
|
arc_group.selectAll("circle").remove();
|
|
arc_group.selectAll("path").remove();
|
|
// alert("Update");
|
|
}
|
|
|
|
paths = arc_group.selectAll("path").data(filteredPieData);
|
|
|
|
paths.enter().append("svg:path")
|
|
.attr("display", function(d) { return d.depth ? null : "none"; })
|
|
.attr("d", arc)
|
|
.attr("fill-rule", "evenodd")
|
|
.style("fill", function(d) { return color(d.name+d.id); })
|
|
.style("opacity", 1)
|
|
.on("mouseover", mouseover)
|
|
.on("dblclick",function(d) {if(d.url) window.location.href = d.url; });
|
|
|
|
// Add the mouseleave handler to the bounding circle.
|
|
d3.select("#container"+circle_name).on("mouseleave", mouseleave);
|
|
|
|
// Get total size of the tree = value of root node from partition.
|
|
totalSize = paths.node().__data__.value;
|
|
|
|
filteredPieData.forEach(function(d) {
|
|
|
|
if ((last_process.localeCompare(d.name) == 0) && (d.name != "")){
|
|
|
|
var data = bytesToVolumeAndLabel(d.value);
|
|
var value = data[0]
|
|
if (last_byte < d.value) {
|
|
value = data[0]+ ' \uf062';
|
|
}else if (last_byte > d.value) {
|
|
value = data[0]+ ' \uf063';
|
|
} else {
|
|
value = data[0]+ ' \uf068';
|
|
}
|
|
|
|
var name = d.name.substring(0,substring_limit);
|
|
if (d.name.length > substring_limit) {name = name + "..";}
|
|
|
|
totalValue.text(value);
|
|
totalLabel.text(name);
|
|
totalUnits.text(data[1]);
|
|
};
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// UTILS FUNCTIONS ////////////////////////////////////
|
|
///////////////////////////////////////////////////////////
|
|
|
|
function mouseover(d) {
|
|
|
|
var percentage = (100 * d.value / totalSize).toPrecision(3);
|
|
var percentageString = percentage + "%";
|
|
if (percentage < 0.1) {
|
|
percentageString = "< 0.1%";
|
|
}
|
|
var data = bytesToVolumeAndLabel(d.value);
|
|
|
|
totalValue.text(data[0]);
|
|
totalLabel.text(d.name);
|
|
totalUnits.text(data[1]);
|
|
last_process = d.name;
|
|
last_byte = d.value;
|
|
|
|
var sequenceArray = getAncestors(d);
|
|
updateBreadcrumbs(sequenceArray, percentageString);
|
|
|
|
// Fade all the segments.
|
|
arc_group.selectAll("path")
|
|
.style("opacity", 0.3);
|
|
|
|
// Then highlight only those that are an ancestor of the current segment.
|
|
arc_group.selectAll("path")
|
|
.filter(function(node)
|
|
{
|
|
return (sequenceArray.indexOf(node) >= 0);
|
|
})
|
|
.style("opacity", 1);
|
|
};
|
|
|
|
// Restore everything to full opacity when moving off the visualization.
|
|
function mouseleave(d) {
|
|
|
|
// Hide the breadcrumb trail
|
|
trail.style("visibility", "hidden");
|
|
|
|
// Deactivate all segments during transition.
|
|
arc_group.selectAll("path").on("mouseover", null);
|
|
|
|
// Transition each segment to full opacity and then reactivate it.
|
|
arc_group.selectAll("path")
|
|
.transition()
|
|
.duration(500)
|
|
.style("opacity", 1)
|
|
.each("end", function() {
|
|
d3.select(this).on("mouseover", mouseover);
|
|
});
|
|
|
|
|
|
|
|
};
|
|
|
|
// Given a node in a partition layout, return an array of all of its ancestor
|
|
// nodes, highest first, but excluding the root.
|
|
function getAncestors(node) {
|
|
var path = [];
|
|
var current = node;
|
|
while (current.parent) {
|
|
path.unshift(current);
|
|
current = current.parent;
|
|
}
|
|
return path;
|
|
}
|
|
|
|
// Initialize the Breadcrumb as default
|
|
function initializeBreadcrumbTrail(circle_name,sequence_name) {
|
|
// Add the svg area.
|
|
var trail = d3.select("#"+sequence_name).append("svg:svg")
|
|
.attr("width", width)
|
|
.attr("height", 50)
|
|
.attr("id", "trail");
|
|
// Add the label at the end, for the percentage.
|
|
trail.append("svg:text")
|
|
.attr("id", "endlabel")
|
|
.style("fill", "#000");
|
|
|
|
return trail;
|
|
}
|
|
|
|
// Generate a string that describes the points of a breadcrumb polygon.
|
|
function breadcrumbPoints(d, i) {
|
|
var points = [];
|
|
points.push("0,0");
|
|
points.push(b.w + ",0");
|
|
points.push(b.w + b.t + "," + (b.h / 2));
|
|
points.push(b.w + "," + b.h);
|
|
points.push("0," + b.h);
|
|
if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex.
|
|
points.push(b.t + "," + (b.h / 2));
|
|
}
|
|
return points.join(" ");
|
|
}
|
|
|
|
// Update the breadcrumb trail to show the current sequence and percentage.
|
|
function updateBreadcrumbs(nodeArray, percentageString) {
|
|
|
|
// Data join; key function combines name and depth (= position in sequence).
|
|
var g = trail.selectAll("g")
|
|
.data(nodeArray, function(d) { return d.name + d.depth; });
|
|
|
|
// Add breadcrumb and label for entering nodes.
|
|
var entering = g.enter().append("svg:g");
|
|
|
|
entering.append("svg:polygon")
|
|
.attr("points", breadcrumbPoints)
|
|
.style("fill", function(d) { return color(d.name+d.id); });
|
|
|
|
entering.append("svg:text")
|
|
.attr("x", (b.w + b.t) / 2)
|
|
.attr("y", b.h / 2)
|
|
.attr("dy", "0.35em")
|
|
.attr("text-anchor", "middle")
|
|
.text(function(d)
|
|
{
|
|
var name = d.name.substring(0,substring_limit);
|
|
if (d.name.length > substring_limit) {name = name + "..";}
|
|
return (name);
|
|
});
|
|
|
|
// Set position for entering and updating nodes.
|
|
g.attr("transform", function(d, i) {
|
|
return "translate(" + i * (b.w + b.s) + ", 0)";
|
|
});
|
|
|
|
// Remove exiting nodes.
|
|
g.exit().remove();
|
|
|
|
// Now move and update the percentage at the end.
|
|
trail.select("#endlabel")
|
|
.attr("x", (nodeArray.length + 0.5) * (b.w + b.s))
|
|
.attr("y", b.h / 2)
|
|
.attr("dy", "0.35em")
|
|
.attr("text-anchor", "middle")
|
|
.text(percentageString);
|
|
|
|
// Make the breadcrumb trail visible, if it's hidden.
|
|
trail.style("visibility", "");
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// INIT FUNCTIONS ////////////////////////////////////
|
|
///////////////////////////////////////////////////////////
|
|
|
|
function create_sequence_sunburst(circle_name, sequence_name,title,units) {
|
|
// Dimensions of sunburst.
|
|
var width = 600;
|
|
var height = 280;
|
|
var radius = 120;
|
|
// Total size of all segments; we set this later, after loading the data.
|
|
var totalSize = 0;
|
|
|
|
// Breadcrumb dimensions: width, height, spacing, width of tip/tail.
|
|
var b = {
|
|
w: 60, h: 25, s: 3, t: 10
|
|
};
|
|
|
|
//D3 helper function to create colors from an ordinal scale
|
|
var color = d3.scale.category20c();
|
|
|
|
var partition = d3.layout.partition()
|
|
.size([2 * Math.PI, radius * radius])
|
|
.value(function(d) { return d.size; });
|
|
|
|
var totalSize = 0;
|
|
|
|
//D3 helper function to draw arcs, populates parameter "d" in path object
|
|
var arc = d3.svg.arc()
|
|
.startAngle(function(d) { return d.x; })
|
|
.endAngle(function(d) { return d.x + d.dx; })
|
|
.innerRadius(function(d) { return Math.sqrt(d.y); })
|
|
.outerRadius(function(d) { return Math.sqrt(d.y + d.dy); });
|
|
|
|
|
|
var vis = d3.select("#"+circle_name).append("svg:svg")
|
|
.attr("width", width)
|
|
.attr("height", height);
|
|
|
|
var arc_group = vis.append("svg:g")
|
|
.attr("id", "container"+circle_name)
|
|
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
|
|
|
|
// Basic setup of page elements.
|
|
var trail = initializeBreadcrumbTrail(circle_name,sequence_name,width);
|
|
|
|
var whiteCircle = arc_group.append("svg:circle")
|
|
.attr("fill", "white")
|
|
.attr("r", radius);
|
|
|
|
// LABEL
|
|
totalLabel = arc_group.append("svg:text")
|
|
.attr("class", "label_sunburst")
|
|
.attr("dy", -25)
|
|
.attr("text-anchor", "middle")
|
|
.attr('font-family', 'FontAwesome')
|
|
.text("");
|
|
|
|
//PERCENT
|
|
totalValue = arc_group.append("svg:text")
|
|
.attr("class", "total")
|
|
.attr("dy", 7)
|
|
.attr("text-anchor", "middle")
|
|
.attr('font-family', 'FontAwesome')
|
|
.text("");
|
|
|
|
//UNITS LABEL
|
|
totalUnits = arc_group.append("svg:text")
|
|
.attr("class", "units")
|
|
.attr("dy",30)
|
|
.attr("text-anchor", "middle")
|
|
.text("");
|
|
|
|
return([color, partition, totalSize, arc, arc_group, trail, whiteCircle, totalLabel, totalValue, totalUnits, radius,width,height,b]);
|
|
|
|
} //End function create_sequence_sunburst
|
|
|
|
this.resetCentralCirleText = function (){
|
|
totalValue.text(" ");
|
|
totalLabel.text(" ");
|
|
totalUnits.text("");
|
|
}
|
|
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// PUBLIC FUNCTIONS ////////////////////////////////////
|
|
///////////////////////////////////////////////////////////
|
|
|
|
SequenceSunburst.prototype.setUrlParams = function(url_params) {
|
|
this.url_params = url_params;
|
|
this.resetCentralCirleText();
|
|
this.forceUpdate();
|
|
}
|
|
|
|
SequenceSunburst.prototype.forceUpdate = function(url_params) {
|
|
// this.stopInterval();
|
|
this.flashUpdate(0,1);
|
|
this.update();
|
|
// this.startInterval();
|
|
}
|
|
|
|
SequenceSunburst.prototype.setInterval = function(p_sunburstInterval) {
|
|
this.sunburstInterval = p_sunburstInterval;
|
|
}
|
|
|
|
SequenceSunburst.prototype.stopInterval = function() {
|
|
//disabled graph interval
|
|
window.clearInterval(this.sunburstInterval);
|
|
}
|
|
|
|
SequenceSunburst.prototype.startInterval = function() {
|
|
this.sunburstInterval = window.setInterval(this.update(), this.refresh)
|
|
}
|