You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by bi...@apache.org on 2012/05/15 18:56:45 UTC
svn commit: r1338793 - in /accumulo/trunk/server/src/main:
java/org/apache/accumulo/server/monitor/
java/org/apache/accumulo/server/monitor/servlets/ resources/web/
Author: billie
Date: Tue May 15 16:56:45 2012
New Revision: 1338793
URL: http://svn.apache.org/viewvc?rev=1338793&view=rev
Log:
ACCUMULO-453 converted server activity to use json instead of xml
Added:
accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/JSONServlet.java (with props)
Modified:
accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/Monitor.java
accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/BasicServlet.java
accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/VisServlet.java
accumulo/trunk/server/src/main/resources/web/vis.xml
Modified: accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/Monitor.java
URL: http://svn.apache.org/viewvc/accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/Monitor.java?rev=1338793&r1=1338792&r2=1338793&view=diff
==============================================================================
--- accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/Monitor.java (original)
+++ accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/Monitor.java Tue May 15 16:56:45 2012
@@ -54,6 +54,7 @@ import org.apache.accumulo.server.client
import org.apache.accumulo.server.conf.ServerConfiguration;
import org.apache.accumulo.server.monitor.servlets.DefaultServlet;
import org.apache.accumulo.server.monitor.servlets.GcStatusServlet;
+import org.apache.accumulo.server.monitor.servlets.JSONServlet;
import org.apache.accumulo.server.monitor.servlets.LogServlet;
import org.apache.accumulo.server.monitor.servlets.LoggersServlet;
import org.apache.accumulo.server.monitor.servlets.MasterServlet;
@@ -480,6 +481,7 @@ public class Monitor {
server.addServlet(GcStatusServlet.class, "/gc");
server.addServlet(LogServlet.class, "/log");
server.addServlet(XMLServlet.class, "/xml");
+ server.addServlet(JSONServlet.class, "/json");
server.addServlet(VisServlet.class, "/vis");
server.addServlet(Summary.class, "/trace/summary");
server.addServlet(ListType.class, "/trace/listType");
Modified: accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/BasicServlet.java
URL: http://svn.apache.org/viewvc/accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/BasicServlet.java?rev=1338793&r1=1338792&r2=1338793&view=diff
==============================================================================
--- accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/BasicServlet.java (original)
+++ accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/BasicServlet.java Tue May 15 16:56:45 2012
@@ -115,6 +115,22 @@ abstract public class BasicServlet exten
}
// BEGIN PAGE
+ sb.append("<!--\n");
+ sb.append(" Licensed to the Apache Software Foundation (ASF) under one or more\n");
+ sb.append(" contributor license agreements. See the NOTICE file distributed with\n");
+ sb.append(" this work for additional information regarding copyright ownership.\n");
+ sb.append(" The ASF licenses this file to You under the Apache License, Version 2.0\n");
+ sb.append(" (the \"License\"); you may not use this file except in compliance with\n");
+ sb.append(" the License. You may obtain a copy of the License at\n");
+ sb.append("\n");
+ sb.append(" http://www.apache.org/licenses/LICENSE-2.0\n");
+ sb.append("\n");
+ sb.append(" Unless required by applicable law or agreed to in writing, software\n");
+ sb.append(" distributed under the License is distributed on an \"AS IS\" BASIS,\n");
+ sb.append(" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n");
+ sb.append(" See the License for the specific language governing permissions and\n");
+ sb.append(" limitations under the License.\n");
+ sb.append("-->\n");
sb.append("<html>\n");
// BEGIN HEADER
@@ -172,7 +188,8 @@ abstract public class BasicServlet exten
if (numProblems > 0)
sb.append("<span class='error'><a href='/problems'>Table Problems <span class='smalltext'>(" + numProblems + ")</a></span></span><br />\n");
sb.append("<hr />\n");
- sb.append("<a href='/xml'>XML</a><hr />\n");
+ sb.append("<a href='/xml'>XML</a><br />\n");
+ sb.append("<a href='/json'>JSON</a><hr />\n");
sb.append("<div class='smalltext'>[<a href='").append("/op?action=refresh&value=").append(refresh < 1 ? "5" : "-1");
sb.append("&redir=").append(currentPage(req)).append("'>");
sb.append(refresh < 1 ? "en" : "dis").append("able auto-refresh</a>]</div>\n");
Added: accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/JSONServlet.java
URL: http://svn.apache.org/viewvc/accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/JSONServlet.java?rev=1338793&view=auto
==============================================================================
--- accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/JSONServlet.java (added)
+++ accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/JSONServlet.java Tue May 15 16:56:45 2012
@@ -0,0 +1,80 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.accumulo.server.monitor.servlets;
+
+import java.util.Map.Entry;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.accumulo.core.master.thrift.DeadServer;
+import org.apache.accumulo.core.master.thrift.TableInfo;
+import org.apache.accumulo.core.master.thrift.TabletServerStatus;
+import org.apache.accumulo.server.monitor.Monitor;
+import org.apache.accumulo.server.monitor.util.celltypes.TServerLinkType;
+
+public class JSONServlet extends BasicServlet {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected String getTitle(HttpServletRequest req) {
+ return "JSON Report";
+ }
+
+ @Override
+ protected void pageStart(HttpServletRequest req, HttpServletResponse resp, StringBuilder sb) {
+ resp.setContentType("application/json");
+ sb.append("{ 'servers': [\n");
+ }
+
+ private static void addServerLine(StringBuilder sb, String ip, String hostname, double osload, double ingest, double query, double ingestMB, double queryMB,
+ int scans, double scansessions, long holdtime) {
+ sb.append(" {'ip': '").append(ip).append("',\n 'hostname': '").append(hostname).append("',\n 'osload': ").append(osload).append(",\n 'ingest': ")
+ .append(ingest).append(",\n 'query': ").append(query).append(",\n 'ingestMB': ").append(ingestMB).append(",\n 'queryMB': ").append(queryMB)
+ .append(",\n 'scans': ").append(scans).append(",\n 'scansessions': ").append(scansessions).append(",\n 'holdtime': ").append(holdtime)
+ .append("},\n");
+ }
+
+ @Override
+ protected void pageBody(HttpServletRequest req, HttpServletResponse resp, StringBuilder sb) {
+ if (Monitor.getMmi() == null || Monitor.getMmi().tableMap == null) {
+ return;
+ }
+
+ for (TabletServerStatus status : Monitor.getMmi().tServerInfo) {
+ TableInfo summary = Monitor.summarizeTableStats(status);
+ addServerLine(sb, status.name, TServerLinkType.displayName(status.name), status.osLoad, summary.ingestRate, summary.queryRate,
+ summary.ingestByteRate / 1000000.0, summary.queryByteRate / 1000000.0, summary.scans.running + summary.scans.queued, Monitor.getLookupRate(),
+ status.holdTime);
+ }
+
+ for (Entry<String,Byte> entry : Monitor.getMmi().badTServers.entrySet()) {
+ sb.append(" {'ip': '").append(entry.getKey()).append("',\n 'bad':true},\n");
+ }
+
+ for (DeadServer dead : Monitor.getMmi().deadTabletServers) {
+ sb.append(" {'ip': '").append(dead.server).append("',\n 'dead': true},\n");
+ }
+ if (Monitor.getMmi().tServerInfo.size() > 0 || Monitor.getMmi().badTServers.size() > 0 || Monitor.getMmi().deadTabletServers.size() > 0)
+ sb.setLength(sb.length() - 2);
+ }
+
+ @Override
+ protected void pageEnd(HttpServletRequest req, HttpServletResponse resp, StringBuilder sb) {
+ sb.append("\n ]\n}\n");
+ }
+}
Propchange: accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/JSONServlet.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/VisServlet.java
URL: http://svn.apache.org/viewvc/accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/VisServlet.java?rev=1338793&r1=1338792&r2=1338793&view=diff
==============================================================================
--- accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/VisServlet.java (original)
+++ accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/VisServlet.java Tue May 15 16:56:45 2012
@@ -204,30 +204,30 @@ public class VisServlet extends BasicSer
// initialization of some javascript variables
sb.append("<script type='text/javascript'>\n");
sb.append("var numCores = " + ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors() + ";\n");
- sb.append("var xmlurl = '" + url + "xml';\n");
+ sb.append("var jsonurl = '" + url + "json';\n");
sb.append("var visurl = '" + url + "vis';\n");
sb.append("var serverurl = '" + url + "tservers?s=';\n\n");
sb.append("// observable stats that can be connected to motion or color\n");
- sb.append("var statName = [");
+ sb.append("var statNames = {");
for (StatType st : StatType.values())
- sb.append("'").append(st).append("',");
+ sb.append("'").append(st).append("': ").append(st.derived).append(",");
sb.setLength(sb.length() - 1);
- sb.append("];\n");
- sb.append("var maxStatValue = [");
+ sb.append("};\n");
+ sb.append("var maxStatValues = {");
for (StatType st : StatType.values())
- sb.append(st.getMax()).append(",");
- sb.setLength(sb.length() - 1);
- sb.append("]; // initial values that are system-dependent may increase based on observed values\n");
- sb.append("var adjustMax = [");
+ sb.append("'").append(st).append("': ").append(st.getMax()).append(", ");
+ sb.setLength(sb.length() - 2);
+ sb.append("}; // initial values that are system-dependent may increase based on observed values\n");
+ sb.append("var adjustMax = {");
for (StatType st : StatType.values())
- sb.append(st.getAdjustMax()).append(",");
- sb.setLength(sb.length() - 1);
- sb.append("]; // whether to allow increases in the max based on observed values\n");
- sb.append("var significance = [");
+ sb.append("'").append(st).append("': ").append(st.getAdjustMax()).append(", ");
+ sb.setLength(sb.length() - 2);
+ sb.append("}; // whether to allow increases in the max based on observed values\n");
+ sb.append("var significance = {");
for (StatType st : StatType.values())
- sb.append(st.getSignificance()).append(",");
- sb.setLength(sb.length() - 1);
- sb.append("]; // values will be converted by floor(this*value)/this\n");
+ sb.append("'").append(st).append("': ").append(st.getSignificance()).append(", ");
+ sb.setLength(sb.length() - 2);
+ sb.append("}; // values will be converted by floor(this*value)/this\n");
sb.append("var numNormalStats = ").append(StatType.values().length - StatType.numDerived()).append(";\n");
sb.append("</script>\n");
Modified: accumulo/trunk/server/src/main/resources/web/vis.xml
URL: http://svn.apache.org/viewvc/accumulo/trunk/server/src/main/resources/web/vis.xml?rev=1338793&r1=1338792&r2=1338793&view=diff
==============================================================================
--- accumulo/trunk/server/src/main/resources/web/vis.xml (original)
+++ accumulo/trunk/server/src/main/resources/web/vis.xml Tue May 15 16:56:45 2012
@@ -17,27 +17,23 @@
<script type='text/javascript'>
// size and spacing variables
-var numDots = 0; // number of dots to draw
-var numLive = 0;
var dotSpacing = 10; // spacing between centers of dots (radius)
var dotPadding = 0.5; // dot padding
var minDotRadius = 3; // min dot radius
var maxDotRadius = dotSpacing - dotPadding;
// arrays of information about each dot
-var dotSize = new Array(numDots); // current sizes
-var dotSizeGrowing = new Array(numDots); // true when dot size is growing, false when shrinking
-var ids = new Array(numDots); // server ids
+var stats = {'servers': []};
+var dots = new Array(0); // current sizes and change directions
var mousedDot = -1; // the dot currently under the mouse
-var allStats = new Array(numDots);
var colorPalette = ['#0000CC', '#0014B8', '#0029A3', '#003D8F', '#00527A', '#006666', '#007A52', '#008F3D', '#00A329', '#00B814', '#00CC00', '#14D100', '#29D600', '#3DDB00', '#52E000', '#66E600', '#7AEB00', '#8FF000', '#A3F500', '#B8FA00', '#CCFF00', '#CCFF00', '#CCF200', '#CCE600', '#CCD900', '#CCCC00', '#CCBF00', '#CCB200', '#CCA600', '#CC9900', '#CC8C00', '#CC8000', '#CC7300', '#CC6600', '#CC5900', '#CC4C00', '#CC4000', '#CC3300', '#CC2600', '#CC1A00', '#CC0D00', '#CC0000'];
var nullColor = '#F5F8FA';
var deadColor = '#B000CC';
// animation variables
-var frame = 0;
+var drawing = false;
var canvas = document.getElementById('visCanvas');
var context = canvas.getContext('2d');
@@ -50,20 +46,22 @@ canvas.addEventListener('click', goToSer
// initialize settings based on request parameters
var main = document.getElementById('main');
-var speedStatType = document.getElementById('motion').selectedIndex; // index into statName
-var colorStatType = document.getElementById('color').selectedIndex; // index into statName
+var speedStatType;
+var colorStatType;
var useCircles = true;
setShape(document.getElementById('shape'));
setSize(document.getElementById('size'));
+setMotion(document.getElementById('motion'));
+setColor(document.getElementById('color'));
// xml loading variables
var xmlReturned = true;
var xmlhttp=new XMLHttpRequest(); // don't bother allowing for IE 5 or 6 since canvas won't work
-xmlhttp.overrideMimeType("text/xml");
xmlhttp.onreadystatechange=function() {
handleNewData();
}
self.setInterval("getXML()",5000);
+//self.setInterval("drawDots()",20);
window.requestAnimFrame = (function(callback){
return window.requestAnimationFrame ||
@@ -80,110 +78,76 @@ function handleNewData() {
if (xmlhttp.readyState!=4) {
return;
}
- if (xmlhttp.status!=200 || xmlhttp.responseXML==null) {
+ if (xmlhttp.status!=200 || xmlhttp.responseText==null) {
xmlReturned = true;
return;
}
- var statinfo = new Array(numNormalStats);
- for (j=0; j < numNormalStats; j++)
- statinfo[j] = xmlhttp.responseXML.getElementsByTagName(statName[j]);
- var deadinfo = xmlhttp.responseXML.getElementsByTagName('deadTabletServer');
- var badinfo = xmlhttp.responseXML.getElementsByTagName('badTabletServer');
- var idinfo = xmlhttp.responseXML.getElementsByTagName('server');
- var hostinfo = xmlhttp.responseXML.getElementsByTagName('hostname');
-
- var statValues = new Array(numNormalStats);
- for (i=0; i < idinfo.length; i++) {
- var info = idinfo[i].attributes[0].nodeValue;
- var host = hostinfo[i].childNodes[0].nodeValue;
- for (j=0; j < numNormalStats; j++) {
- statValues[j] = Math.max(0,Math.floor(significance[j]*parseFloat(statinfo[j][i].childNodes[0].nodeValue))/significance[j]);
+ var newstats = eval('(' + xmlhttp.responseText + ')');
+ for (var i in newstats.servers) {
+ for (var s in statNames) {
+ if (statNames[s])
+ continue;
+ newstats.servers[i][s] = Math.max(0,Math.floor(significance[s]*newstats.servers[i][s])/significance[s]);
+ if (adjustMax[s])
+ maxStatValues[s] = Math.max(newstats.servers[i][s],maxStatValues[s]);
}
- setStats(statValues,i);
- setDotInfo(info,host,i);
}
- numLive = idinfo.length;
- resetOverallStats();
- for (i=idinfo.length,j=0; j < deadinfo.length; i++,j++) {
- setDotInfo(deadinfo[j].attributes[0].nodeValue,'',i);
- }
- for (i=idinfo.length+deadinfo.length,j=0; j < badinfo.length; i++,j++) {
- setDotInfo(badinfo[j].attributes[0].nodeValue,'',i);
- }
- if (numDots != idinfo.length + deadinfo.length + badinfo.length)
- drawGrid();
- numDots = idinfo.length + deadinfo.length + badinfo.length;
+ initDerivedInfo(newstats);
+ var oldstats = stats;
+ while(drawing) {}
+ stats = newstats;
+ delete oldstats;
xmlReturned = true;
}
-// set the data for a given server
-function setStats(statValues,index) {
- var newStats = new Array(numNormalStats+3);
- for (j=0; j < numNormalStats; j++) {
- if (adjustMax[j])
- maxStatValue[j] = Math.max(statValues[j],maxStatValue[j]);
- newStats[j] = statValues[j];
- }
- setOverallStats(newStats);
- if (index >= allStats.length)
- allStats.push(newStats);
- else
- allStats[index] = newStats;
-}
-
// set max and average
-function setOverallStats(statValues) {
- avgStat = 0;
- maxStat = 0;
- maxIndex = 0;
- for (j=0; j < numNormalStats; j++) {
- normStat = statValues[j]/maxStatValue[j];
+function setDerivedStats(serverStats) {
+ var avgStat = 0;
+ var maxStat = 0;
+ var maxIndex = 0;
+ for (var s in statNames) {
+ if (statNames[s])
+ continue;
+ normStat = serverStats[s]/maxStatValues[s];
if (normStat > 0)
avgStat += normStat;
if (maxStat < normStat) {
maxStat = normStat;
- maxIndex = j;
+ maxIndex = s;
}
}
- avgStat = avgStat/numNormalStats;
- maxStat = Math.min(1,maxStat);
- statValues[numNormalStats] = Math.floor(significance[numNormalStats]*avgStat)/significance[numNormalStats];
- statValues[numNormalStats+1] = Math.floor(significance[numNormalStats+1]*maxStat)/significance[numNormalStats+1];
- statValues[numNormalStats+2] = maxIndex;
-}
-
-// reset max and average for all servers (global maxes may have changed)
-function resetOverallStats() {
- for (i=0; i < numLive; i++) {
- setOverallStats(allStats[i]);
- }
+ serverStats.allmax = Math.floor(significance.allmax*Math.min(1,maxStat))/significance.allmax;
+ serverStats.allavg = Math.floor(significance.allavg*avgStat/numNormalStats)/significance.allavg;
+ serverStats.maxStat = maxIndex;
}
-// initialize or update dot info
-function setDotInfo(id,host,index) {
- if (index >= ids.length) {
- ids.push([id,host]);
- dotSize.push(maxDotRadius);
- dotSizeGrowing.push(false);
- } else {
- ids[index] = [id,host];
- // keep existing size and direction
+function initDerivedInfo(newstats) {
+ for (var i in newstats.servers) {
+ if ('dead' in newstats.servers[i] || 'bad' in newstats.servers[i]) {
+ continue;
+ }
+ if (i >= dots.length) {
+ dots.push({'size': maxDotRadius, 'growing': false});
+ }
+ setDerivedStats(newstats.servers[i]);
}
}
// construct server info for hover
-function getInfo(i) {
- var extra = '<strong>' + ids[i][0] + '</strong>';
- if (i < numLive) {
- extra = extra + ' (' + ids[i][1] + ')';
- for (j=0; j < numNormalStats; j++) {
- if (j % 4 == 0)
- extra = extra + '<br>\n';
- extra = extra + ' ' + statName[j] + ': <strong>' + allStats[i][j] + '</strong>';
- }
- extra = extra + '<br>\n avg: <strong>' + allStats[i][numNormalStats] + '</strong> max: <strong>' + allStats[i][numNormalStats+1] + '</strong> (' + statName[allStats[i][numNormalStats+2]] + ')';
+function getInfo(serverStats) {
+ var extra = '<strong>' + serverStats.ip + '</strong>';
+ if ('dead' in serverStats || 'bad' in serverStats)
+ return extra;
+ extra = extra + ' (' + serverStats.hostname + ')';
+ var j = 0;
+ for (var s in statNames) {
+ if (j % 4 == 0)
+ extra = extra + '<br>\n';
+ extra = extra + ' ' + s + ': <strong>' + serverStats[s] + '</strong>';
+ j++;
}
+ extra = extra + ' (' + serverStats.maxStat + ')';
return extra;
}
@@ -191,7 +155,7 @@ function getInfo(i) {
function getXML() {
if (xmlReturned == true) {
xmlReturned = false;
- xmlhttp.open('POST',xmlurl,true);
+ xmlhttp.open('POST',jsonurl,true);
xmlhttp.send();
}
}
@@ -200,54 +164,58 @@ function getXML() {
function drawDots() {
requestAnimFrame(drawDots);
- frame++;
-
- var width = Math.ceil(Math.sqrt(numDots));
- var height = Math.ceil(numDots/width);
+ var width = Math.ceil(Math.sqrt(stats.servers.length));
+ var height = Math.ceil(stats.servers.length/width);
var x;
var y;
+ var server
var sizeChange;
- for (i=0; i < numDots; i++) {
- if (Math.floor(dotSize[i]) > maxDotRadius) {
+ drawing = true;
+ for (var i in stats.servers) {
+ server = stats.servers[i];
+ x = i % width;
+ y = Math.floor(i / width);
+ if ('bad' in server || 'dead' in server) {
+ strokeDot(x,y,maxDotRadius-1,deadColor);
+ continue;
+ }
+ if (Math.floor(dots[i].size) > maxDotRadius) {
// check for resize by the user
- dotSize[i] = maxDotRadius;
- } else if (i >= numLive || allStats[i][speedStatType]<=0) {
+ dots[i].size = maxDotRadius;
+ } else if (server[speedStatType]<=0) {
// if not changing size, increase to max radius
- if (dotSize[i] < maxDotRadius)
- dotSize[i] = dotSize[i] + 1;
- if (dotSize[i] > maxDotRadius)
- dotSize[i] = maxDotRadius;
+ if (dots[i].size < maxDotRadius)
+ dots[i].size = dots[i].size + 1;
+ if (dots[i].size > maxDotRadius)
+ dots[i].size = maxDotRadius;
} else {
sizeChange = getStat(i,speedStatType);
- if (dotSizeGrowing[i]) {
- dotSize[i] = dotSize[i] + sizeChange;
- if (dotSize[i] + sizeChange > maxDotRadius) {
- dotSizeGrowing[i] = false;
+ if (dots[i].growing) {
+ dots[i].size = dots[i].size + sizeChange;
+ if (dots[i].size + sizeChange > maxDotRadius) {
+ dots[i].growing = false;
}
}
else {
- dotSize[i] = dotSize[i] - sizeChange;
- if (dotSize[i] - sizeChange < minDotRadius) {
- dotSizeGrowing[i] = true;
+ dots[i].size = dots[i].size - sizeChange;
+ if (dots[i].size - sizeChange < minDotRadius) {
+ dots[i].growing = true;
}
}
}
- x = i % width;
- y = Math.floor(i / width);
- if (i >= numLive)
- strokeDot(x,y,maxDotRadius-1,deadColor);
- else
- drawDot(x,y,Math.floor(dotSize[i]),getColor(getStat(i,colorStatType)));
+ drawDot(x,y,Math.floor(dots[i].size),getColor(getStat(i,colorStatType)));
}
- if (mousedDot >= 0 && mousedDot < numDots)
- document.getElementById('vishoverinfo').innerHTML=getInfo(mousedDot);
+ // mousedDot shouldn't be set to an invalid dot, but stats might have changed since then
+ if (mousedDot >= 0 && mousedDot < stats.servers.length)
+ document.getElementById('vishoverinfo').innerHTML=getInfo(stats.servers[mousedDot]);
+ drawing = false;
}
// fill in a few grey dots
function drawGrid() {
context.clearRect(0, 0, canvas.width, canvas.height);
- for (i=0,k=0; i < canvas.width; i+=dotSpacing*2,k++) {
- for (j=0,l=0; j < canvas.height; j+=dotSpacing*2,l++) {
+ for (var i=0, k=0; i < canvas.width; i+=dotSpacing*2,k++) {
+ for (var j=0, l=0; j < canvas.height; j+=dotSpacing*2,l++) {
drawDot(k,l,maxDotRadius,nullColor);
}
}
@@ -255,8 +223,8 @@ function drawGrid() {
// fill a dot specified by indices into dot grid
function drawDot(i,j,r,c) {
- x = i*dotSpacing*2 + dotSpacing;
- y = j*dotSpacing*2 + dotSpacing;
+ var x = i*dotSpacing*2 + dotSpacing;
+ var y = j*dotSpacing*2 + dotSpacing;
context.clearRect(x-dotSpacing, y-dotSpacing, dotSpacing*2, dotSpacing*2);
if (useCircles)
fillCircle(x,y,r-dotPadding,c);
@@ -266,8 +234,8 @@ function drawDot(i,j,r,c) {
// stroke a dot specified by indices into dot grid
function strokeDot(i,j,r,c) {
- x = i*dotSpacing*2 + dotSpacing;
- y = j*dotSpacing*2 + dotSpacing;
+ var x = i*dotSpacing*2 + dotSpacing;
+ var y = j*dotSpacing*2 + dotSpacing;
context.clearRect(x-dotSpacing, y-dotSpacing, dotSpacing*2, dotSpacing*2);
if (useCircles)
strokeCircle(x,y,r-dotPadding,c);
@@ -276,7 +244,7 @@ function strokeDot(i,j,r,c) {
}
function getStat(dotIndex,statIndex) {
- return Math.min(1,allStats[dotIndex][statIndex]/maxStatValue[statIndex]);
+ return Math.min(1,stats.servers[dotIndex][statIndex]/maxStatValues[statIndex]);
}
// translate color between 0 and maxObservedColor into an html color code
@@ -358,13 +326,27 @@ function setSize(obj) {
// callback for motion selection
function setMotion(obj) {
- speedStatType = obj.selectedIndex;
+ var i = 0;
+ for (var s in statNames) {
+ if (i==obj.selectedIndex) {
+ speedStatType = s;
+ break;
+ }
+ i++;
+ }
setState();
}
// callback for color selection
function setColor(obj) {
- colorStatType = obj.selectedIndex;
+ var i = 0;
+ for (var s in statNames) {
+ if (i==obj.selectedIndex) {
+ colorStatType = s;
+ break;
+ }
+ i++;
+ }
setState();
}
@@ -387,9 +369,11 @@ function showId(e) {
}
var relx = x - canvas.offsetLeft - main.offsetLeft;
var rely = y - canvas.offsetTop - main.offsetTop;
- var width = Math.ceil(Math.sqrt(numDots));
- mousedDot = Math.floor(relx/(dotSpacing*2)) + width*Math.floor(rely/(dotSpacing*2));
- if (relx < (width*dotSpacing*2) && mousedDot >= 0 && mousedDot < numDots) {
+ var width = Math.ceil(Math.sqrt(stats.servers.length));
+ gotDot = Math.floor(relx/(dotSpacing*2)) + width*Math.floor(rely/(dotSpacing*2));
+ mousedDot = -1;
+ if (relx < (width*dotSpacing*2) && gotDot >= 0 && gotDot < stats.servers.length) {
+ mousedDot = gotDot;
document.getElementById('vishoverinfo').style.left=relx+canvas.offsetLeft;
document.getElementById('vishoverinfo').style.top=Math.max(0,rely+canvas.offsetTop-70);
document.getElementById('vishoverinfo').style.visibility='visible';
@@ -400,14 +384,15 @@ function showId(e) {
}
function setState() {
- var url = visurl+'?shape='+(useCircles?'circles':'squares')+'&size='+(dotSpacing*2)+'&motion='+statName[speedStatType]+'&color='+statName[colorStatType];
+ var url = visurl+'?shape='+(useCircles?'circles':'squares')+'&size='+(dotSpacing*2)+'&motion='+speedStatType+'&color='+colorStatType;
window.history.replaceState(window.history.state,'Server Activity',url);
}
// go to server page on click
function goToServer(e) {
- if (mousedDot >= 0 && mousedDot < numDots)
- window.location = serverurl + ids[mousedDot][0];
+ // mousedDot shouldn't be set to an invalid dot, but stats might have changed since then
+ if (mousedDot >= 0 && mousedDot < stats.servers.length)
+ window.location = serverurl + stats.servers[mousedDot].ip;
}
window.onload = function() {