Return-Path: X-Original-To: apmail-accumulo-commits-archive@www.apache.org Delivered-To: apmail-accumulo-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B2C5395A7 for ; Tue, 14 Aug 2012 17:26:31 +0000 (UTC) Received: (qmail 25118 invoked by uid 500); 14 Aug 2012 17:26:31 -0000 Delivered-To: apmail-accumulo-commits-archive@accumulo.apache.org Received: (qmail 25067 invoked by uid 500); 14 Aug 2012 17:26:31 -0000 Mailing-List: contact commits-help@accumulo.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@accumulo.apache.org Delivered-To: mailing list commits@accumulo.apache.org Received: (qmail 25056 invoked by uid 99); 14 Aug 2012 17:26:31 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 14 Aug 2012 17:26:31 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 14 Aug 2012 17:26:29 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id DDED423889FA for ; Tue, 14 Aug 2012 17:25:45 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1372990 - in /accumulo/trunk/server/src/main: java/org/apache/accumulo/server/monitor/servlets/VisServlet.java resources/web/vis.js resources/web/vis.xml Date: Tue, 14 Aug 2012 17:25:45 -0000 To: commits@accumulo.apache.org From: billie@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120814172545.DDED423889FA@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: billie Date: Tue Aug 14 17:25:45 2012 New Revision: 1372990 URL: http://svn.apache.org/viewvc?rev=1372990&view=rev Log: ACCUMULO-453 changed inclusion of vis script, fixed null url bug in trunk Added: accumulo/trunk/server/src/main/resources/web/vis.js (with props) Removed: accumulo/trunk/server/src/main/resources/web/vis.xml Modified: accumulo/trunk/server/src/main/java/org/apache/accumulo/server/monitor/servlets/VisServlet.java 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=1372990&r1=1372989&r2=1372990&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 Aug 14 17:25:45 2012 @@ -17,7 +17,6 @@ package org.apache.accumulo.server.monitor.servlets; import java.io.IOException; -import java.io.InputStream; import java.lang.management.ManagementFactory; import java.util.ArrayList; @@ -119,8 +118,8 @@ public class VisServlet extends BasicSer protected void pageBody(HttpServletRequest req, HttpServletResponse response, StringBuilder sb) throws IOException { StringBuffer urlsb = req.getRequestURL(); urlsb.setLength(urlsb.lastIndexOf("/") + 1); - String url = urlsb.toString(); VisualizationConfig cfg = new VisualizationConfig(); + cfg.url = urlsb.toString(); String s = req.getParameter("shape"); if (s != null && (s.equals("square") || s.equals("squares"))) { @@ -231,18 +230,6 @@ public class VisServlet extends BasicSer sb.append("var numNormalStats = ").append(StatType.values().length - StatType.numDerived()).append(";\n"); sb.append("\n"); - InputStream data = VisServlet.class.getClassLoader().getResourceAsStream("web/vis.xml"); - if (data != null) { - byte[] buffer = new byte[1024]; - int n; - try { - while ((n = data.read(buffer)) > 0) - sb.append(new String(buffer, 0, n)); - } catch (IOException e) { - e.printStackTrace(); - return; - } - } - sb.append("\n"); + sb.append(""); } } Added: accumulo/trunk/server/src/main/resources/web/vis.js URL: http://svn.apache.org/viewvc/accumulo/trunk/server/src/main/resources/web/vis.js?rev=1372990&view=auto ============================================================================== --- accumulo/trunk/server/src/main/resources/web/vis.js (added) +++ accumulo/trunk/server/src/main/resources/web/vis.js Tue Aug 14 17:25:45 2012 @@ -0,0 +1,402 @@ +/* + * 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. + */ + +// size and spacing variables +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 stats = {'servers': []}; +var dots = new Array(0); // current sizes and change directions +var mousedDot = -1; // the dot currently under the mouse + +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 drawing = false; +var canvas = document.getElementById('visCanvas'); +var context = canvas.getContext('2d'); + +// mouse handling for server information display +document.getElementById('hoverable').addEventListener('mouseover', showId, false); +document.getElementById('hoverable').addEventListener('mousemove', showId, false); +document.getElementById('hoverable').addEventListener('mouseout', hideId, false); +document.getElementById('vishoverinfo').addEventListener('click', goToServer, false); +canvas.addEventListener('click', goToServer, false); + +// initialize settings based on request parameters +var main = document.getElementById('main'); +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.onreadystatechange=function() { + handleNewData(); +} +self.setInterval("getXML()",5000); +//self.setInterval("drawDots()",20); + +window.requestAnimFrame = (function(callback){ + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function(callback){ + window.setTimeout(callback, 1000 / 60); + }; +})(); + +function handleNewData() { + if (xmlhttp.readyState!=4) { + return; + } + if (xmlhttp.status!=200 || xmlhttp.responseText==null) { + xmlReturned = true; + return; + } + 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]); + } + } + + initDerivedInfo(newstats); + var oldstats = stats; + while(drawing) {} + stats = newstats; + delete oldstats; + xmlReturned = true; +} + +// set max and average +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 = s; + } + } + 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; +} + +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(serverStats) { + var extra = '' + serverStats.ip + ''; + 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 + '
\n'; + extra = extra + '  ' + s + ': ' + serverStats[s] + ''; + j++; + } + extra = extra + ' (' + serverStats.maxStat + ')'; + return extra; +} + +// reload xml +function getXML() { + if (xmlReturned == true) { + xmlReturned = false; + xmlhttp.open('POST',jsonurl,true); + xmlhttp.send(); + } +} + +// redraw +function drawDots() { + requestAnimFrame(drawDots); + + 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; + 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 + dots[i].size = maxDotRadius; + } else if (server[speedStatType]<=0) { + // if not changing size, increase to max radius + 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 (dots[i].growing) { + dots[i].size = dots[i].size + sizeChange; + if (dots[i].size + sizeChange > maxDotRadius) { + dots[i].growing = false; + } + } + else { + dots[i].size = dots[i].size - sizeChange; + if (dots[i].size - sizeChange < minDotRadius) { + dots[i].growing = true; + } + } + } + drawDot(x,y,Math.floor(dots[i].size),getColor(getStat(i,colorStatType))); + } + // 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 (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); + } + } +} + +// fill a dot specified by indices into dot grid +function drawDot(i,j,r,c) { + 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); + else + fillSquare(x-r,y-r,(r-dotPadding)*2,c); +} + +// stroke a dot specified by indices into dot grid +function strokeDot(i,j,r,c) { + 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); + else + strokeSquare(x-r,y-r,(r-dotPadding)*2,c); +} + +function getStat(dotIndex,statIndex) { + return Math.min(1,stats.servers[dotIndex][statIndex]/maxStatValues[statIndex]); +} + +// translate color between 0 and maxObservedColor into an html color code +function getColor(normColor) { + return colorPalette[Math.round((colorPalette.length-1)*normColor)]; +} + +function strokeCircle(x,y,r,c) { + context.strokeStyle = c; + context.lineWidth = 2; + context.beginPath(); + context.arc(x,y,r,0,Math.PI*2,true); + context.closePath(); + context.stroke(); +} + +function fillCircle(x,y,r,c) { + context.fillStyle = c; + context.beginPath(); + context.arc(x,y,r,0,Math.PI*2,true); + context.closePath(); + context.fill(); +} + +function strokeSquare(x,y,d,c) { + context.strokeStyle = c; + context.lineWidth = 2; + context.strokeRect(x,y,d,d); +} + +function fillSquare(x,y,d,c) { + context.fillStyle = c; + context.fillRect(x,y,d,d); +} + +// callback for shape selection +function setShape(obj) { + switch (obj.selectedIndex) { + case 0: + useCircles = true; + break; + case 1: + useCircles = false; + break; + default: + useCircles = true; + } + drawGrid(); + setState(); +} + +// callback for size selection +function setSize(obj) { + switch (obj.selectedIndex) { + case 0: + dotSpacing = 5; + minDotRadius = 1; + break; + case 1: + dotSpacing = 10; + minDotRadius = 3; + break; + case 2: + dotSpacing = 20; + minDotRadius = 5; + break; + case 3: + dotSpacing = 40; + minDotRadius = 7; + break; + default: + dotSpacing = 10; + minDotRadius = 3; + } + maxDotRadius = dotSpacing - dotPadding; + drawGrid(); + setState(); +} + +// callback for motion selection +function setMotion(obj) { + var i = 0; + for (var s in statNames) { + if (i==obj.selectedIndex) { + speedStatType = s; + break; + } + i++; + } + setState(); +} + +// callback for color selection +function setColor(obj) { + var i = 0; + for (var s in statNames) { + if (i==obj.selectedIndex) { + colorStatType = s; + break; + } + i++; + } + setState(); +} + +// hide server info on mouseout +function hideId(e) { + document.getElementById('vishoverinfo').style.visibility='hidden'; +} + +// display server info on mouseover +function showId(e) { + var x; + var y; + if (e.pageX || e.pageY) { + x = e.pageX + main.scrollLeft; + y = e.pageY + main.scrollTop; + } + else { + // clientX and clientY unimplemented + return; + } + var relx = x - canvas.offsetLeft - main.offsetLeft; + var rely = y - canvas.offsetTop - main.offsetTop; + 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'; + } + else { + document.getElementById('vishoverinfo').style.visibility='hidden'; + } +} + +function setState() { + 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) { + // 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() { + drawGrid(); + drawDots(); + getXML(); +} + Propchange: accumulo/trunk/server/src/main/resources/web/vis.js ------------------------------------------------------------------------------ svn:eol-style = native