summaryrefslogtreecommitdiffstats
path: root/static/status-dnbd3.html
diff options
context:
space:
mode:
Diffstat (limited to 'static/status-dnbd3.html')
-rw-r--r--static/status-dnbd3.html223
1 files changed, 144 insertions, 79 deletions
diff --git a/static/status-dnbd3.html b/static/status-dnbd3.html
index 5e81657..5f02fa3 100644
--- a/static/status-dnbd3.html
+++ b/static/status-dnbd3.html
@@ -6,6 +6,7 @@
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<script src="smoothie.js"></script>
<style type="text/css">
+ #graph, #statistics, #traffic {position: absolute }
.circle, .link { stroke: #56f; stroke-width: 3px; stroke-opacity: 0.75; }
.nodetext { pointer-events: none; font: 10px sans-serif; }
body { width:100%; height:100%; margin:0; padding:0; overflow: hidden; }
@@ -14,53 +15,61 @@
</head>
<body>
<div id="graph"></div>
+<div id="statistics"> </div>
<div> <canvas id="traffic" width="100%" height="150"></canvas></div>
</body>
<script type="text/javascript">
+// Initialize the statistics chart at the bottom.
var smoothie = new SmoothieChart({'millisPerPixel': 300, 'grid': {'millisPerLine': 30000}, timestampFormatter:SmoothieChart.timeFormatter});
smoothie.streamTo(document.getElementById("traffic"), 2000);
-//var line1 = new TimeSeries();
-//smoothie.addTimeSeries(line1);
+// For coloring the servers and the chart-lines.
var colorList = d3.scale.category20();
+// IDs need to begin with a letter.
+function makeId(prefix, text) {
+ return prefix + text.replace(/\./g, "-");
+}
+
function myGraph(el) {
- var changed = false;
+ var changed = false;
// Add and remove elements on the graph object
this.addNode = function (id, radius, color, distance, x, y) {
title = id;
- id = 'a' + id.replace(/\./g, "-");
+ id = makeId("a", id);
if (!distance) distance = 5;
distance *= w / 2000;
if (!radius) radius = 5;
var node = findNode(id);
+ // Add node, if it doesn't exist
if (!node) {
- nodes.push({"id":id, "title": title, "distance":distance, "radius":radius, "active":2, "x":x, "y":y, "color":color});
+ nodes.push({"id":id, "title": title, "distance":distance, "radius":radius, "lifetime":2, "x":x, "y":y, "color":color});
changed = true;
} else {
var visNode = vis.select("#" + id);
if (visNode) {
- visNode.select("title").text(id);
visNode.select("circle").attr("r", radius);
}
+
node.distance = distance;
node.radius = radius;
- node.active = 2;
+ node.lifetime = 2;
node.color = color;
+
var s = servers[title];
if (s && visNode) {
visNode.select("circle").style("fill", s.color);
- //visNode.select("#" + id).select("circle").style("stroke", color);
}
}
}
+ // Remove nodes/edges that haven't reported for a while.
this.decay = function () {
for (var i = nodes.length - 1; i >= 0; --i) {
- if ( nodes[i].active <= 0 ) {
+ if ( nodes[i].lifetime <= 0 ) {
for (var j = links.length - 1; j >= 0; --j) {
if ((links[j].source === nodes[i]) || (links[j].target === nodes[i])) links.splice(j,1);
}
@@ -68,64 +77,63 @@ function myGraph(el) {
changed = true;
continue;
}
- nodes[i].active--;
+ nodes[i].lifetime--;
}
for (var i = links.length - 1; i >= 0; --i) {
- if (links[i].active <= 0) {
+ if (links[i].lifetime <= 0) {
links.splice(i, 1);
changed = true;
continue;
}
- links[i].active--;
+ links[i].lifetime--;
}
}
- this.removeNode = function (id) {
- var i = 0;
- var n = findNode(id);
- while (i < links.length) {
- if ((links[i]['source'] === n)||(links[i]['target'] == n)) links.splice(i,1);
- else i++;
- }
- var index = findNodeIndex(id);
- if(index !== undefined) {
- nodes.splice(index, 1);
- changed = true;
- //update();
- }
- }
+// this.removeNode = function (id) {
+// var i = 0;
+// var n = findNode(id);
+// while (i < links.length) {
+// if ((links[i]['source'] === n)||(links[i]['target'] == n)) links.splice(i,1);
+// else i++;
+// }
+// var index = findNodeIndex(id);
+// if(index !== undefined) {
+// nodes.splice(index, 1);
+// changed = true;
+// }
+// }
this.addLink = function (sourceId, targetId) {
- sourceId = 'a' + sourceId.replace(/\./g, "-");
- targetId = 'a' + targetId.replace(/\./g, "-");
+
+ sourceId = makeId("a", sourceId);
+ targetId = makeId("a", targetId);
var sourceNode = findNode(sourceId);
var targetNode = findNode(targetId);
if ((sourceNode !== undefined) && (targetNode !== undefined)) {
- var link = findLink(sourceNode, targetNode);
- if (!link) {
- links.push({"source": sourceNode, "target": targetNode, "active":5});
- //update();
- changed = true;
- } else {
- link.active = 5;
- }
+ var link = findLink(sourceNode, targetNode);
+ if (!link) {
+ links.push({"source": sourceNode, "target": targetNode, "lifetime":5});
+ changed = true;
+ } else {
+ link.lifetime = 5;
+ }
}
}
var findNode = function (id) {
- for (var i=0; i < nodes.length; i++) {
+ for (var i = 0; i < nodes.length; i++) {
if (nodes[i].id === id)
return nodes[i]
}
}
var findLink = function (sourceId, targetId) {
- for (var i = 0; i < links.length; ++i) {
- if ( (links[i].source === sourceId && links[i].target === targetId)
- || (links[i].source === targetId && links[i].target === sourceId) )
- return links[i];
- }
+ for (var i = 0; i < links.length; ++i) {
+ if ( (links[i].source === sourceId && links[i].target === targetId)
+ || (links[i].source === targetId && links[i].target === sourceId) )
+ return links[i];
+ }
}
var findNodeIndex = function (id) {
@@ -138,34 +146,46 @@ function myGraph(el) {
var w = 100, h = 100;
var updateBounds = function() {
- w = window.innerWidth;
- h = window.innerHeight - 150 - 10;
+ var width = window.innerWidth;
+ // Width for the graph and the statistics div
+ w = width/2;
+ // Chart needs to fit under the graph and the statistics
+ h = window.innerHeight - 150;
vis.attr("width", w);
vis.attr("height", h);
force.size([w, h]);
$(el).attr("width", w);
$(el).attr("height", h);
- $("#traffic").attr("width", w);
+ // Positions for statistics and the traffic graph
+ $("#statistics").attr("width", w).css("width", w + "px").css("left", w + "px");
+ $("#statistics").attr("height", h).css("height", h + "px");
+ $("#traffic").attr("width", width).css("top", h + "px");
}
var vis = this.vis = d3.select(el).append("svg:svg")
.attr("width", w)
.attr("height", h);
+ // Settings for movement of the graph
var force = d3.layout.force()
+ // Force of center gravitation
.gravity(.02)
+ // Distance of the links
.distance(function(bla) { return bla.source.distance * bla.target.distance; })
+ // Strength of the links
.linkStrength(0.5)
+ // Force with which the links "pull"
.charge(function(bla) { return -bla.distance * 10 * bla.distance; })
+ // Friction for the graph nodes
.friction(0.6)
.size([w, h]);
+
var nodes = force.nodes(),
links = force.links();
this.update = function () {
- if (!changed)
- return;
+ if (!changed) return;
update();
}
@@ -175,15 +195,30 @@ function myGraph(el) {
var node = vis.selectAll("g.node")
.data(nodes, function(d) { return d.id;});
+
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("id", function(d) { return d.id;})
.on("mouseover", function(d) {
+ // Highlight statistics div
+ var statDiv = document.getElementById(makeId("b", d.title))
+ if (statDiv){
+ statDiv.setAttribute("style", "background-color:blue; color:white;");
+ }
+
+ // Increase line width of server in chart
var s = servers[d.title];
if (!s) return;
smoothie.seriesSet[s.index].options.lineWidth = 4;
})
.on("mouseout", function(d) {
+ // Make statistics div normal again
+ var statDiv = document.getElementById(makeId("b", d.title))
+ if (statDiv){
+ statDiv.setAttribute("style", "background-color:white; color:black;");
+ }
+
+ // Reset line width
var s = servers[d.title];
if (!s) return;
smoothie.seriesSet[s.index].options.lineWidth = 2;
@@ -194,7 +229,6 @@ function myGraph(el) {
.attr("r", function(d) { return d.radius; })
.style("fill", function(d) { return d.color; });
- nodeEnter.append("title");
nodeEnter.append("text")
.attr("class", "nodetext")
@@ -261,39 +295,70 @@ graph = new myGraph("#graph");
var servers = {};
var serverCount = 0;
+// Get new data
setInterval( function() {
- $.get('/data.json', function(data) {
- var g = data.graph;
- var stats = data.servers;
- if (g) {
- for (var i = 0; i < g.nodes.length; ++i) {
- graph.addNode(g.nodes[i].name, g.nodes[i].radius, g.nodes[i].color, g.nodes[i].distance, g.nodes[i].x, g.nodes[i].y);
- }
- for (var i = 0; i < g.edges.length; ++i) {
- graph.addLink(g.edges[i].source, g.edges[i].target);
- }
- }
- if (stats) {
- for (var i = 0; i < stats.length; ++i) {
- var server = servers[stats[i].address];
- if (!server) {
- servers[stats[i].address] = server = { 'lastTime': 0, 'lastSent': 0, 'line': new TimeSeries(), 'index': serverCount++ };
- server.color = colorList(server.index);
- smoothie.addTimeSeries(server['line'], {lineWidth:2, strokeStyle: server.color});
- }
- if (server['lastTime'] != 0) {
- server['line'].append(new Date().getTime(), (stats[i].bytesSent - server['lastSent'])/1000/(data.timestamp - server.lastTime));
- //smoothie.seriesSet[server.index].options.strokeStyle = 'rgba(0,255,0,0.93)';
- }
- server['lastTime'] = data.timestamp;
- server['lastSent'] = stats[i].bytesSent;
- }
+ $.get('/data.json', function(data) {
+ var g = data.graph;
+ var stats = data.servers;
+ updateGraph(g, data);
+ updateTrafficGraph(stats, data);
+ updateTextStatistics(stats);
+ }, 'json').always(function() {
+ graph.decay();
+ graph.update();
+ });
+ }, 2000);
+
+// Update data of the graph
+function updateGraph(g, data){
+ if (g) {
+ for (var i = 0; i < g.nodes.length; ++i) {
+ graph.addNode(g.nodes[i].name, g.nodes[i].radius, g.nodes[i].color, g.nodes[i].distance, g.nodes[i].x, g.nodes[i].y);
+ }
+ for (var i = 0; i < g.edges.length; ++i) {
+ graph.addLink(g.edges[i].source, g.edges[i].target);
+ }
+ }
+}
+
+// Update data of the statistics divs
+function updateTextStatistics(stats){
+ if (stats) {
+ for (var i = 0; i < stats.length; ++i) {
+ var server = document.getElementById(makeId("b", stats[i].address));
+ if (!server){
+ $("#statistics").append("<div id=" + makeId ("b", stats[i].address) + "></div>");
+ server = document.getElementById(makeId("b", stats[i].address));
+
}
+ server.innerHTML = "<p><b> Server: " + stats[i].address + "</b><br>"
+ + "Number of clients: "
+ + stats[i].clientCount + "<br>"
+ + "uptime: " + Math.floor(stats[i].uptime / (3600 * 24)) + "d "
+ + Math.floor(stats[i].uptime / 3600) % 24 + "h " + Math.floor((stats[i].uptime) / 60) % 60 + "min" + "<br>"
+ + "Sent: " + Math.floor(stats[i].bytesSent / Math.pow(1024, 3)) + "GiB <br>"
+ + "Received: " + Math.floor(stats[i].bytesReceived / Math.pow(1024, 3)) + "GiB </p>";
+ }
+ }
+}
- }, 'json').always(function() {
- graph.decay();
- graph.update();
- });
- }, 2000);
+// Update the traffic graph
+function updateTrafficGraph(stats, data){
+ if (stats) {
+ for (var i = 0; i < stats.length; ++i) {
+ var server = servers[stats[i].address];
+ if (!server) {
+ servers[stats[i].address] = server = { 'lastTime': 0, 'lastSent': 0, 'line': new TimeSeries(), 'index': serverCount++ };
+ server.color = colorList(server.index);
+ smoothie.addTimeSeries(server['line'], {lineWidth:2, strokeStyle: server.color});
+ }
+ if (server['lastTime'] != 0) {
+ server['line'].append(new Date().getTime(), (stats[i].bytesSent - server['lastSent'])/1000/(data.timestamp - server.lastTime));
+ }
+ server['lastTime'] = data.timestamp;
+ server['lastSent'] = stats[i].bytesSent;
+ }
+ }
+}
</script>