summaryrefslogtreecommitdiffstats
path: root/static/status-dnbd3.html
diff options
context:
space:
mode:
authorStephan Schwaer2015-05-21 17:45:23 +0200
committerStephan Schwaer2015-05-21 17:45:23 +0200
commit225a8d4957484745eb6cc4da6dcb3cc3f6464612 (patch)
tree1db691d4f26e1d8cb7880c7662917249b291b8c1 /static/status-dnbd3.html
parentLean and mean first prototype - to be improved! (diff)
downloaddnbd3-status-225a8d4957484745eb6cc4da6dcb3cc3f6464612.tar.gz
dnbd3-status-225a8d4957484745eb6cc4da6dcb3cc3f6464612.tar.xz
dnbd3-status-225a8d4957484745eb6cc4da6dcb3cc3f6464612.zip
Added the html file and needed libraries.
Diffstat (limited to 'static/status-dnbd3.html')
-rw-r--r--static/status-dnbd3.html299
1 files changed, 299 insertions, 0 deletions
diff --git a/static/status-dnbd3.html b/static/status-dnbd3.html
new file mode 100644
index 0000000..5e81657
--- /dev/null
+++ b/static/status-dnbd3.html
@@ -0,0 +1,299 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<html>
+<head>
+ <script src="d3.v3.min.js"></script>
+ <script type="text/javascript" src="jquery-1.7.1.min.js"></script>
+ <script src="smoothie.js"></script>
+ <style type="text/css">
+ .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; }
+ svg, div, canvas { margin:0; padding:0; }
+ </style>
+</head>
+<body>
+<div id="graph"></div>
+<div> <canvas id="traffic" width="100%" height="150"></canvas></div>
+</body>
+<script type="text/javascript">
+
+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);
+var colorList = d3.scale.category20();
+
+function myGraph(el) {
+
+ 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, "-");
+ if (!distance) distance = 5;
+ distance *= w / 2000;
+ if (!radius) radius = 5;
+ var node = findNode(id);
+ if (!node) {
+ nodes.push({"id":id, "title": title, "distance":distance, "radius":radius, "active":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.color = color;
+ var s = servers[title];
+ if (s && visNode) {
+ visNode.select("circle").style("fill", s.color);
+ //visNode.select("#" + id).select("circle").style("stroke", color);
+ }
+ }
+ }
+
+ this.decay = function () {
+ for (var i = nodes.length - 1; i >= 0; --i) {
+ if ( nodes[i].active <= 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);
+ }
+ nodes.splice(i, 1);
+ changed = true;
+ continue;
+ }
+ nodes[i].active--;
+ }
+ for (var i = links.length - 1; i >= 0; --i) {
+ if (links[i].active <= 0) {
+ links.splice(i, 1);
+ changed = true;
+ continue;
+ }
+ links[i].active--;
+ }
+ }
+
+ 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.addLink = function (sourceId, targetId) {
+ sourceId = 'a' + sourceId.replace(/\./g, "-");
+ targetId = 'a' + targetId.replace(/\./g, "-");
+ 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 findNode = function (id) {
+ 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];
+ }
+ }
+
+ var findNodeIndex = function (id) {
+ for (var i=0; i < nodes.length; i++) {
+ if (nodes[i].id === id)
+ return i
+ };
+ }
+
+ var w = 100, h = 100;
+
+ var updateBounds = function() {
+ w = window.innerWidth;
+ h = window.innerHeight - 150 - 10;
+ vis.attr("width", w);
+ vis.attr("height", h);
+ force.size([w, h]);
+ $(el).attr("width", w);
+ $(el).attr("height", h);
+ $("#traffic").attr("width", w);
+ }
+
+ var vis = this.vis = d3.select(el).append("svg:svg")
+ .attr("width", w)
+ .attr("height", h);
+
+ var force = d3.layout.force()
+ .gravity(.02)
+ .distance(function(bla) { return bla.source.distance * bla.target.distance; })
+ .linkStrength(0.5)
+ .charge(function(bla) { return -bla.distance * 10 * bla.distance; })
+ .friction(0.6)
+ .size([w, h]);
+
+ var nodes = force.nodes(),
+ links = force.links();
+
+ this.update = function () {
+ if (!changed)
+ return;
+ update();
+ }
+
+ var update = function () {
+ changed = false;
+
+ 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) {
+ var s = servers[d.title];
+ if (!s) return;
+ smoothie.seriesSet[s.index].options.lineWidth = 4;
+ })
+ .on("mouseout", function(d) {
+ var s = servers[d.title];
+ if (!s) return;
+ smoothie.seriesSet[s.index].options.lineWidth = 2;
+ });
+
+ nodeEnter.append("circle")
+ .attr("class", "circle")
+ .attr("r", function(d) { return d.radius; })
+ .style("fill", function(d) { return d.color; });
+
+ nodeEnter.append("title");
+
+ nodeEnter.append("text")
+ .attr("class", "nodetext")
+ .attr("dx", -32)
+ .attr("dy", "-1em")
+ .text(function(d) {return d.title});
+
+ node.exit().remove();
+
+ var link = vis.selectAll("line.link")
+ .data(links, function(d) { return d.source.id + "-" + d.target.id; });
+
+ link.enter().insert("line")
+ .attr("class", "link");
+
+ link.exit().remove();
+
+ vis.selectAll('g.node').forEach(function(e){$('#graph').find('svg').append(e)});
+
+ var render = function() {
+ var fixX = function(x) {
+ return (x - lx) * scale + 20 + offX;
+ }
+ var fixY = function(y) {
+ return (y - ly) * scale + 20 + offY;
+ }
+ var lx = 1000, ly = 1000, ux = -1000, uy = -1000;
+ for (var i = 0; i < nodes.length; ++i) {
+ if (nodes[i].x < lx) lx = nodes[i].x;
+ if (nodes[i].x > ux) ux = nodes[i].x;
+ if (nodes[i].y < ly) ly = nodes[i].y;
+ if (nodes[i].y > uy) uy = nodes[i].y;
+ }
+ var width = (ux - lx), height = (uy - ly);
+ var scale;
+ var offX = 0, offY = 0;
+ if ( (width / w) > (height / h) ) {
+ scale = (w - 40) / width;
+ offY = (h - (height * scale + 20)) / 2;
+ } else {
+ scale = (h - 40) / height;
+ offX = (w - (width * scale + 20)) / 2;
+ }
+ link.attr("x1", function(d) { return fixX(d.source.x); })
+ .attr("y1", function(d) { return fixY(d.source.y); })
+ .attr("x2", function(d) { return fixX(d.target.x); })
+ .attr("y2", function(d) { return fixY(d.target.y); });
+
+ node.attr("transform", function(d) { return "translate(" + fixX(d.x) + "," + fixY(d.y) + ")"; });
+ };
+
+ force.on("tick", render);
+
+ updateBounds();
+ force.start();
+ }
+
+ update();
+ $( window ).resize( update );
+}
+
+graph = new myGraph("#graph");
+
+var servers = {};
+var serverCount = 0;
+
+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;
+ }
+ }
+
+ }, 'json').always(function() {
+ graph.decay();
+ graph.update();
+ });
+ }, 2000);
+
+</script>